Refer to "Entity Configuration" below for general notes on privacy configurations. This demo requires that there be 4 entities configured by the genconfs
tool, which will name them "Alice", "Bob", "Carol" and "Dinesh". These would correspond to business entities on the blockchain, communicating with private messages over the blockchain. Confirm this setup with the server
command.
Launch the cluster, and load the demo.yaml file.
node3> load demo/demo.yaml
status: success
data: TableCreated
Setting batch command to: (demo.transfer "Acct1" "Acct2" 1.00)
Create the private accounts by sending a private message that executes a multi-step pact to create private accounts on each entity. Change to Alice's server (node0) and send a private message to the other 3 participants with the demo code:
node3> server node0
node0> private Alice [Bob Carol Dinesh] (demo.create-private-accounts)
The private
command creates an encrypted message, sent from Alice to Bob, Carol and Dinesh. The create-private-accounts
pact executes a single command on the different servers. To see the results, perform local queries on each node.
node0> local (demo.read-all)
account | amount | balance | data
-------------------------------------------------
"A" | "1000.0" | "1000.0" | "Created account"
node0> server node1
node1> local (demo.read-all)
account | amount | balance | data
-------------------------------------------------
"B" | "1000.0" | "1000.0" | "Created account"
node1> server node2
node2> local (demo.read-all)
account | amount | balance | data
-------------------------------------------------
"C" | "1000.0" | "1000.0" | "Created account"
node2> server node3
node3> local (demo.read-all)
account | amount | balance | data
-------------------------------------------------
"D" | "1000.0" | "1000.0" | "Created account"
This illustrates how the different servers (which would be presumably behind firewalls, etc) contain different, private data.
Now, execute a confidential transfer between Alice and Bob, transfering money from Alice's account "A" to Bob's account "B".
For this, the pact "payment" is used, which executes the debit step on the "source" entity, and the credit step on the "dest" entity. You can see the function docs by simply executing payment
:
node3> local demo.payment
status: success
data: (TDef defpact demo.payment (src-entity:<i> src:<j> dest-entity:<k> dest:<l>
amount:<m> -> <n>) "Two-phase confidential payment, sending money from SRC at SRC-ENTITY
to DEST at DEST-ENTITY.")
Set the server to node0 for Alice, and execute the pact to send 1.00 to Bob:
node3> server node0
node0> private Alice [Bob] (demo.payment "Alice" "A" "Bob" "B" 1.00)
status: success
data:
amount: '1.00'
result: Write succeeded
To see the results, issue local queries on the nodes. Note that node2 and node 3 are unchanged:
node0> local (demo.read-all)
account | amount | balance | data
----------------------------------------------------------------------------
"A" | "-1.00" | "999.00" | {"tx":5,"transfer-to":"B","message":"Starting pact"}
node0> server node1
node1> local (demo.read-all)
account | amount | balance | data
-------------------------------------------------------------------------------------
"B" | "1.00" | "1001.00" | {"tx":5,"debit-result":"Write succeeded","transfer-from":"A"}
node1> server node2
node2> local (demo.read-all)
account | amount | balance | data
-------------------------------------------------
"C" | "1000.0" | "1000.0" | "Created account"
node2> server node3
node3> local (demo.read-all)
account | amount | balance | data
-------------------------------------------------
"D" | "1000.0" | "1000.0" | "Created account"
You can also test out the rollback functionality on an error. Mistype the recipient account id (in this case we use "bad" instead of "B"). The pact will execute the debit on Alice/node0; attempt the credit on Bob/node1, failing because of the bad ID; finally the rollback will execute on Alice/node0. Bob's account will be unchanged, while Alice's account will note the rollback with the original tx id of the pact execution.
node0> private Alice [Bob] (demo.payment "Alice" "A" "Bob" "bad" 1.00)
status: success
data:
tx: 7
amount: '1.00'
result: Write succeeded
node0> local (demo.read-all)
account | amount | balance | data
--------------------------------------------
"A" | "1.00" | "999.00" | {"rollback":7}
node0> server node1
node1> local (demo.read-all)
account | amount | balance | data
--------------------------------------------------------------------------------------------
"B" | "1.00" | "1001.00" | {"tx":5,"debit-result":"Write succeeded","transfer-from":"A"}
NB: The result of the first send shows you the result of the first part of the multi-phase tx, thus the "success"/"Write succeeded" status. Querying the database reveals the rollback which occurred two transactions later.