mirror of
https://github.com/corda/corda.git
synced 2025-06-01 15:10:54 +00:00
Minor: make LedgerTransaction keep track of the hash of the original serialised tx
This commit is contained in:
parent
f0557e106d
commit
03ddf454c7
@ -54,7 +54,7 @@ data class WireTransaction(val inputStates: List<ContractStateRef>,
|
|||||||
val institutions = it.pubkeys.mapNotNull { pk -> institutionKeyMap[pk] }
|
val institutions = it.pubkeys.mapNotNull { pk -> institutionKeyMap[pk] }
|
||||||
AuthenticatedObject(it.pubkeys, institutions, it.command)
|
AuthenticatedObject(it.pubkeys, institutions, it.command)
|
||||||
}
|
}
|
||||||
return LedgerTransaction(inputStates, outputStates, authenticatedArgs, timestamp)
|
return LedgerTransaction(inputStates, outputStates, authenticatedArgs, timestamp, hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,30 +172,46 @@ data class TimestampedWireTransaction(
|
|||||||
*/
|
*/
|
||||||
class LedgerTransaction(
|
class LedgerTransaction(
|
||||||
/** The input states which will be consumed/invalidated by the execution of this transaction. */
|
/** The input states which will be consumed/invalidated by the execution of this transaction. */
|
||||||
val inputStates: List<ContractStateRef>,
|
val inStateRefs: List<ContractStateRef>,
|
||||||
/** The states that will be generated by the execution of this transaction. */
|
/** The states that will be generated by the execution of this transaction. */
|
||||||
val outputStates: List<ContractState>,
|
val outStates: List<ContractState>,
|
||||||
/** Arbitrary data passed to the program of each input state. */
|
/** Arbitrary data passed to the program of each input state. */
|
||||||
val commands: List<AuthenticatedObject<Command>>,
|
val commands: List<AuthenticatedObject<Command>>,
|
||||||
/** The moment the transaction was timestamped for */
|
/** The moment the transaction was timestamped for */
|
||||||
val time: Instant
|
val time: Instant,
|
||||||
|
/** The hash of the original serialised WireTransaction */
|
||||||
|
val hash: SecureHash
|
||||||
// TODO: nLockTime equivalent?
|
// TODO: nLockTime equivalent?
|
||||||
)
|
)
|
||||||
|
|
||||||
/** A transaction in fully resolved and sig-checked form, ready for passing as input to a verification function. */
|
/** A transaction in fully resolved and sig-checked form, ready for passing as input to a verification function. */
|
||||||
class TransactionForVerification(val inStates: List<ContractState>,
|
data class TransactionForVerification(val inStates: List<ContractState>,
|
||||||
val outStates: List<ContractState>,
|
val outStates: List<ContractState>,
|
||||||
val commands: List<AuthenticatedObject<Command>>,
|
val commands: List<AuthenticatedObject<Command>>,
|
||||||
val time: Instant) {
|
val time: Instant,
|
||||||
|
val origHash: SecureHash) {
|
||||||
|
override fun hashCode() = origHash.hashCode()
|
||||||
|
override fun equals(other: Any?) = other is TransactionForVerification && other.origHash == origHash
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws VerificationException if a contract throws an exception, the original is in the cause field
|
||||||
|
* @throws IllegalStateException if a state refers to an unknown contract.
|
||||||
|
*/
|
||||||
|
@Throws(VerificationException::class, IllegalStateException::class)
|
||||||
fun verify(programMap: Map<SecureHash, Contract>) {
|
fun verify(programMap: Map<SecureHash, Contract>) {
|
||||||
// For each input and output state, locate the program to run. Then execute the verification function. If any
|
// For each input and output state, locate the program to run. Then execute the verification function. If any
|
||||||
// throws an exception, the entire transaction is invalid.
|
// throws an exception, the entire transaction is invalid.
|
||||||
val programHashes = (inStates.map { it.programRef } + outStates.map { it.programRef }).toSet()
|
val programHashes = (inStates.map { it.programRef } + outStates.map { it.programRef }).toSet()
|
||||||
for (hash in programHashes) {
|
for (hash in programHashes) {
|
||||||
val program = programMap[hash] ?: throw IllegalStateException("Unknown program hash $hash")
|
val program = programMap[hash] ?: throw IllegalStateException("Unknown program hash $hash")
|
||||||
program.verify(this)
|
try {
|
||||||
|
program.verify(this)
|
||||||
|
} catch(e: Throwable) {
|
||||||
|
throw VerificationException(this, program, e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
/** Thrown if a verification fails due to a contract rejection. */
|
||||||
|
class VerificationException(val tx: TransactionForVerification, val contract: Contract, cause: Throwable?) : Exception(cause)
|
@ -67,6 +67,7 @@ class TransactionForTest() {
|
|||||||
override fun hashCode(): Int = state.hashCode()
|
override fun hashCode(): Int = state.hashCode()
|
||||||
}
|
}
|
||||||
private val outStates = arrayListOf<LabeledOutput>()
|
private val outStates = arrayListOf<LabeledOutput>()
|
||||||
|
|
||||||
private val commands: MutableList<AuthenticatedObject<Command>> = arrayListOf()
|
private val commands: MutableList<AuthenticatedObject<Command>> = arrayListOf()
|
||||||
|
|
||||||
constructor(inStates: List<ContractState>, outStates: List<ContractState>, commands: List<AuthenticatedObject<Command>>) : this() {
|
constructor(inStates: List<ContractState>, outStates: List<ContractState>, commands: List<AuthenticatedObject<Command>>) : this() {
|
||||||
@ -82,7 +83,7 @@ class TransactionForTest() {
|
|||||||
commands.add(AuthenticatedObject(keys, keys.mapNotNull { TEST_KEYS_TO_CORP_MAP[it] }, c()))
|
commands.add(AuthenticatedObject(keys, keys.mapNotNull { TEST_KEYS_TO_CORP_MAP[it] }, c()))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun run(time: Instant) = TransactionForVerification(inStates, outStates.map { it.state }, commands, time).verify(TEST_PROGRAM_MAP)
|
private fun run(time: Instant) = TransactionForVerification(inStates, outStates.map { it.state }, commands, time, SecureHash.randomSHA256()).verify(TEST_PROGRAM_MAP)
|
||||||
|
|
||||||
infix fun `fails requirement`(msg: String) = rejects(msg)
|
infix fun `fails requirement`(msg: String) = rejects(msg)
|
||||||
// which is uglier?? :)
|
// which is uglier?? :)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user