mirror of
https://github.com/corda/corda.git
synced 2025-01-18 10:46:38 +00:00
Style changes.
This commit is contained in:
parent
a5dfaa255d
commit
023ba380a0
@ -11,7 +11,7 @@ class MerkleTreeException(val reason: String): Exception() {
|
||||
|
||||
/**
|
||||
* Building and verification of Partial Merkle Tree.
|
||||
* Partial Merkle Tree is a minimal tree needed to check that given set of leaves belongs to a full Merkle Tree.
|
||||
* Partial Merkle Tree is a minimal tree needed to check that a given set of leaves belongs to a full Merkle Tree.
|
||||
*
|
||||
* Example of Merkle tree with 5 leaves.
|
||||
*
|
||||
@ -24,8 +24,8 @@ class MerkleTreeException(val reason: String): Exception() {
|
||||
* l1 l2 l3 l4 l5->d(l5)
|
||||
*
|
||||
* l* denote hashes of leaves, h* - hashes of nodes below.
|
||||
* h5->d(h5) denotes duplication of left hand side node. These nodes are kept in a full tree as DuplicatedLeaf.
|
||||
* When filtering the tree for l5, we don't want to keep both l5 and it's duplicate (it can also be solved using null
|
||||
* h5->d(h5) denotes duplication of the left hand side node. These nodes are kept in a full tree as DuplicatedLeaf.
|
||||
* When filtering the tree for l5, we don't want to keep both l5 and its duplicate (it can also be solved using null
|
||||
* values in a tree, but this solution is clearer).
|
||||
*
|
||||
* Example of Partial tree based on the tree above.
|
||||
@ -87,28 +87,26 @@ class PartialMerkleTree(val root: PartialTree) {
|
||||
includeHashes: List<SecureHash>,
|
||||
usedHashes: MutableList<SecureHash>
|
||||
): Pair<Boolean, PartialTree> {
|
||||
if (root is MerkleTree.Leaf) {
|
||||
if (root.value in includeHashes) {
|
||||
usedHashes.add(root.value)
|
||||
return Pair(true, PartialTree.IncludedLeaf(root.value))
|
||||
} else return Pair(false, PartialTree.Leaf(root.value))
|
||||
} else if (root is MerkleTree.DuplicatedLeaf) {
|
||||
//Duplicate leaves should be stored as normal leaves not included ones.
|
||||
return Pair(false, PartialTree.Leaf(root.value))
|
||||
} else if (root is MerkleTree.Node) {
|
||||
val leftNode = buildPartialTree(root.left, includeHashes, usedHashes)
|
||||
val rightNode = buildPartialTree(root.right, includeHashes, usedHashes)
|
||||
if (leftNode.first or rightNode.first) {
|
||||
//This node is on a path to some included leaves. Don't store hash.
|
||||
val newTree = PartialTree.Node(leftNode.second, rightNode.second)
|
||||
return Pair(true, newTree)
|
||||
} else {
|
||||
//This node has no included leaves below. Cut the tree here and store a hash as a Leaf.
|
||||
val newTree = PartialTree.Leaf(root.value)
|
||||
return Pair(false, newTree)
|
||||
return when (root) {
|
||||
is MerkleTree.Leaf ->
|
||||
if (root.value in includeHashes) {
|
||||
usedHashes.add(root.value)
|
||||
Pair(true, PartialTree.IncludedLeaf(root.value))
|
||||
} else Pair(false, PartialTree.Leaf(root.value))
|
||||
is MerkleTree.DuplicatedLeaf -> Pair(false, PartialTree.Leaf(root.value))
|
||||
is MerkleTree.Node -> {
|
||||
val leftNode = buildPartialTree(root.left, includeHashes, usedHashes)
|
||||
val rightNode = buildPartialTree(root.right, includeHashes, usedHashes)
|
||||
if (leftNode.first or rightNode.first) {
|
||||
//This node is on a path to some included leaves. Don't store hash.
|
||||
val newTree = PartialTree.Node(leftNode.second, rightNode.second)
|
||||
return Pair(true, newTree)
|
||||
} else {
|
||||
//This node has no included leaves below. Cut the tree here and store a hash as a Leaf.
|
||||
val newTree = PartialTree.Leaf(root.value)
|
||||
return Pair(false, newTree)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw MerkleTreeException("Invalid MerkleTree.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -121,7 +119,7 @@ class PartialMerkleTree(val root: PartialTree) {
|
||||
val usedHashes = ArrayList<SecureHash>()
|
||||
val verifyRoot = verify(root, usedHashes)
|
||||
//It means that we obtained more/less hashes than needed or different sets of hashes.
|
||||
if(hashesToCheck.size != usedHashes.size || hashesToCheck.minus(usedHashes).isNotEmpty())
|
||||
if (hashesToCheck.groupBy { it } != usedHashes.groupBy { it })
|
||||
return false
|
||||
return (verifyRoot == merkleRootHash)
|
||||
}
|
||||
@ -130,18 +128,18 @@ class PartialMerkleTree(val root: PartialTree) {
|
||||
* Recursive calculation of root of this partial tree.
|
||||
* Modifies usedHashes to later check for inclusion with hashes provided.
|
||||
*/
|
||||
private fun verify(node: PartialTree, usedHashes: MutableList<SecureHash>): SecureHash{
|
||||
if (node is PartialTree.IncludedLeaf) {
|
||||
usedHashes.add(node.hash)
|
||||
return node.hash
|
||||
} else if (node is PartialTree.Leaf ) {
|
||||
return node.hash
|
||||
} else if (node is PartialTree.Node) {
|
||||
val leftHash = verify(node.left, usedHashes)
|
||||
val rightHash = verify(node.right, usedHashes)
|
||||
return leftHash.hashConcat(rightHash)
|
||||
} else {
|
||||
throw MerkleTreeException("Invalid node type.")
|
||||
private fun verify(node: PartialTree, usedHashes: MutableList<SecureHash>): SecureHash {
|
||||
return when (node) {
|
||||
is PartialTree.IncludedLeaf -> {
|
||||
usedHashes.add(node.hash)
|
||||
node.hash
|
||||
}
|
||||
is PartialTree.Leaf -> node.hash
|
||||
is PartialTree.Node -> {
|
||||
val leftHash = verify(node.left, usedHashes)
|
||||
val rightHash = verify(node.right, usedHashes)
|
||||
return leftHash.hashConcat(rightHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ sealed class MerkleTree(val hash: SecureHash) {
|
||||
val right = when {
|
||||
//If there is an odd number of elements at this level,
|
||||
//the last element is hashed with itself and stored as a Leaf.
|
||||
i+1 > n-1 -> MerkleTree.DuplicatedLeaf(lastNodesList[n-1].hash)
|
||||
i + 1 > n - 1 -> MerkleTree.DuplicatedLeaf(lastNodesList[n-1].hash)
|
||||
else -> lastNodesList[i+1]
|
||||
}
|
||||
val combined = left.hashNodes(right)
|
||||
@ -112,10 +112,12 @@ class FilteredLeaves(
|
||||
* Holds filter functions on transactions fields.
|
||||
* Functions are used to build a partial tree only out of some subset of original transaction fields.
|
||||
*/
|
||||
class FilterFuns(val filterInputs: (StateRef) -> Boolean = { false },
|
||||
val filterOutputs: (TransactionState<ContractState>) -> Boolean = { false },
|
||||
val filterAttachments: (SecureHash) -> Boolean = { false },
|
||||
val filterCommands: (Command) -> Boolean = { false }) {
|
||||
class FilterFuns(
|
||||
val filterInputs: (StateRef) -> Boolean = { false },
|
||||
val filterOutputs: (TransactionState<ContractState>) -> Boolean = { false },
|
||||
val filterAttachments: (SecureHash) -> Boolean = { false },
|
||||
val filterCommands: (Command) -> Boolean = { false }
|
||||
) {
|
||||
fun <T: Any> genericFilter(elem: T): Boolean {
|
||||
return when (elem) {
|
||||
is StateRef -> filterInputs(elem)
|
||||
|
@ -104,6 +104,14 @@ class PartialMerkleTreeTest {
|
||||
assertFailsWith<MerkleTreeException> { PartialMerkleTree.build(merkleTree, inclHashes) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `build Partial Merkle Tree - only duplicate leaves, less included failure`() {
|
||||
val leaves = "aaa"
|
||||
val hashes = leaves.map { it.serialize().hash }
|
||||
val mt = MerkleTree.getMerkleTree(hashes)
|
||||
assertFailsWith<MerkleTreeException> { PartialMerkleTree.build(mt, hashes.subList(0,1)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `verify Partial Merkle Tree - too many leaves failure`() {
|
||||
val inclHashes = arrayListOf(hashed[3], hashed[5])
|
||||
|
Loading…
Reference in New Issue
Block a user