You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* A transaction is valid if the verify() function of the contract of all the transaction's
33
+
* input and output states does not throw an exception.
34
+
*/
35
+
overridefunverify(tx:LedgerTransaction) {
36
+
val command = tx.commands.requireSingleCommand<Commands>()
37
+
when (command.value) {
38
+
isCommands.Lock-> requireThat {
39
+
"There should be one input state." using (tx.inputs.size ==1)
40
+
"There should be one output state." using (tx.outputs.size ==1)
41
+
"The output state should be of type AssetExchangeHTLCState." using (tx.outputs[0].data isAssetExchangeHTLCState)
42
+
43
+
// Get the HTLC State
44
+
val htlcState = tx.outputs[0].data asAssetExchangeHTLCState
45
+
46
+
// Check if timeout is beyond current time
47
+
"Timeout after current time" using (htlcState.lockInfo.expiryTime >Instant.now())
48
+
49
+
// Check if owner is locker
50
+
val inputState = tx.inputs[0].state.data
51
+
"Locker must be the owner of asset" using inputState.participants.containsAll(listOf(htlcState.locker))
52
+
53
+
// Check if asset consumed in input is same as in HTLC State
54
+
val assetPointer =StaticPointer(tx.inputs[0].ref, tx.inputs[0].state.data.javaClass)
55
+
"Asset State match with input state" using (assetPointer.equals(htlcState.assetStatePointer))
56
+
57
+
// Check if both locker and recipient are signers
58
+
val participantKeys = htlcState.participants.map { it.owningKey }
59
+
"The required signers of the transaction must include locker and recipient." using (command.signers.containsAll(participantKeys))
60
+
}
61
+
isCommands.Claim-> requireThat {
62
+
"There should be one input state." using (tx.inputs.size ==1)
63
+
"The input state should be of type AssetExchangeHTLCState." using (tx.inputs[0].state.data isAssetExchangeHTLCState)
64
+
"There should be one output state." using (tx.outputs.size ==1)
65
+
66
+
// Get the Claim Command
67
+
val claimCmd = tx.commandsOfType<Commands.Claim>().single()
68
+
69
+
// Get the input HTLC state
70
+
val htlcState = tx.inputs[0].state.data asAssetExchangeHTLCState
71
+
72
+
// Check if timeWindow <= expiryTime
73
+
val untilTime = tx.timeWindow!!.untilTime!!
74
+
"Time Window for claim shoule be before expiry time." using (untilTime.isBefore(htlcState.lockInfo.expiryTime) || untilTime.equals(htlcState.lockInfo.expiryTime))
75
+
76
+
// Verify if (hash, preimage) pair matches
77
+
val computedHash = claimCmd.value.assetClaimHTLC.hashPreimage.sha256().bytes
78
+
val expectedHash = htlcState.lockInfo.hash.bytes
79
+
"Hash match with pre-image." using (Arrays.equals(computedHash, expectedHash))
80
+
81
+
// Check if owner is recipient
82
+
val outputState = tx.outputs[0].data
83
+
"Recipient must be the owner of asset" using outputState.participants.containsAll(listOf(htlcState.recipient))
84
+
85
+
// Verify if recipient is signer
86
+
val participantKeys =listOf(htlcState.recipient.owningKey)
87
+
"The required signers of the transaction must include recipient." using (command.signers.containsAll(participantKeys))
88
+
}
89
+
isCommands.Unlock-> requireThat {
90
+
"There should be one input state." using (tx.inputs.size ==1)
91
+
"The input state should be of type AssetExchangeHTLCState." using (tx.inputs[0].state.data isAssetExchangeHTLCState)
92
+
"There should be one output state." using (tx.outputs.size ==1)
93
+
94
+
// Get the input HTLC state
95
+
val htlcState = tx.inputs[0].state.data asAssetExchangeHTLCState
96
+
97
+
// Check if timeWindow > expiryTime
98
+
val fromTime = tx.timeWindow!!.fromTime!!
99
+
"TimeWindow for unlock should be after expiry time." using (fromTime.isAfter(htlcState.lockInfo.expiryTime))
100
+
101
+
// Check if owner is locker
102
+
val outputState = tx.outputs[0].data
103
+
"Locker must be the owner of asset" using outputState.participants.containsAll(listOf(htlcState.locker))
104
+
105
+
// Verify if locker is signer
106
+
val participantKeys =listOf(htlcState.locker.owningKey)
107
+
"The required signers of the transaction must include locker." using (command.signers.containsAll(participantKeys))
108
+
}
109
+
}
110
+
}
111
+
112
+
/**
113
+
* Commands are used to indicate the intent of a transaction.
114
+
* Commands for [AssetExchangeHTLCStateContract] are:
0 commit comments