From d2aaba282041d6d372521164da6f52a24e15dfcd Mon Sep 17 00:00:00 2001 From: Matthew Nesbit Date: Mon, 19 Jun 2017 17:30:11 +0100 Subject: [PATCH] Java accessible API for merkle trees Respond to PR comment --- .../core/transactions/MerkleTransaction.kt | 4 +++- .../corda/core/transactions/WireTransaction.kt | 17 +++++++++-------- .../main/kotlin/net/corda/flows/NotaryFlow.kt | 3 ++- .../corda/core/crypto/PartialMerkleTreeTest.kt | 5 +++-- .../kotlin/net/corda/irs/flows/RatesFixFlow.kt | 3 ++- .../corda/irs/testing/NodeInterestRatesTest.kt | 13 +++++++------ 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/core/src/main/kotlin/net/corda/core/transactions/MerkleTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/MerkleTransaction.kt index 8ef6fba2e9..0e611fb242 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/MerkleTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/MerkleTransaction.kt @@ -11,6 +11,7 @@ import net.corda.core.serialization.p2PKryo import net.corda.core.serialization.serialize import net.corda.core.serialization.withoutReferences import java.security.PublicKey +import java.util.function.Predicate fun serializedHash(x: T): SecureHash { return p2PKryo().run { kryo -> kryo.withoutReferences { x.serialize(kryo).hash } } @@ -116,8 +117,9 @@ class FilteredTransaction private constructor( * @param wtx WireTransaction to be filtered. * @param filtering filtering over the whole WireTransaction */ + @JvmStatic fun buildMerkleTransaction(wtx: WireTransaction, - filtering: (Any) -> Boolean + filtering: Predicate ): FilteredTransaction { val filteredLeaves = wtx.filterWithFun(filtering) val merkleTree = wtx.merkleTree diff --git a/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt index a02ac8d1d9..ecc2c58be9 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt @@ -13,6 +13,7 @@ import net.corda.core.serialization.p2PKryo import net.corda.core.serialization.serialize import net.corda.core.utilities.Emoji import java.security.PublicKey +import java.util.function.Predicate /** * A transaction ready for serialisation, without any signatures attached. A WireTransaction is usually wrapped @@ -106,7 +107,7 @@ class WireTransaction( /** * Build filtered transaction using provided filtering functions. */ - fun buildFilteredTransaction(filtering: (Any) -> Boolean): FilteredTransaction { + fun buildFilteredTransaction(filtering: Predicate): FilteredTransaction { return FilteredTransaction.buildMerkleTransaction(this, filtering) } @@ -120,15 +121,15 @@ class WireTransaction( * @param filtering filtering over the whole WireTransaction * @returns FilteredLeaves used in PartialMerkleTree calculation and verification. */ - fun filterWithFun(filtering: (Any) -> Boolean): FilteredLeaves { - fun notNullFalse(elem: Any?): Any? = if (elem == null || !filtering(elem)) null else elem + fun filterWithFun(filtering: Predicate): FilteredLeaves { + fun notNullFalse(elem: Any?): Any? = if (elem == null || !filtering.test(elem)) null else elem return FilteredLeaves( - inputs.filter { filtering(it) }, - attachments.filter { filtering(it) }, - outputs.filter { filtering(it) }, - commands.filter { filtering(it) }, + inputs.filter { filtering.test(it) }, + attachments.filter { filtering.test(it) }, + outputs.filter { filtering.test(it) }, + commands.filter { filtering.test(it) }, notNullFalse(notary) as Party?, - mustSign.filter { filtering(it) }, + mustSign.filter { filtering.test(it) }, notNullFalse(type) as TransactionType?, notNullFalse(timeWindow) as TimeWindow? ) diff --git a/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt b/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt index 3c67bb35e3..a12770ca1f 100644 --- a/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt @@ -19,6 +19,7 @@ import net.corda.core.serialization.serialize import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.unwrap +import java.util.function.Predicate object NotaryFlow { /** @@ -63,7 +64,7 @@ object NotaryFlow { val payload: Any = if (serviceHub.networkMapCache.isValidatingNotary(notaryParty)) { stx } else { - wtx.buildFilteredTransaction { it is StateRef || it is TimeWindow } + wtx.buildFilteredTransaction(Predicate { it is StateRef || it is TimeWindow }) } val response = try { diff --git a/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt b/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt index 93baa88cec..2452fc8466 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt @@ -15,6 +15,7 @@ import net.corda.core.utilities.TEST_TX_TIME import net.corda.testing.* import org.junit.Test import java.security.PublicKey +import java.util.function.Predicate import kotlin.test.* class PartialMerkleTreeTest { @@ -104,7 +105,7 @@ class PartialMerkleTreeTest { } } - val mt = testTx.buildFilteredTransaction(::filtering) + val mt = testTx.buildFilteredTransaction(Predicate(::filtering)) val leaves = mt.filteredLeaves val d = WireTransaction.deserialize(testTx.serialized) assertEquals(testTx.id, d.id) @@ -128,7 +129,7 @@ class PartialMerkleTreeTest { @Test fun `nothing filtered`() { - val mt = testTx.buildFilteredTransaction({ false }) + val mt = testTx.buildFilteredTransaction(Predicate { false }) assertTrue(mt.filteredLeaves.attachments.isEmpty()) assertTrue(mt.filteredLeaves.commands.isEmpty()) assertTrue(mt.filteredLeaves.inputs.isEmpty()) diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/RatesFixFlow.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/RatesFixFlow.kt index 211422bc66..c708c4e4af 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/RatesFixFlow.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/RatesFixFlow.kt @@ -17,6 +17,7 @@ import net.corda.irs.utilities.suggestInterestRateAnnouncementTimeWindow import java.math.BigDecimal import java.time.Instant import java.util.* +import java.util.function.Predicate // This code is unit tested in NodeInterestRates.kt @@ -62,7 +63,7 @@ open class RatesFixFlow(protected val tx: TransactionBuilder, tx.addCommand(fix, oracle.owningKey) beforeSigning(fix) progressTracker.currentStep = SIGNING - val mtx = tx.toWireTransaction().buildFilteredTransaction({ filtering(it) }) + val mtx = tx.toWireTransaction().buildFilteredTransaction(Predicate { filtering(it) }) val signature = subFlow(FixSignFlow(tx, oracle, mtx)) tx.addSignatureUnchecked(signature) } diff --git a/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt b/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt index 6359767547..f8ac8ea194 100644 --- a/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt +++ b/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt @@ -36,6 +36,7 @@ import org.junit.Before import org.junit.Test import java.io.Closeable import java.math.BigDecimal +import java.util.function.Predicate import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertFalse @@ -142,11 +143,11 @@ class NodeInterestRatesTest { } } - val ftx1 = wtx1.buildFilteredTransaction(::filterAllOutputs) + val ftx1 = wtx1.buildFilteredTransaction(Predicate(::filterAllOutputs)) assertFailsWith { oracle.sign(ftx1) } tx.addCommand(Cash.Commands.Move(), ALICE_PUBKEY) val wtx2 = tx.toWireTransaction() - val ftx2 = wtx2.buildFilteredTransaction { x -> filterCmds(x) } + val ftx2 = wtx2.buildFilteredTransaction(Predicate { x -> filterCmds(x) }) assertFalse(wtx1.id == wtx2.id) assertFailsWith { oracle.sign(ftx2) } } @@ -160,7 +161,7 @@ class NodeInterestRatesTest { tx.addCommand(fix, oracle.identity.owningKey) // Sign successfully. val wtx = tx.toWireTransaction() - val ftx = wtx.buildFilteredTransaction { x -> fixCmdFilter(x) } + val ftx = wtx.buildFilteredTransaction(Predicate { x -> fixCmdFilter(x) }) val signature = oracle.sign(ftx) tx.checkAndAddSignature(signature) } @@ -174,7 +175,7 @@ class NodeInterestRatesTest { val badFix = Fix(fixOf, "0.6789".bd) tx.addCommand(badFix, oracle.identity.owningKey) val wtx = tx.toWireTransaction() - val ftx = wtx.buildFilteredTransaction { x -> fixCmdFilter(x) } + val ftx = wtx.buildFilteredTransaction(Predicate { x -> fixCmdFilter(x) }) val e1 = assertFailsWith { oracle.sign(ftx) } assertEquals(fixOf, e1.fix) } @@ -194,7 +195,7 @@ class NodeInterestRatesTest { } tx.addCommand(fix, oracle.identity.owningKey) val wtx = tx.toWireTransaction() - val ftx = wtx.buildFilteredTransaction(::filtering) + val ftx = wtx.buildFilteredTransaction(Predicate(::filtering)) assertFailsWith { oracle.sign(ftx) } } } @@ -203,7 +204,7 @@ class NodeInterestRatesTest { fun `empty partial transaction to sign`() { val tx = makeTX() val wtx = tx.toWireTransaction() - val ftx = wtx.buildFilteredTransaction({ false }) + val ftx = wtx.buildFilteredTransaction(Predicate { false }) assertFailsWith { oracle.sign(ftx) } }