Include Merkle tree root hash in FilteredTransaction

Remove no longer needed test. Make FilteredTransaction constructor private
This commit is contained in:
Andrius Dagys 2017-02-09 14:55:02 +00:00 committed by Chris Rankin
parent 680bf8e462
commit 04e41b5ed4
5 changed files with 24 additions and 37 deletions

View File

@ -80,10 +80,12 @@ class FilteredLeaves(
/**
* Class representing merkleized filtered transaction.
* @param rootHash Merkle tree root hash.
* @param filteredLeaves Leaves included in a filtered transaction.
* @param partialMerkleTree Merkle branch needed to verify filteredLeaves.
*/
class FilteredTransaction(
class FilteredTransaction private constructor(
val rootHash: SecureHash,
val filteredLeaves: FilteredLeaves,
val partialMerkleTree: PartialMerkleTree
) {
@ -99,26 +101,26 @@ class FilteredTransaction(
val filteredLeaves = wtx.filterWithFun(filtering)
val merkleTree = wtx.getMerkleTree()
val pmt = PartialMerkleTree.build(merkleTree, filteredLeaves.calculateLeavesHashes())
return FilteredTransaction(filteredLeaves, pmt)
return FilteredTransaction(merkleTree.hash, filteredLeaves, pmt)
}
}
/**
* Runs verification of Partial Merkle Branch with merkleRootHash.
* Runs verification of Partial Merkle Branch against [rootHash].
*/
@Throws(MerkleTreeException::class)
fun verify(merkleRootHash: SecureHash): Boolean {
fun verify(): Boolean {
val hashes: List<SecureHash> = filteredLeaves.calculateLeavesHashes()
if (hashes.isEmpty())
throw MerkleTreeException("Transaction without included leaves.")
return partialMerkleTree.verify(merkleRootHash, hashes)
return partialMerkleTree.verify(rootHash, hashes)
}
/**
* Runs verification of Partial Merkle Branch with merkleRootHash. Checks filteredLeaves with provided checkingFun.
* Runs verification of Partial Merkle Branch against [rootHash]. Checks filteredLeaves with provided checkingFun.
*/
@Throws(MerkleTreeException::class)
fun verifyWithFunction(merkleRootHash: SecureHash, checkingFun: (Any) -> Boolean): Boolean {
return verify(merkleRootHash) && filteredLeaves.checkWithFun { checkingFun(it) }
fun verifyWithFunction(checkingFun: (Any) -> Boolean): Boolean {
return verify() && filteredLeaves.checkWithFun { checkingFun(it) }
}
}

View File

@ -113,7 +113,7 @@ class PartialMerkleTreeTest {
assertTrue(mt.filteredLeaves.timestamp != null)
assertEquals(null, mt.filteredLeaves.type)
assertEquals(null, mt.filteredLeaves.notary)
assert(mt.verify(testTx.id))
assert(mt.verify())
}
@Test
@ -131,7 +131,7 @@ class PartialMerkleTreeTest {
assertTrue(mt.filteredLeaves.inputs.isEmpty())
assertTrue(mt.filteredLeaves.outputs.isEmpty())
assertTrue(mt.filteredLeaves.timestamp == null)
assertFailsWith<MerkleTreeException> { mt.verify(testTx.id) }
assertFailsWith<MerkleTreeException> { mt.verify() }
}
// Partial Merkle Tree building tests

View File

@ -79,7 +79,7 @@ object NodeInterestRates {
@Suspendable
override fun call() {
val request = receive<RatesFixFlow.SignRequest>(otherParty).unwrap { it }
send(otherParty, service.oracle.sign(request.ftx, request.rootHash))
send(otherParty, service.oracle.sign(request.ftx))
}
}
@ -189,8 +189,8 @@ object NodeInterestRates {
// Oracle gets signing request for only some of them with a valid partial tree? We sign over a whole transaction.
// It will be fixed by adding partial signatures later.
// DOCSTART 1
fun sign(ftx: FilteredTransaction, merkleRoot: SecureHash): DigitalSignature.LegallyIdentifiable {
if (!ftx.verify(merkleRoot)) {
fun sign(ftx: FilteredTransaction): DigitalSignature.LegallyIdentifiable {
if (!ftx.verify()) {
throw MerkleTreeException("Rate Fix Oracle: Couldn't verify partial Merkle tree.")
}
// Performing validation of obtained FilteredLeaves.
@ -219,7 +219,7 @@ object NodeInterestRates {
// Note that we will happily sign an invalid transaction, as we are only being presented with a filtered
// version so we can't resolve or check it ourselves. However, that doesn't matter much, as if we sign
// an invalid transaction the signature is worthless.
return signingKey.signWithECDSA(merkleRoot.bytes, identity)
return signingKey.signWithECDSA(ftx.rootHash.bytes, identity)
}
// DOCEND 1
}

View File

@ -45,7 +45,7 @@ open class RatesFixFlow(protected val tx: TransactionBuilder,
class FixOutOfRange(@Suppress("unused") val byAmount: BigDecimal) : Exception("Fix out of range by $byAmount")
data class QueryRequest(val queries: List<FixOf>, val deadline: Instant)
data class SignRequest(val rootHash: SecureHash, val ftx: FilteredTransaction)
data class SignRequest(val ftx: FilteredTransaction)
// DOCSTART 2
@Suspendable
@ -109,9 +109,7 @@ open class RatesFixFlow(protected val tx: TransactionBuilder,
val partialMerkleTx: FilteredTransaction) : FlowLogic<DigitalSignature.LegallyIdentifiable>() {
@Suspendable
override fun call(): DigitalSignature.LegallyIdentifiable {
val wtx = tx.toWireTransaction()
val rootHash = wtx.id
val resp = sendAndReceive<DigitalSignature.LegallyIdentifiable>(oracle, SignRequest(rootHash, partialMerkleTx))
val resp = sendAndReceive<DigitalSignature.LegallyIdentifiable>(oracle, SignRequest(partialMerkleTx))
return resp.unwrap { sig ->
check(sig.signer == oracle)
tx.checkSignature(sig)

View File

@ -137,12 +137,12 @@ class NodeInterestRatesTest {
}
}
val ftx1 = wtx1.buildFilteredTransaction(::filterAllOutputs)
assertFailsWith<IllegalArgumentException> { oracle.sign(ftx1, wtx1.id) }
assertFailsWith<IllegalArgumentException> { oracle.sign(ftx1) }
tx.addCommand(Cash.Commands.Move(), ALICE_PUBKEY)
val wtx2 = tx.toWireTransaction()
val ftx2 = wtx2.buildFilteredTransaction { x -> filterCmds(x) }
assertFalse(wtx1.id == wtx2.id)
assertFailsWith<IllegalArgumentException> { oracle.sign(ftx2, wtx2.id) }
assertFailsWith<IllegalArgumentException> { oracle.sign(ftx2) }
}
}
@ -155,7 +155,7 @@ class NodeInterestRatesTest {
// Sign successfully.
val wtx = tx.toWireTransaction()
val ftx = wtx.buildFilteredTransaction { x -> fixCmdFilter(x) }
val signature = oracle.sign(ftx, wtx.id)
val signature = oracle.sign(ftx)
tx.checkAndAddSignature(signature)
}
}
@ -169,7 +169,7 @@ class NodeInterestRatesTest {
tx.addCommand(badFix, oracle.identity.owningKey)
val wtx = tx.toWireTransaction()
val ftx = wtx.buildFilteredTransaction { x -> fixCmdFilter(x) }
val e1 = assertFailsWith<NodeInterestRates.UnknownFix> { oracle.sign(ftx, wtx.id) }
val e1 = assertFailsWith<NodeInterestRates.UnknownFix> { oracle.sign(ftx) }
assertEquals(fixOf, e1.fix)
}
}
@ -189,7 +189,7 @@ class NodeInterestRatesTest {
tx.addCommand(fix, oracle.identity.owningKey)
val wtx = tx.toWireTransaction()
val ftx = wtx.buildFilteredTransaction(::filtering)
assertFailsWith<IllegalArgumentException> { oracle.sign(ftx, wtx.id) }
assertFailsWith<IllegalArgumentException> { oracle.sign(ftx) }
}
}
@ -198,20 +198,7 @@ class NodeInterestRatesTest {
val tx = makeTX()
val wtx = tx.toWireTransaction()
val ftx = wtx.buildFilteredTransaction({ false })
assertFailsWith<MerkleTreeException> { oracle.sign(ftx, wtx.id) }
}
@Test
fun `partial tree verification exception`() {
databaseTransaction(database) {
val tx = makeTX()
val wtx1 = tx.toWireTransaction()
tx.addCommand(Cash.Commands.Move(), ALICE_PUBKEY)
val wtx2 = tx.toWireTransaction()
val ftx2 = wtx2.buildFilteredTransaction { x -> filterCmds(x) }
assertFalse(wtx1.id == wtx2.id)
assertFailsWith<MerkleTreeException> { oracle.sign(ftx2, wtx1.id) }
}
assertFailsWith<MerkleTreeException> { oracle.sign(ftx) }
}
@Test