From 21b4ab0c26c672238279f0cd6a63091ce5c0b263 Mon Sep 17 00:00:00 2001 From: Katarzyna Streich Date: Tue, 8 Nov 2016 17:45:28 +0000 Subject: [PATCH] Add transaction tear-offs documentation. --- docs/source/index.rst | 1 + docs/source/merkle-trees.rst | 111 ++++++++++++++++++++++++ docs/source/resources/merkleTree.png | Bin 0 -> 15642 bytes docs/source/resources/partialMerkle.png | Bin 0 -> 8741 bytes 4 files changed, 112 insertions(+) create mode 100644 docs/source/merkle-trees.rst create mode 100644 docs/source/resources/merkleTree.png create mode 100644 docs/source/resources/partialMerkle.png diff --git a/docs/source/index.rst b/docs/source/index.rst index b10f28379c..ca54315def 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -28,6 +28,7 @@ Read on to learn: getting-set-up data-model transaction-data-types + merkle-trees consensus messaging persistence diff --git a/docs/source/merkle-trees.rst b/docs/source/merkle-trees.rst new file mode 100644 index 0000000000..1b30b68df3 --- /dev/null +++ b/docs/source/merkle-trees.rst @@ -0,0 +1,111 @@ +Transaction Tear-offs +====================== + +One of the basic data structures in our platform is a transaction. It can be passed around to be signed and verified, +also by third parties. The construction of transactions assumes that they form a whole entity with input and output states, +commands and attachments inside. However all sensitive data shouldn’t be revealed to other nodes that take part in +the creation of transaction on validation level (a good example of this situation is the Oracle which validates only +embedded commands). How to achive it in a way that convinces the other party the data they got for signing really did form +a part of the transaction? + +We decided to use well known and described cryptographic scheme to provide proofs of inclusion and data integrity. +Merkle trees are widely used in peer-to-peer networks, blockchain systems and git. +You can read more on the concept `here `_. + +Merkle trees in Corda +---------------------- + +Transactions are split into leaves, each of them contains either input, output, command or attachment. Other fields like +timestamp or signers are not used in the calculation. +Next, the Merkle tree is built in the normal way by hashing the concatenation +of nodes’ hashes below the current one together. It’s visible on the example image below, where ``H`` denotes sha256 function, +"+" - concatenation. + +.. image:: resources/merkleTree.png + +The transaction has one input state, one output and three commands. If a tree is not a full binary tree, the rightmost nodes are +duplicated in hash calculation (dotted lines). + +Finally, the hash of the root is the identifier of the transaction, it's also used for signing and verification of data integrity. +Every change in transaction on a leaf level will change its identifier. + +Hiding data +----------- + +Hiding data and providing the proof that it formed a part of a transaction is done by constructing Partial Merkle Trees +(or Merkle branches). A Merkle branch is a set of hashes, that given the leaves’ data, is used to calculate the root’s hash. +Then that hash is compared with the hash of a whole transaction and if they match it means that data we obtained belongs +to that particular transaction. + +.. image:: resources/partialMerkle.png + +In the example above, the red node is the one holding data for signing Oracle service. Blue nodes' hashes form the Partial Merkle +Tree, dotted ones are not included. Having the command that should be in a red node place and branch we are able to calculate +root of this tree and compare it with original transaction identifier - we have a proof that this command belongs to this transaction. + +Example of usage +----------------- + +Let’s focus on a code example. We want to construct a transaction with commands containing interest rate fix data as in: +:doc:`oracles`. +After construction of a partial transaction, with included ``Fix`` commands in it, we want to send it to the Oracle for checking +and signing. To do so we need to specify which parts of the transaction are going to be revealed. That can be done by constructing +filtering functions for inputs, outputs, attachments and commands separately. If a function is not provided by default none +of the elements from this group will be included in a Partial Merkle Tree. + +.. container:: codeset + + .. sourcecode:: kotlin + + val partialTx = ... + val oracle: Party = ... + fun filterCommands(c: Command) = oracle.owningKey in c.signers && c.value is Fix + val filterFuns = FilterFuns(filterCommands = ::filterCommands) + +Assuming that we already assembled partialTx with some commands and know the identity of Oracle service, +we pass filtering function over commands - ``filterCommands`` to ``FilterFuns``. It filters only +commands of type ``Fix`` as in IRSDemo example. Then we can construct ``FilteredTransaction``: + +.. container:: codeset + + .. sourcecode:: kotlin + + val wtx: WireTransaction = partialTx.toWireTransaction() + val ftx = FilteredTransaction.buildMerkleTransaction(wtx, filterFuns) + +In the Oracle example this step takes place in ``RatesFixProtocol``: + +.. container:: codeset + + .. sourcecode:: kotlin + + val protocol = RatesFixProtocol(partialTx, filterFuns, oracle, fixOf, "0.675".bd, "0.1".bd) + +``FilteredTransaction`` holds ``filteredLeaves`` (data that we wanted to reveal) and Merkle branch for them. + +.. container:: codeset + + .. sourcecode:: kotlin + + // Getting included commands, inputs, outputs, attachments. + val cmds: List = ftx.filteredLeaves.commands + val ins: List = ftx.filteredLeaves.inputs + val outs: List> = ftx.filteredLeaves.outputs + val attchs: List = ftx.filteredLeaves.attachments + + +If you want to verify obtained ``FilteredTransaction`` all you need is the root hash of the full transaction: + +.. container:: codeset + + .. sourcecode:: kotlin + + if (!ftx.verify(merkleRoot)){ + throw MerkleTreeException("Rate Fix Oracle: Couldn't verify partial Merkle tree.") + } + + +.. note:: The way the ``FilteredTransaction`` is constructed ensures that after signing of the root hash it's impossible to add or remove + leaves. However, it can happen that having transaction with multiple commands one party reveals only subset of them to the Oracle. + As signing is done now over the merkle root hash, the service signs all commands of given type, even though it didn't see + all of them. This issue will be handled after implementing partial signatures. diff --git a/docs/source/resources/merkleTree.png b/docs/source/resources/merkleTree.png new file mode 100644 index 0000000000000000000000000000000000000000..696f5104504ca964273dab39a890452d8a7c4c6f GIT binary patch literal 15642 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 SyBqw3cqIK)sz^fD>wf?-Ose|; literal 0 HcmV?d00001 diff --git a/docs/source/resources/partialMerkle.png b/docs/source/resources/partialMerkle.png new file mode 100644 index 0000000000000000000000000000000000000000..a2c5af7a2350d95224f4cb838e6d9e1696e304bc GIT binary patch literal 8741 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 -p{zW38ITE@*aRW8)m)3V$d46&T70 zK~FMS79(1K4ql+Pw{Wj*f4r)QTFJsRyYvlOO7B32*~(tRU5Un_&hK!egAq`~Unv+V zRiNK*I-C#Tg7e!h69N-ijD50*|3_VlcEx4ImdB_8iveXJ8keO4dOex0&GeWlkSZf_ z$A{}NlsaH?Sr)reFpTu{ExXf^BmDUy<^AFPnT96b9!fNfDm%k}S0^!2P8Spv!vU>2 zb3R1mpumTLa7{dfx8QZ#L?GZ0K!R3!tSB%4HgeZ*{vW^QCjJZA1+cn85zG}Oi)e7} zoDe>sh_4qMA1wJtZ|9x-j#M?PSjY$UXEw@dlv*F~_)a(Polw4&XH_R^0bp}pL98K6 zm0g;cE$M9!ir3mp#4~TdRet@zt$wB@?`!X5rjJBh^+|TwHirBplgW-@-&jj-KGtq= zI^HfgK4}3672F3i)Q5-Q;9WoYOM)9t8XL26b}o3D9xXMWLUrN5UXL+vif5$FU3xqQ z?5t>V2iVmc9c_oJ{v9P=Z;$V&_MX{NAccPknB-veec*g2WTySrInTib+u6zL%UUN* zv8tj|SC^-?*v9pz6EIF`q?(X@H)fAMR$ef*ZAl2iTy^nTMFkI{Z~yo zDy$iZHR2xMsV$YJLp-g0hA=xOx2dwnE~?$OQFEX#R9Z(HCnY&DR9$lB^LTS!+-0tw zTX9{Ky2p;I4Q;$97XLVE>|%<1;>QNH_c#wrXU7%JT=pf$#TiAqyT-UXo>R1wrGGLK zWv1OKR6Dc2sdIPRt;Nm`q6!;!bkAqBEll(K`(TKzOqLS7%&J-LVo?ZZ7(HYJt3LRTlRr`S8;uG?0x0=b;I9UWJVKe zc_Nw5=GjnO-^D5&r!Bri4cDhPrp*STwX2l#y=@3xjiXFSVP(JTxjkA9Uj zbKlo)VzY>Yf4r}h_xxYD&?nIny$9jJ`CchymhO3{HNvE7^cLNR(ngE+$Pb#weN-qa zxg9vA>J_DT>pFf4Ez?K~Rc3BWa#|%~dvypJav@VJ^X8#2LlPP@r9sfhj{kur&_#hG pQU+YYAZUyH=LPuSL;dzKC6-RqtXa-H7ks4v8R(d5ztnUg{6B!v`R4!t literal 0 HcmV?d00001