diff --git a/core/src/main/kotlin/net/corda/core/internal/JarSignatureCollector.kt b/core/src/main/kotlin/net/corda/core/internal/JarSignatureCollector.kt index 15475c740f..cc46372576 100644 --- a/core/src/main/kotlin/net/corda/core/internal/JarSignatureCollector.kt +++ b/core/src/main/kotlin/net/corda/core/internal/JarSignatureCollector.kt @@ -67,9 +67,9 @@ object JarSignatureCollector { (it.signerCertPath.certificates[0] as X509Certificate).publicKey }.sortedBy { it.hash} // Sorted for determinism. - private fun Set.toOrderedPublicKeys(): List = map { - (it.signerCertPath.certificates[0] as X509Certificate).publicKey - }.sortedBy { it.hash} // Sorted for determinism. + private fun Set.toPartiesOrderedByName(): List = map { + Party(it.signerCertPath.certificates[0] as X509Certificate) + }.sortedBy { it.name.toString() } // Sorted for determinism. private val JarInputStream.entries get(): Sequence = generateSequence(nextJarEntry) { nextJarEntry } } diff --git a/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt index de05494f1a..adf63a000a 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt @@ -107,30 +107,6 @@ data class LedgerTransaction @JvmOverloads constructor( } } - /** - * Verify that package ownership is respected. - * - * TODO - revisit once transaction contains network parameters. - */ - private fun validatePackageOwnership(contractAttachmentsByContract: Map) { - // This should never happen once we have network parameters in the transaction. - if (networkParameters == null) { - return - } - - val contractsAndOwners = allStates.mapNotNull { transactionState -> - val contractClassName = transactionState.contract - networkParameters.getOwnerOf(contractClassName)?.let { contractClassName to it } - }.toMap() - - contractsAndOwners.forEach { contract, owner -> - val attachment = contractAttachmentsByContract[contract]!! - if (!owner.isFulfilledBy(attachment.signers)) { - throw TransactionVerificationException.ContractAttachmentNotSignedByPackageOwnerException(this.id, id, contract) - } - } - } - /** * Verify that for each contract the network wide package owner is respected. * diff --git a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt index 8475afaf52..b132d30e21 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt @@ -181,7 +181,7 @@ open class TransactionBuilder @JvmOverloads constructor( val resolvedStates: List> = contractAttachmentsAndResolvedOutputStates.mapNotNull { it.second }.flatten() // The output states need to preserve the order in which they were added. - val resolvedOutputStatesInTheOriginalOrder: List> = outputStates().map { os -> resolvedStates.find { rs -> rs.data == os.data }!! } + val resolvedOutputStatesInTheOriginalOrder: List> = outputStates().map { os -> resolvedStates.find { rs -> rs.data == os.data && rs.encumbrance == os.encumbrance}!! } val attachments: Collection = contractAttachmentsAndResolvedOutputStates.map { it.first } + refStateContractAttachments diff --git a/core/src/test/kotlin/net/corda/core/JarSignatureTestUtils.kt b/core/src/test/kotlin/net/corda/core/JarSignatureTestUtils.kt index d5d9bed118..273d5b2234 100644 --- a/core/src/test/kotlin/net/corda/core/JarSignatureTestUtils.kt +++ b/core/src/test/kotlin/net/corda/core/JarSignatureTestUtils.kt @@ -25,8 +25,8 @@ object JarSignatureTestUtils { .waitFor()) } - fun Path.generateKey(alias: String, password: String, name: String) = - executeProcess("keytool", "-genkey", "-keystore", "_teststore", "-storepass", "storepass", "-keyalg", "RSA", "-alias", alias, "-keypass", password, "-dname", name) + fun Path.generateKey(alias: String, password: String, name: String, keyalg: String = "RSA") = + executeProcess("keytool", "-genkey", "-keystore", "_teststore", "-storepass", "storepass", "-keyalg", keyalg, "-alias", alias, "-keypass", password, "-dname", name) fun Path.createJar(fileName: String, vararg contents: String) = executeProcess(*(arrayOf("jar", "cvf", fileName) + contents)) diff --git a/core/src/test/kotlin/net/corda/core/internal/JarSignatureCollectorTest.kt b/core/src/test/kotlin/net/corda/core/internal/JarSignatureCollectorTest.kt index 66529970bc..b7a50cee46 100644 --- a/core/src/test/kotlin/net/corda/core/internal/JarSignatureCollectorTest.kt +++ b/core/src/test/kotlin/net/corda/core/internal/JarSignatureCollectorTest.kt @@ -34,9 +34,9 @@ class JarSignatureCollectorTest { @BeforeClass @JvmStatic fun beforeClass() { - dir.generateKey(ALICE, ALICE_PASS, ALICE_NAME) - dir.generateKey(BOB, BOB_PASS, BOB_NAME) - dir.generateKey(CHARLIE, CHARLIE_PASS, CHARLIE_NAME, "EC") + dir.generateKey(ALICE, ALICE_PASS, ALICE_NAME.toString()) + dir.generateKey(BOB, BOB_PASS, BOB_NAME.toString()) + dir.generateKey(CHARLIE, CHARLIE_PASS, CHARLIE_NAME.toString(), "EC") (dir / "_signable1").writeLines(listOf("signable1")) (dir / "_signable2").writeLines(listOf("signable2")) @@ -134,13 +134,13 @@ class JarSignatureCollectorTest { // Signing using EC algorithm produced JAR File spec incompatible signature block (META-INF/*.EC) which is anyway accepted by jarsiner, see [JarSignatureCollector] @Test fun `one signer with EC sign algorithm`() { - createJar("_signable1", "_signable2") - signJar(CHARLIE, CHARLIE_PASS) - assertEquals(listOf(CHARLIE_NAME), getJarSigners().names) // We only reused CHARLIE's distinguished name, so the keys will be different. + dir.createJar(FILENAME, "_signable1", "_signable2") + val charlieKey = dir.signJar(FILENAME, CHARLIE, CHARLIE_PASS) + assertEquals(setOf(charlieKey), dir.getJarSigners(FILENAME).toSet()) // We only reused CHARLIE's distinguished name, so the keys will be different. (dir / "my-dir").createDirectory() - updateJar("my-dir") - assertEquals(listOf(CHARLIE_NAME), getJarSigners().names) // Unsigned directory is irrelevant. + dir.updateJar(FILENAME, "my-dir") + assertEquals(setOf(charlieKey), dir.getJarSigners(FILENAME).toSet()) // Unsigned directory is irrelevant. } private fun signAsAlice() = dir.signJar(FILENAME, ALICE, ALICE_PASS) diff --git a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt index cd98fe5476..5322811f76 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt @@ -481,7 +481,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties { vaultFiller.fillWithSomeTestLinearStates(1, constraint = AlwaysAcceptAttachmentConstraint).states.first().state.constraint vaultFiller.fillWithSomeTestLinearStates(1, constraint = WhitelistedByZoneAttachmentConstraint).states.first().state.constraint // hash constraint - val linearStateHash = vaultFiller.fillWithSomeTestLinearStates(1, constraint = HashAttachmentConstraint(SecureHash.randomSHA256())) + val linearStateHash = vaultFiller.fillWithSomeTestLinearStates(1, constraint = AutomaticPlaceholderConstraint) // defaults to the HashConstraint val constraintHash = linearStateHash.states.first().state.constraint as HashAttachmentConstraint // signature constraint (single key) val linearStateSignature = vaultFiller.fillWithSomeTestLinearStates(1, constraint = SignatureAttachmentConstraint(alice.publicKey)) @@ -504,7 +504,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties { val constraintTypeCriteria2 = VaultQueryCriteria(constraintTypes = setOf(HASH)) val constraintResults2 = vaultService.queryBy(constraintTypeCriteria2) assertThat(constraintResults2.states).hasSize(2) - assertThat(constraintResults2.states.map { it.state.constraint }).containsOnlyOnce(constraintHash) + assertThat(constraintResults2.states.map { it.state.constraint }.toSet()).isEqualTo(setOf(constraintHash)) // search for states with [Vault.ConstraintInfo.Type] either HASH or CZ_WHITELISED // DOCSTART VaultQueryExample30 @@ -536,7 +536,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties { val alwaysAcceptConstraint = vaultFiller.fillWithSomeTestLinearStates(1, constraint = AlwaysAcceptAttachmentConstraint).states.first().state.constraint vaultFiller.fillWithSomeTestLinearStates(1, constraint = WhitelistedByZoneAttachmentConstraint) // hash constraint - val linearStateHash = vaultFiller.fillWithSomeTestLinearStates(1, constraint = HashAttachmentConstraint(SecureHash.randomSHA256())) + val linearStateHash = vaultFiller.fillWithSomeTestLinearStates(1, constraint = AutomaticPlaceholderConstraint) // defaults to the hash constraint. val constraintHash = linearStateHash.states.first().state.constraint as HashAttachmentConstraint // signature constraint (single key) val linearStateSignature = vaultFiller.fillWithSomeTestLinearStates(1, constraint = SignatureAttachmentConstraint(alice.publicKey)) @@ -559,7 +559,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties { // search for states for a specific HashAttachmentConstraint val constraintsCriteria2 = VaultQueryCriteria(constraints = setOf(Vault.ConstraintInfo(constraintHash))) val constraintResults2 = vaultService.queryBy(constraintsCriteria2) - assertThat(constraintResults2.states).hasSize(1) + assertThat(constraintResults2.states).hasSize(2) assertThat(constraintResults2.states.first().state.constraint).isEqualTo(constraintHash) // search for states with a specific SignatureAttachmentConstraint constraint @@ -574,7 +574,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties { Vault.ConstraintInfo(constraintSignatureCompositeKey), Vault.ConstraintInfo(constraintHash))) val constraintResults = vaultService.queryBy(constraintCriteria) // DOCEND VaultQueryExample31 - assertThat(constraintResults.states).hasSize(3) + assertThat(constraintResults.states).hasSize(4) assertThat(constraintResults.states.map { it.state.constraint }).containsAll(listOf(constraintHash, constraintSignature, constraintSignatureCompositeKey)) // exercise enriched query @@ -2337,7 +2337,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties { database.transaction { vaultFiller.fillWithSomeTestLinearStates(1, constraint = WhitelistedByZoneAttachmentConstraint) vaultFiller.fillWithSomeTestLinearStates(1, constraint = SignatureAttachmentConstraint(alice.publicKey)) - vaultFiller.fillWithSomeTestLinearStates(1, constraint = HashAttachmentConstraint( SecureHash.randomSHA256())) + vaultFiller.fillWithSomeTestLinearStates(1, constraint = AutomaticPlaceholderConstraint) // this defaults to the HashConstraint vaultFiller.fillWithSomeTestLinearStates(1, constraint = AlwaysAcceptAttachmentConstraint) // Base criteria diff --git a/notary/mysql/src/test/kotlin/net/corda/notary/mysql/MySQLNotaryServiceTests.kt b/notary/mysql/src/test/kotlin/net/corda/notary/mysql/MySQLNotaryServiceTests.kt index ee394f92d4..1de0acac4f 100644 --- a/notary/mysql/src/test/kotlin/net/corda/notary/mysql/MySQLNotaryServiceTests.kt +++ b/notary/mysql/src/test/kotlin/net/corda/notary/mysql/MySQLNotaryServiceTests.kt @@ -241,7 +241,7 @@ class MySQLNotaryServiceTests : IntegrationTest() { val builder = DummyContract.generateInitial(Random().nextInt(), notary, node.info.singleIdentity().ref(0)) val stx = node.services.signInitialTransaction(builder) node.services.recordTransactions(stx) - StateAndRef(builder.outputStates().first(), StateRef(stx.id, 0)) + StateAndRef(stx.coreTransaction.outputs.first(), StateRef(stx.id, 0)) } } diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/CommercialPaperTests.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/CommercialPaperTests.kt index f280e1c1c4..8725ad8445 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/CommercialPaperTests.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/CommercialPaperTests.kt @@ -116,7 +116,7 @@ class CommercialPaperTestsGeneric { // Some CP is issued onto the ledger by MegaCorp. transaction("Issuance") { - attachments(CP_PROGRAM_ID, CommercialPaper.CP_PROGRAM_ID) + attachments(CP_PROGRAM_ID) output(thisTest.getContract(), "paper", thisTest.getPaper()) command(MEGA_CORP_PUBKEY, thisTest.getIssueCommand(DUMMY_NOTARY)) timeWindow(TEST_TX_TIME) @@ -126,7 +126,7 @@ class CommercialPaperTestsGeneric { // The CP is sold to alice for her $900, $100 less than the face value. At 10% interest after only 7 days, // that sounds a bit too good to be true! transaction("Trade") { - attachments(Cash.PROGRAM_ID, CommercialPaper.CP_PROGRAM_ID) + attachments(Cash.PROGRAM_ID) input("paper") input("alice's $900") output(Cash.PROGRAM_ID, "borrowed $900", 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP) @@ -139,7 +139,7 @@ class CommercialPaperTestsGeneric { // Time passes, and Alice redeem's her CP for $1000, netting a $100 profit. MegaCorp has received $1200 // as a single payment from somewhere and uses it to pay Alice off, keeping the remaining $200 as change. transaction("Redemption") { - attachments(CP_PROGRAM_ID, CommercialPaper.CP_PROGRAM_ID) + attachments(CP_PROGRAM_ID) input("alice's paper") input("some profits") @@ -182,7 +182,6 @@ class CommercialPaperTestsGeneric { @Test fun `key mismatch at issue`() { transaction { - attachment(CP_PROGRAM_ID) attachment(CP_PROGRAM_ID) output(thisTest.getContract(), thisTest.getPaper()) command(MINI_CORP_PUBKEY, thisTest.getIssueCommand(DUMMY_NOTARY)) @@ -194,7 +193,6 @@ class CommercialPaperTestsGeneric { @Test fun `face value is not zero`() { transaction { - attachment(CP_PROGRAM_ID) attachment(CP_PROGRAM_ID) output(thisTest.getContract(), thisTest.getPaper().withFaceValue(0.DOLLARS `issued by` issuer)) command(MEGA_CORP_PUBKEY, thisTest.getIssueCommand(DUMMY_NOTARY)) @@ -206,7 +204,6 @@ class CommercialPaperTestsGeneric { @Test fun `maturity date not in the past`() { transaction { - attachment(CP_PROGRAM_ID) attachment(CP_PROGRAM_ID) output(thisTest.getContract(), thisTest.getPaper().withMaturityDate(TEST_TX_TIME - 10.days)) command(MEGA_CORP_PUBKEY, thisTest.getIssueCommand(DUMMY_NOTARY)) @@ -218,7 +215,6 @@ class CommercialPaperTestsGeneric { @Test fun `issue cannot replace an existing state`() { transaction { - attachment(CP_PROGRAM_ID) attachment(CP_PROGRAM_ID) input(thisTest.getContract(), thisTest.getPaper()) output(thisTest.getContract(), thisTest.getPaper()) diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashTests.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashTests.kt index 895257e006..1b51e95b43 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashTests.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashTests.kt @@ -567,7 +567,7 @@ class CashTests { private fun makeCash(amount: Amount, issuer: AbstractParty, depositRef: Byte = 1) = StateAndRef( - TransactionState(Cash.State(amount `issued by` issuer.ref(depositRef), ourIdentity), Cash.PROGRAM_ID, DUMMY_NOTARY), + TransactionState(Cash.State(amount `issued by` issuer.ref(depositRef), ourIdentity), Cash.PROGRAM_ID, DUMMY_NOTARY, constraint = AlwaysAcceptAttachmentConstraint), StateRef(SecureHash.randomSHA256(), Random().nextInt(32)) ) diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TransactionDSLInterpreter.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TransactionDSLInterpreter.kt index 4604c3a085..209362816e 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TransactionDSLInterpreter.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TransactionDSLInterpreter.kt @@ -1,32 +1,6 @@ package net.corda.testing.dsl import net.corda.core.DoNotImplement -import net.corda.core.contracts.AlwaysAcceptAttachmentConstraint -import net.corda.core.contracts.Attachment -import net.corda.core.contracts.AttachmentConstraint -import net.corda.core.contracts.AutomaticHashConstraint -import net.corda.core.contracts.CommandData -import net.corda.core.contracts.ContractClassName -import net.corda.core.contracts.ContractState -import net.corda.core.contracts.StateRef -import net.corda.core.contracts.TimeWindow -import net.corda.core.contracts.AlwaysAcceptAttachmentConstraint -import net.corda.core.contracts.Attachment -import net.corda.core.contracts.AttachmentConstraint -import net.corda.core.contracts.AutomaticPlaceholderConstraint -import net.corda.core.contracts.CommandData -import net.corda.core.contracts.ContractClassName -import net.corda.core.contracts.ContractState -import net.corda.core.contracts.StateRef -import net.corda.core.contracts.TimeWindow -import net.corda.core.contracts.AlwaysAcceptAttachmentConstraint -import net.corda.core.contracts.Attachment -import net.corda.core.contracts.AttachmentConstraint -import net.corda.core.contracts.CommandData -import net.corda.core.contracts.ContractClassName -import net.corda.core.contracts.ContractState -import net.corda.core.contracts.StateRef -import net.corda.core.contracts.TimeWindow import net.corda.core.contracts.* import net.corda.core.crypto.SecureHash import net.corda.core.identity.Party diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/VaultFiller.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/VaultFiller.kt index eb46690305..03926a432c 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/VaultFiller.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/VaultFiller.kt @@ -103,7 +103,7 @@ class VaultFiller @JvmOverloads constructor( linearNumber: Long = 0L, linearBoolean: Boolean = false, linearTimestamp: Instant = now(), - constraint: AttachmentConstraint = AutomaticHashConstraint): Vault { + constraint: AttachmentConstraint = AutomaticPlaceholderConstraint): Vault { val myKey: PublicKey = services.myInfo.chooseIdentity().owningKey val me = AnonymousParty(myKey) val issuerKey = defaultNotary.keyPair