mirror of
https://github.com/corda/corda.git
synced 2025-06-23 09:25:36 +00:00
Merge branch 'master' into feature/CORDA-2570/revert-to-one-attachment-per-contract
# Conflicts: # core/src/main/kotlin/net/corda/core/internal/TransactionVerifierServiceInternal.kt # core/src/test/kotlin/net/corda/core/contracts/ConstraintsPropagationTests.kt
This commit is contained in:
@ -275,15 +275,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
||||
@KeepForDJVM
|
||||
class OverlappingAttachmentsException(txId: SecureHash, path: String) : TransactionVerificationException(txId, "Multiple attachments define a file at $path.", null)
|
||||
|
||||
/**
|
||||
* Thrown when a transaction appears to be trying to downgrade a state to an earlier version of the app that defines it.
|
||||
* This could be an attempt to exploit a bug in the app, so we prevent it.
|
||||
*/
|
||||
@KeepForDJVM
|
||||
class TransactionVerificationVersionException(txId: SecureHash, contractClassName: ContractClassName, inputVersion: String, outputVersion: String)
|
||||
: TransactionVerificationException(txId, "No-Downgrade Rule has been breached for contract class $contractClassName. " +
|
||||
"The output state contract version '$outputVersion' is lower than the version of the input state '$inputVersion'.", null)
|
||||
|
||||
/**
|
||||
* Thrown to indicate that a contract attachment is not signed by the network-wide package owner. Please note that
|
||||
* the [txId] will always be [SecureHash.zeroHash] because package ownership is an error with a particular attachment,
|
||||
|
@ -375,6 +375,24 @@ class ConstraintsPropagationTests {
|
||||
SignableData(wireTransaction.id, SignatureMetadata(4, Crypto.findSignatureScheme(nodeKey).schemeNumberID)), nodeKey))
|
||||
recordTransactions(SignedTransaction(wireTransaction, sigs))
|
||||
}
|
||||
@Test
|
||||
fun `Input state contract version may be incompatible with lower version`() {
|
||||
ledgerServices.ledger(DUMMY_NOTARY) {
|
||||
ledgerServices.recordTransaction(transaction {
|
||||
attachment(Cash.PROGRAM_ID, SecureHash.allOnesHash, listOf(hashToSignatureConstraintsKey), mapOf(Attributes.Name.IMPLEMENTATION_VERSION.toString() to "2"))
|
||||
output(Cash.PROGRAM_ID, "c1", DUMMY_NOTARY, null, SignatureAttachmentConstraint(hashToSignatureConstraintsKey), Cash.State(1000.POUNDS `issued by` ALICE_PARTY.ref(1), ALICE_PARTY))
|
||||
command(ALICE_PUBKEY, Cash.Commands.Issue())
|
||||
verifies()
|
||||
})
|
||||
transaction {
|
||||
attachment(Cash.PROGRAM_ID, SecureHash.zeroHash, listOf(hashToSignatureConstraintsKey), mapOf(Attributes.Name.IMPLEMENTATION_VERSION.toString() to "1"))
|
||||
input("c1")
|
||||
output(Cash.PROGRAM_ID, "c2", DUMMY_NOTARY, null, SignatureAttachmentConstraint(hashToSignatureConstraintsKey), Cash.State(1000.POUNDS `issued by` ALICE_PARTY.ref(1), BOB_PARTY))
|
||||
command(ALICE_PUBKEY, Cash.Commands.Move())
|
||||
verifies()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Input state contract version is compatible with the same version`() {
|
||||
@ -414,6 +432,50 @@ class ConstraintsPropagationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Input states contract version may be lower that current contract version`() {
|
||||
ledgerServices.ledger(DUMMY_NOTARY) {
|
||||
ledgerServices.recordTransaction(transaction {
|
||||
attachment(Cash.PROGRAM_ID, SecureHash.allOnesHash, listOf(hashToSignatureConstraintsKey), mapOf(Attributes.Name.IMPLEMENTATION_VERSION.toString() to "1"))
|
||||
output(Cash.PROGRAM_ID, "c1", DUMMY_NOTARY, null, SignatureAttachmentConstraint(hashToSignatureConstraintsKey), Cash.State(1000.POUNDS `issued by` ALICE_PARTY.ref(1), ALICE_PARTY))
|
||||
command(ALICE_PUBKEY, Cash.Commands.Issue())
|
||||
verifies()
|
||||
})
|
||||
ledgerServices.recordTransaction(transaction {
|
||||
attachment(Cash.PROGRAM_ID, SecureHash.zeroHash, listOf(hashToSignatureConstraintsKey), mapOf(Attributes.Name.IMPLEMENTATION_VERSION.toString() to "2"))
|
||||
output(Cash.PROGRAM_ID, "c2", DUMMY_NOTARY, null, SignatureAttachmentConstraint(hashToSignatureConstraintsKey), Cash.State(1000.POUNDS `issued by` ALICE_PARTY.ref(1), ALICE_PARTY))
|
||||
command(ALICE_PUBKEY, Cash.Commands.Issue())
|
||||
verifies()
|
||||
})
|
||||
transaction {
|
||||
input("c1")
|
||||
input("c2")
|
||||
output(Cash.PROGRAM_ID, "c3", DUMMY_NOTARY, null, SignatureAttachmentConstraint(hashToSignatureConstraintsKey), Cash.State(2000.POUNDS `issued by` ALICE_PARTY.ref(1), BOB_PARTY))
|
||||
command(ALICE_PUBKEY, Cash.Commands.Move())
|
||||
verifies()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Input state with contract version can be downgraded to no version`() {
|
||||
ledgerServices.ledger(DUMMY_NOTARY) {
|
||||
ledgerServices.recordTransaction(transaction {
|
||||
attachment(Cash.PROGRAM_ID, SecureHash.allOnesHash, listOf(hashToSignatureConstraintsKey), mapOf(Attributes.Name.IMPLEMENTATION_VERSION.toString() to "2"))
|
||||
output(Cash.PROGRAM_ID, "c1", DUMMY_NOTARY, null, SignatureAttachmentConstraint(hashToSignatureConstraintsKey), Cash.State(1000.POUNDS `issued by` ALICE_PARTY.ref(1), ALICE_PARTY))
|
||||
command(ALICE_PUBKEY, Cash.Commands.Issue())
|
||||
verifies()
|
||||
})
|
||||
transaction {
|
||||
attachment(Cash.PROGRAM_ID, SecureHash.zeroHash, listOf(hashToSignatureConstraintsKey), emptyMap())
|
||||
input("c1")
|
||||
output(Cash.PROGRAM_ID, "c2", DUMMY_NOTARY, null, SignatureAttachmentConstraint(hashToSignatureConstraintsKey), Cash.State(1000.POUNDS `issued by` ALICE_PARTY.ref(1), BOB_PARTY))
|
||||
command(ALICE_PUBKEY, Cash.Commands.Move())
|
||||
verifies()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Input state without contract version is compatible with any version`() {
|
||||
ledgerServices.ledger(DUMMY_NOTARY) {
|
||||
|
Reference in New Issue
Block a user