Remove the SignedTransaction.id field, which took part in serialisation. Calculate it on demand instead.

This commit is contained in:
Mike Hearn 2017-02-18 16:14:41 +00:00
parent 0b33b52d1a
commit b8942a2cc9
7 changed files with 17 additions and 16 deletions

View File

@ -23,8 +23,7 @@ import java.util.*
* A transaction ID should be the hash of the [WireTransaction] Merkle tree root. Thus adding or removing a signature does not change it. * A transaction ID should be the hash of the [WireTransaction] Merkle tree root. Thus adding or removing a signature does not change it.
*/ */
data class SignedTransaction(val txBits: SerializedBytes<WireTransaction>, data class SignedTransaction(val txBits: SerializedBytes<WireTransaction>,
val sigs: List<DigitalSignature.WithKey>, val sigs: List<DigitalSignature.WithKey>
override val id: SecureHash
) : NamedByHash { ) : NamedByHash {
init { init {
require(sigs.isNotEmpty()) require(sigs.isNotEmpty())
@ -33,11 +32,14 @@ data class SignedTransaction(val txBits: SerializedBytes<WireTransaction>,
// TODO: This needs to be reworked to ensure that the inner WireTransaction is only ever deserialised sandboxed. // TODO: This needs to be reworked to ensure that the inner WireTransaction is only ever deserialised sandboxed.
/** Lazily calculated access to the deserialised/hashed transaction data. */ /** Lazily calculated access to the deserialised/hashed transaction data. */
val tx: WireTransaction by lazy { val tx: WireTransaction by lazy { WireTransaction.deserialize(txBits) }
val temp = WireTransaction.deserialize(txBits)
check(temp.id == id) { "Supplied transaction ID does not match deserialized transaction's ID - this is probably a problem in serialization/deserialization" } /**
temp * The Merkle root of the inner [WireTransaction]. Note that this is _not_ the same as the simple hash of
} * [txBits], which would not use the Merkle tree structure. If the difference isn't clear, please consult
* the user guide section "Transaction tear-offs" to learn more about Merkle trees.
*/
override val id: SecureHash get() = tx.id
class SignaturesMissingException(val missing: Set<CompositeKey>, val descriptions: List<String>, override val id: SecureHash) : NamedByHash, SignatureException() { class SignaturesMissingException(val missing: Set<CompositeKey>, val descriptions: List<String>, override val id: SecureHash) : NamedByHash, SignatureException() {
override fun toString(): String { override fun toString(): String {

View File

@ -137,7 +137,7 @@ open class TransactionBuilder(
throw IllegalStateException("Missing signatures on the transaction for the public keys: ${missing.joinToString()}") throw IllegalStateException("Missing signatures on the transaction for the public keys: ${missing.joinToString()}")
} }
val wtx = toWireTransaction() val wtx = toWireTransaction()
return SignedTransaction(wtx.serialize(), ArrayList(currentSigs), wtx.id) return SignedTransaction(wtx.serialize(), ArrayList(currentSigs))
} }
open fun addInputState(stateAndRef: StateAndRef<*>) { open fun addInputState(stateAndRef: StateAndRef<*>) {

View File

@ -35,7 +35,7 @@ class TransactionTests {
timestamp = null timestamp = null
) )
val bytes: SerializedBytes<WireTransaction> = wtx.serialized val bytes: SerializedBytes<WireTransaction> = wtx.serialized
fun make(vararg keys: KeyPair) = SignedTransaction(bytes, keys.map { it.signWithECDSA(wtx.id.bytes) }, wtx.id) fun make(vararg keys: KeyPair) = SignedTransaction(bytes, keys.map { it.signWithECDSA(wtx.id.bytes) })
assertFailsWith<IllegalArgumentException> { make().verifySignatures() } assertFailsWith<IllegalArgumentException> { make().verifySignatures() }
assertEquals( assertEquals(

View File

@ -84,8 +84,7 @@ class SignedTransactionGenerator : Generator<SignedTransaction>(SignedTransactio
val wireTransaction = WiredTransactionGenerator().generate(random, status) val wireTransaction = WiredTransactionGenerator().generate(random, status)
return SignedTransaction( return SignedTransaction(
txBits = wireTransaction.serialized, txBits = wireTransaction.serialized,
sigs = listOf(NullSignature), sigs = listOf(NullSignature)
id = wireTransaction.id
) )
} }
} }

View File

@ -167,6 +167,6 @@ class RequeryConfigurationTest {
type = TransactionType.General(), type = TransactionType.General(),
timestamp = null timestamp = null
) )
return SignedTransaction(wtx.serialized, listOf(DigitalSignature.WithKey(NullPublicKey, ByteArray(1))), wtx.id) return SignedTransaction(wtx.serialized, listOf(DigitalSignature.WithKey(NullPublicKey, ByteArray(1))))
} }
} }

View File

@ -156,6 +156,6 @@ class DBTransactionStorageTests {
type = TransactionType.General(), type = TransactionType.General(),
timestamp = null timestamp = null
) )
return SignedTransaction(wtx.serialized, listOf(DigitalSignature.WithKey(NullPublicKey, ByteArray(1))), wtx.id) return SignedTransaction(wtx.serialized, listOf(DigitalSignature.WithKey(NullPublicKey, ByteArray(1))))
} }
} }

View File

@ -282,7 +282,7 @@ data class TestLedgerDSLInterpreter private constructor (
override fun verifies(): EnforceVerifyOrFail { override fun verifies(): EnforceVerifyOrFail {
try { try {
val usedInputs = mutableSetOf<StateRef>() val usedInputs = mutableSetOf<StateRef>()
services.recordTransactions(transactionsUnverified.map { SignedTransaction(it.serialized, listOf(NullSignature), it.id) }) services.recordTransactions(transactionsUnverified.map { SignedTransaction(it.serialized, listOf(NullSignature)) })
for ((key, value) in transactionWithLocations) { for ((key, value) in transactionWithLocations) {
val wtx = value.transaction val wtx = value.transaction
val ltx = wtx.toLedgerTransaction(services) val ltx = wtx.toLedgerTransaction(services)
@ -294,7 +294,7 @@ data class TestLedgerDSLInterpreter private constructor (
throw DoubleSpentInputs(txIds) throw DoubleSpentInputs(txIds)
} }
usedInputs.addAll(wtx.inputs) usedInputs.addAll(wtx.inputs)
services.recordTransactions(SignedTransaction(wtx.serialized, listOf(NullSignature), wtx.id)) services.recordTransactions(SignedTransaction(wtx.serialized, listOf(NullSignature)))
} }
return EnforceVerifyOrFail.Token return EnforceVerifyOrFail.Token
} catch (exception: TransactionVerificationException) { } catch (exception: TransactionVerificationException) {
@ -340,7 +340,7 @@ fun signAll(transactionsToSign: List<WireTransaction>, extraKeys: List<KeyPair>)
val key = keyLookup[it] ?: throw IllegalArgumentException("Missing required key for ${it.toStringShort()}") val key = keyLookup[it] ?: throw IllegalArgumentException("Missing required key for ${it.toStringShort()}")
signatures += key.signWithECDSA(wtx.id) signatures += key.signWithECDSA(wtx.id)
} }
SignedTransaction(bits, signatures, wtx.id) SignedTransaction(bits, signatures)
} }
/** /**