diff --git a/core-tests/src/test/kotlin/net/corda/coretests/flows/ContractUpgradeFlowTest.kt b/core-tests/src/test/kotlin/net/corda/coretests/flows/ContractUpgradeFlowTest.kt index 54678ff3c6..e6994316a8 100644 --- a/core-tests/src/test/kotlin/net/corda/coretests/flows/ContractUpgradeFlowTest.kt +++ b/core-tests/src/test/kotlin/net/corda/coretests/flows/ContractUpgradeFlowTest.kt @@ -30,7 +30,7 @@ import java.util.* class ContractUpgradeFlowTest : WithContracts, WithFinality { companion object { - private val classMockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, DUMMY_CONTRACTS_CORDAPP, enclosedCordapp())) + private val classMockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, FINANCE_WORKFLOWS_CORDAPP, DUMMY_CONTRACTS_CORDAPP, enclosedCordapp())) @JvmStatic @AfterClass diff --git a/core-tests/src/test/kotlin/net/corda/coretests/flows/FinalityFlowTests.kt b/core-tests/src/test/kotlin/net/corda/coretests/flows/FinalityFlowTests.kt index 013fa07d53..644ea2013a 100644 --- a/core-tests/src/test/kotlin/net/corda/coretests/flows/FinalityFlowTests.kt +++ b/core-tests/src/test/kotlin/net/corda/coretests/flows/FinalityFlowTests.kt @@ -40,6 +40,7 @@ import net.corda.core.utilities.unwrap import net.corda.coretesting.internal.matchers.flow.willReturn import net.corda.coretesting.internal.matchers.flow.willThrow import net.corda.coretests.flows.WithFinality.FinalityInvoker +import net.corda.coretests.flows.WithFinality.OldFinalityInvoker import net.corda.finance.GBP import net.corda.finance.POUNDS import net.corda.finance.contracts.asset.Cash @@ -50,6 +51,9 @@ import net.corda.finance.test.flows.CashIssueWithObserversFlow import net.corda.finance.test.flows.CashPaymentWithObserversFlow import net.corda.node.services.persistence.DBTransactionStorage import net.corda.node.services.persistence.DBTransactionStorageLedgerRecovery +import net.corda.node.services.persistence.DBTransactionStorageLedgerRecovery.DBReceiverDistributionRecord +import net.corda.node.services.persistence.DBTransactionStorageLedgerRecovery.DBSenderDistributionRecord +import net.corda.node.services.persistence.HashedDistributionList import net.corda.node.services.persistence.ReceiverDistributionRecord import net.corda.node.services.persistence.SenderDistributionRecord import net.corda.nodeapi.internal.persistence.CordaPersistence @@ -59,7 +63,6 @@ import net.corda.testing.core.BOB_NAME import net.corda.testing.core.CHARLIE_NAME import net.corda.testing.core.TestIdentity import net.corda.testing.core.singleIdentity -import net.corda.testing.node.internal.CustomCordapp import net.corda.testing.node.internal.DUMMY_CONTRACTS_CORDAPP import net.corda.testing.node.internal.FINANCE_CONTRACTS_CORDAPP import net.corda.testing.node.internal.FINANCE_WORKFLOWS_CORDAPP @@ -87,9 +90,7 @@ class FinalityFlowTests : WithFinality { } override val mockNet = InternalMockNetwork(cordappsForAllNodes = setOf(FINANCE_CONTRACTS_CORDAPP, FINANCE_WORKFLOWS_CORDAPP, DUMMY_CONTRACTS_CORDAPP, enclosedCordapp(), - findCordapp("net.corda.finance.test.flows"), - CustomCordapp(targetPlatformVersion = 3, classes = setOf(FinalityFlow::class.java)))) - + findCordapp("net.corda.finance.test.flows"))) private val aliceNode = makeNode(ALICE_NAME) private val notary = mockNet.defaultNotaryIdentity @@ -124,7 +125,7 @@ class FinalityFlowTests : WithFinality { val oldBob = createBob(cordapps = listOf(tokenOldCordapp())) val stx = aliceNode.issuesCashTo(oldBob) @Suppress("DEPRECATION") - aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture.getOrThrow() + aliceNode.startFlowAndRunNetwork(OldFinalityInvoker(stx)).resultFuture.getOrThrow() assertThat(oldBob.services.validatedTransactions.getTransaction(stx.id)).isNotNull } @@ -394,8 +395,10 @@ class FinalityFlowTests : WithFinality { assertEquals(StatesToRecord.ONLY_RELEVANT, this?.statesToRecord) assertEquals(aliceNode.info.singleIdentity().name.hashCode().toLong(), this?.initiatorPartyId) // note: Charlie assertion here is using the hinted StatesToRecord value passed to it from Alice - assertEquals(mapOf(BOB_NAME.hashCode().toLong() to StatesToRecord.ONLY_RELEVANT, - CHARLIE_NAME.hashCode().toLong() to StatesToRecord.ALL_VISIBLE), this?.peersToStatesToRecord) + assertEquals(mapOf( + BOB_NAME.hashCode().toLong() to StatesToRecord.ONLY_RELEVANT, + CHARLIE_NAME.hashCode().toLong() to StatesToRecord.ALL_VISIBLE + ), distList.peerHashToStatesToRecord) } validateSenderAndReceiverTimestamps(sdrs, rdr!!) @@ -511,6 +514,7 @@ class FinalityFlowTests : WithFinality { } } + @Suppress("unused") @InitiatedBy(SpendFlow::class) class AcceptSpendFlow(private val otherSide: FlowSession) : FlowLogic() { @@ -547,6 +551,7 @@ class FinalityFlowTests : WithFinality { } } + @Suppress("unused") @InitiatedBy(SpeedySpendFlow::class) class AcceptSpeedySpendFlow(private val otherSideSession: FlowSession) : FlowLogic() { @@ -580,7 +585,7 @@ class FinalityFlowTests : WithFinality { } } - class FinaliseSpeedySpendFlow(val id: SecureHash, val sigs: List) : FlowLogic() { + class FinaliseSpeedySpendFlow(val id: SecureHash, private val sigs: List) : FlowLogic() { @Suspendable override fun call(): SignedTransaction { @@ -606,6 +611,7 @@ class FinalityFlowTests : WithFinality { } } + @Suppress("unused") @InitiatedBy(MimicFinalityFailureFlow::class) class TriggerReceiveFinalityFlow(private val otherSide: FlowSession) : FlowLogic() { @Suspendable diff --git a/core-tests/src/test/kotlin/net/corda/coretests/flows/WithFinality.kt b/core-tests/src/test/kotlin/net/corda/coretests/flows/WithFinality.kt index 9ed9b04679..714e8b85fa 100644 --- a/core-tests/src/test/kotlin/net/corda/coretests/flows/WithFinality.kt +++ b/core-tests/src/test/kotlin/net/corda/coretests/flows/WithFinality.kt @@ -4,7 +4,13 @@ import co.paralleluniverse.fibers.Suspendable import com.natpryce.hamkrest.MatchResult import com.natpryce.hamkrest.Matcher import com.natpryce.hamkrest.equalTo -import net.corda.core.flows.* +import net.corda.core.flows.FinalityFlow +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.FlowSession +import net.corda.core.flows.InitiatedBy +import net.corda.core.flows.InitiatingFlow +import net.corda.core.flows.ReceiveFinalityFlow +import net.corda.core.flows.StartableByRPC import net.corda.core.identity.Party import net.corda.core.internal.FlowStateMachineHandle import net.corda.core.messaging.CordaRPCOps @@ -58,4 +64,13 @@ interface WithFinality : WithMockNet { subFlow(ReceiveFinalityFlow(otherSide)) } } + + @StartableByRPC + class OldFinalityInvoker(private val transaction: SignedTransaction) : FlowLogic() { + @Suspendable + override fun call(): SignedTransaction { + @Suppress("DEPRECATION") + return subFlow(FinalityFlow(transaction)) + } + } } diff --git a/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt b/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt index 36b5174ad8..62d85b9fff 100644 --- a/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt @@ -219,6 +219,7 @@ class FinalityFlow private constructor(val transaction: SignedTransaction, val requiresNotarisation = needsNotarySignature(transaction) val useTwoPhaseFinality = serviceHub.myInfo.platformVersion >= PlatformVersionSwitches.TWO_PHASE_FINALITY + && serviceHub.getAppContext().cordapp.targetPlatformVersion >= PlatformVersionSwitches.TWO_PHASE_FINALITY if (useTwoPhaseFinality) { val stxn = if (requiresNotarisation) { @@ -250,6 +251,7 @@ class FinalityFlow private constructor(val transaction: SignedTransaction, return stxn } else { + logger.warnOnce("The current usage of FinalityFlow is not using Two Phase Finality. Please consider upgrading your CorDapp (refer to Corda 4.11 release notes).") val stxn = if (requiresNotarisation) { notarise().first } else transaction @@ -501,6 +503,8 @@ class ReceiveFinalityFlow(private val otherSideSession: FlowSession, val requiresNotarisation = needsNotarySignature(stx) val fromTwoPhaseFinalityNode = serviceHub.networkMapCache.getNodeByLegalIdentity(otherSideSession.counterparty)?.platformVersion!! >= PlatformVersionSwitches.TWO_PHASE_FINALITY + && serviceHub.getAppContext().cordapp.targetPlatformVersion >= PlatformVersionSwitches.TWO_PHASE_FINALITY + if (fromTwoPhaseFinalityNode) { if (requiresNotarisation) { serviceHub.telemetryServiceInternal.span("${this::class.java.name}#recordUnnotarisedTransaction", flowLogic = this) { @@ -537,6 +541,7 @@ class ReceiveFinalityFlow(private val otherSideSession: FlowSession, otherSideSession.send(FetchDataFlow.Request.End) // Finish fetching data (deferredAck) } } else { + logger.warnOnce("The current usage of ReceiveFinalityFlow is not using Two Phase Finality. Please consider upgrading your CorDapp (refer to Corda 4.11 release notes).") serviceHub.telemetryServiceInternal.span("${this::class.java.name}#recordTransactions", flowLogic = this) { serviceHub.recordTransactions(statesToRecord, setOf(stx)) } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt index 166a10fdf3..d747c23b97 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt @@ -432,7 +432,7 @@ object LoggerSerializer : Serializer() { object ClassSerializer : Serializer>() { override fun read(kryo: Kryo, input: Input, type: Class>): Class<*> { val className = input.readString() - return Class.forName(className, true, kryo.classLoader) + return if (className == "void") Void.TYPE else Class.forName(className, true, kryo.classLoader) } override fun write(kryo: Kryo, output: Output, clazz: Class<*>) { diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoTests.kt index 15a98d1552..2f070a4d24 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/kryo/KryoTests.kt @@ -351,6 +351,20 @@ class KryoTests(private val compression: CordaSerializationEncoding?) { assertEquals(randomHash, exception2.requested) } + @Test(timeout=300_000) + fun `serialize - deserialize primative void`() { + val original = JavaVoidHolder() + val roundtrip = original.checkpointSerialize(context).checkpointDeserialize(context) + assertThat(roundtrip.voidClass).isEqualTo(original.voidClass) + } + + class JavaVoidHolder { + val voidClass: Class = Void.TYPE + init { + check(voidClass.name == "void") // Sanity check to make sure we're dealing with the primitive void + } + } + @Test(timeout=300_000) fun `compression has the desired effect`() { compression ?: return @@ -373,6 +387,7 @@ class KryoTests(private val compression: CordaSerializationEncoding?) { @Test(timeout=300_000) fun `compression reduces number of bytes significantly`() { + @Suppress("unused") class Holder(val holder: ByteArray) val obj = Holder(ByteArray(20000)) diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/AesDbEncryptionService.kt b/node/src/main/kotlin/net/corda/node/services/persistence/AesDbEncryptionService.kt index 924ef48c7f..0b4c14638b 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/AesDbEncryptionService.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/AesDbEncryptionService.kt @@ -36,6 +36,7 @@ class AesDbEncryptionService(private val database: CordaPersistence) : Encryptio companion object { private const val INITIAL_KEY_COUNT = 10 private const val UUID_BYTES = 16 + private const val VERSION_TAG = 1 } private val aesKeys = ArrayList>() @@ -73,7 +74,7 @@ class AesDbEncryptionService(private val database: CordaPersistence) : Encryptio val (keyId, aesKey) = aesKeys[newSecureRandom().nextInt(aesKeys.size)] val ciphertext = AesEncryption.encrypt(aesKey, plaintext, additionalData) val buffer = ByteBuffer.allocate(1 + UUID_BYTES + Integer.BYTES + (additionalData?.size ?: 0) + ciphertext.size) - buffer.put(1) // Version tag + buffer.put(VERSION_TAG.toByte()) // Prepend the key ID to the returned ciphertext. It's OK that this is not included in the authenticated additional data because // changing this value will lead to either an non-existent key or an another key which will not be able decrypt the ciphertext. buffer.putUUID(keyId) @@ -88,9 +89,7 @@ class AesDbEncryptionService(private val database: CordaPersistence) : Encryptio } override fun decrypt(ciphertext: ByteArray): EncryptionService.PlaintextAndAAD { - val buffer = ByteBuffer.wrap(ciphertext) - val version = buffer.get().toInt() - require(version == 1) + val buffer = wrap(ciphertext) val keyId = buffer.getUUID() val aesKey = requireNotNull(aesKeys.find { it.first == keyId }?.second) { "Unable to decrypt" } val additionalData = buffer.getAdditionaData() @@ -100,11 +99,18 @@ class AesDbEncryptionService(private val database: CordaPersistence) : Encryptio } override fun extractUnauthenticatedAdditionalData(ciphertext: ByteArray): ByteArray? { - val buffer = ByteBuffer.wrap(ciphertext) - buffer.position(1 + UUID_BYTES) + val buffer = wrap(ciphertext) + buffer.position(buffer.position() + UUID_BYTES) return buffer.getAdditionaData() } + private fun wrap(ciphertext: ByteArray): ByteBuffer { + val buffer = ByteBuffer.wrap(ciphertext) + val version = buffer.get().toInt() + require(version == VERSION_TAG) { "Unknown version $version" } + return buffer + } + private fun ByteBuffer.getAdditionaData(): ByteArray? { val additionalDataSize = getInt() return if (additionalDataSize > 0) ByteArray(additionalDataSize).also { get(it) } else null diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorageLedgerRecovery.kt b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorageLedgerRecovery.kt index 527c0e4e9a..db1c176f0a 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorageLedgerRecovery.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorageLedgerRecovery.kt @@ -11,6 +11,7 @@ import net.corda.core.internal.VisibleForTesting import net.corda.core.node.StatesToRecord import net.corda.core.node.services.vault.Sort import net.corda.core.serialization.CordaSerializable +import net.corda.core.utilities.OpaqueBytes import net.corda.node.CordaClock import net.corda.node.services.EncryptionService import net.corda.node.services.network.PersistentPartyInfoCache @@ -105,8 +106,7 @@ class DBTransactionStorageLedgerRecovery(private val database: CordaPersistence, return ReceiverDistributionRecord( SecureHash.parse(this.txId), this.compositeKey.peerPartyId, - hashedDL.peerHashToStatesToRecord, - hashedDL.senderStatesToRecord, + OpaqueBytes(this.distributionList), this.compositeKey.timestamp ) } @@ -132,7 +132,7 @@ class DBTransactionStorageLedgerRecovery(private val database: CordaPersistence, val timestamp: Instant, val timestampDiscriminator: Int = nextDiscriminatorNumber.andIncrement ) { - constructor(key: TimestampKey, partyId: Long): this(partyId = partyId, timestamp = key.timestamp, timestampDiscriminator = key.timestampDiscriminator) + constructor(key: TimestampKey, partyId: Long): this(partyId, key.timestamp, key.timestampDiscriminator) companion object { val nextDiscriminatorNumber = AtomicInteger() } @@ -268,30 +268,34 @@ class DBTransactionStorageLedgerRecovery(private val database: CordaPersistence, val txnMetadata = criteriaQuery.from(DBReceiverDistributionRecord::class.java) val predicates = mutableListOf() val compositeKey = txnMetadata.get("compositeKey") - predicates.add(criteriaBuilder.greaterThanOrEqualTo(compositeKey.get(PersistentKey::timestamp.name), timeWindow.fromTime)) - predicates.add(criteriaBuilder.and(criteriaBuilder.lessThanOrEqualTo(compositeKey.get(PersistentKey::timestamp.name), timeWindow.untilTime))) + val timestamp = compositeKey.get(PersistentKey::timestamp.name) + predicates.add(criteriaBuilder.greaterThanOrEqualTo(timestamp, timeWindow.fromTime)) + predicates.add(criteriaBuilder.and(criteriaBuilder.lessThanOrEqualTo(timestamp, timeWindow.untilTime))) if (excludingTxnIds.isNotEmpty()) { - predicates.add(criteriaBuilder.and(criteriaBuilder.not(txnMetadata.get(DBSenderDistributionRecord::txId.name).`in`( - excludingTxnIds.map { it.toString() })))) + val txId = txnMetadata.get(DBSenderDistributionRecord::txId.name) + predicates.add(criteriaBuilder.and(criteriaBuilder.not(txId.`in`(excludingTxnIds.map { it.toString() })))) } if (initiators.isNotEmpty()) { - val initiatorPartyIds = initiators.map { partyInfoCache.getPartyIdByCordaX500Name(it) } + val initiatorPartyIds = initiators.map(partyInfoCache::getPartyIdByCordaX500Name) predicates.add(criteriaBuilder.and(compositeKey.get(PersistentKey::peerPartyId.name).`in`(initiatorPartyIds))) } criteriaQuery.where(*predicates.toTypedArray()) // optionally order by timestamp orderByTimestamp?.let { - val orderCriteria = - when (orderByTimestamp) { - // when adding column position of 'group by' shift in case columns were removed - Sort.Direction.ASC -> criteriaBuilder.asc(compositeKey.get(PersistentKey::timestamp.name)) - Sort.Direction.DESC -> criteriaBuilder.desc(compositeKey.get(PersistentKey::timestamp.name)) - } + val orderCriteria = when (orderByTimestamp) { + // when adding column position of 'group by' shift in case columns were removed + Sort.Direction.ASC -> criteriaBuilder.asc(timestamp) + Sort.Direction.DESC -> criteriaBuilder.desc(timestamp) + } criteriaQuery.orderBy(orderCriteria) } session.createQuery(criteriaQuery).resultList } } + + fun decryptHashedDistributionList(encryptedBytes: ByteArray): HashedDistributionList { + return HashedDistributionList.decrypt(encryptedBytes, encryptionService) + } } @@ -301,35 +305,33 @@ class DistributionRecords( val receiverRecords: List = emptyList() ) { init { - assert(senderRecords.isNotEmpty() || receiverRecords.isNotEmpty()) { "Must set senderRecords or receiverRecords or both." } + require(senderRecords.isNotEmpty() || receiverRecords.isNotEmpty()) { "Must set senderRecords or receiverRecords or both." } } val size = senderRecords.size + receiverRecords.size } @CordaSerializable -open class DistributionRecord( - open val txId: SecureHash, - open val statesToRecord: StatesToRecord, - open val timestamp: Instant -) +abstract class DistributionRecord { + abstract val txId: SecureHash + abstract val timestamp: Instant +} @CordaSerializable data class SenderDistributionRecord( override val txId: SecureHash, val peerPartyId: Long, // CordaX500Name hashCode() - override val statesToRecord: StatesToRecord, + val statesToRecord: StatesToRecord, override val timestamp: Instant -) : DistributionRecord(txId, statesToRecord, timestamp) +) : DistributionRecord() @CordaSerializable data class ReceiverDistributionRecord( override val txId: SecureHash, val initiatorPartyId: Long, // CordaX500Name hashCode() - val peersToStatesToRecord: Map, // CordaX500Name hashCode() -> StatesToRecord - override val statesToRecord: StatesToRecord, + val encryptedDistributionList: OpaqueBytes, override val timestamp: Instant -) : DistributionRecord(txId, statesToRecord, timestamp) +) : DistributionRecord() @CordaSerializable enum class DistributionRecordType { diff --git a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt index b53d9daeee..451bc813a9 100644 --- a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt @@ -71,6 +71,7 @@ import net.corda.testing.internal.IS_OPENJ9 import net.corda.testing.internal.LogHelper import net.corda.testing.internal.vault.VaultFiller import net.corda.testing.node.internal.FINANCE_CONTRACTS_CORDAPP +import net.corda.testing.node.internal.FINANCE_WORKFLOWS_CORDAPP import net.corda.testing.node.internal.InternalMockNetwork import net.corda.testing.node.internal.InternalMockNodeParameters import net.corda.testing.node.internal.TestStartedNode @@ -140,7 +141,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) { // We run this in parallel threads to help catch any race conditions that may exist. The other tests // we run in the unit test thread exclusively to speed things up, ensure deterministic results and // allow interruption half way through. - mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP), threadPerNode = true) + mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, FINANCE_WORKFLOWS_CORDAPP), threadPerNode = true) val notaryNode = mockNet.defaultNotaryNode val notary = mockNet.defaultNotaryIdentity notaryNode.services.ledger(notary) { @@ -247,7 +248,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) { @Test(timeout=300_000) fun `shutdown and restore`() { Assume.assumeTrue(!IS_OPENJ9) - mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP)) + mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, FINANCE_WORKFLOWS_CORDAPP)) val notaryNode = mockNet.defaultNotaryNode val notary = mockNet.defaultNotaryIdentity notaryNode.services.ledger(notary) { diff --git a/node/src/test/kotlin/net/corda/node/services/ServiceHubConcurrentUsageTest.kt b/node/src/test/kotlin/net/corda/node/services/ServiceHubConcurrentUsageTest.kt index ecba9d248d..9e235cebb1 100644 --- a/node/src/test/kotlin/net/corda/node/services/ServiceHubConcurrentUsageTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/ServiceHubConcurrentUsageTest.kt @@ -13,6 +13,7 @@ import net.corda.core.utilities.getOrThrow import net.corda.finance.DOLLARS import net.corda.finance.contracts.asset.Cash import net.corda.finance.issuedBy +import net.corda.testing.node.internal.CustomCordapp import net.corda.testing.node.internal.FINANCE_CONTRACTS_CORDAPP import net.corda.testing.node.internal.InternalMockNetwork import net.corda.testing.node.internal.startFlow @@ -23,7 +24,8 @@ import rx.schedulers.Schedulers import java.util.concurrent.CountDownLatch class ServiceHubConcurrentUsageTest { - private val mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP)) + private val mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, + CustomCordapp(classes = setOf(TestFlow::class.java)))) @After fun stopNodes() { diff --git a/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt b/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt index b0b4d8313d..df1fa5aa64 100644 --- a/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt @@ -75,7 +75,9 @@ class TimedFlowTests { @JvmStatic fun setup() { mockNet = InternalMockNetwork( - cordappsForAllNodes = listOf(DUMMY_CONTRACTS_CORDAPP, enclosedCordapp()), + cordappsForAllNodes = listOf(DUMMY_CONTRACTS_CORDAPP, + CustomCordapp(classes = setOf(FinalityFlow::class.java)), + enclosedCordapp()), defaultParameters = MockNetworkParameters().withServicePeerAllocationStrategy(InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin()), threadPerNode = true ) diff --git a/node/src/test/kotlin/net/corda/node/services/persistence/DBTransactionStorageLedgerRecoveryTests.kt b/node/src/test/kotlin/net/corda/node/services/persistence/DBTransactionStorageLedgerRecoveryTests.kt index 3e32fef074..1ffd27e736 100644 --- a/node/src/test/kotlin/net/corda/node/services/persistence/DBTransactionStorageLedgerRecoveryTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/persistence/DBTransactionStorageLedgerRecoveryTests.kt @@ -24,6 +24,8 @@ import net.corda.node.services.network.PersistentNetworkMapCache import net.corda.node.services.network.PersistentPartyInfoCache import net.corda.node.services.persistence.DBTransactionStorage.TransactionStatus.IN_FLIGHT import net.corda.node.services.persistence.DBTransactionStorage.TransactionStatus.VERIFIED +import net.corda.node.services.persistence.DBTransactionStorageLedgerRecovery.DBReceiverDistributionRecord +import net.corda.node.services.persistence.DBTransactionStorageLedgerRecovery.DBSenderDistributionRecord import net.corda.nodeapi.internal.DEV_ROOT_CA import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.DatabaseConfig @@ -260,11 +262,12 @@ class DBTransactionStorageLedgerRecoveryTests { transactionRecovery.addReceiverTransactionRecoveryMetadata(receiverTransaction.id, ALICE_NAME, TransactionMetadata(ALICE_NAME, ReceiverDistributionList(encryptedDL, ALL_VISIBLE))) assertEquals(IN_FLIGHT, readTransactionFromDB(receiverTransaction.id).status) - readReceiverDistributionRecordFromDB(receiverTransaction.id).let { - assertEquals(ONLY_RELEVANT, it.statesToRecord) - assertEquals(ALL_VISIBLE, it.peersToStatesToRecord.map { it.value }[0]) - assertEquals(ALICE_NAME, partyInfoCache.getCordaX500NameByPartyId(it.initiatorPartyId)) - assertEquals(setOf(BOB_NAME), it.peersToStatesToRecord.map { (peer, _) -> partyInfoCache.getCordaX500NameByPartyId(peer) }.toSet() ) + readReceiverDistributionRecordFromDB(receiverTransaction.id).let { record -> + val distList = transactionRecovery.decryptHashedDistributionList(record.encryptedDistributionList.bytes) + assertEquals(ONLY_RELEVANT, distList.senderStatesToRecord) + assertEquals(ALL_VISIBLE, distList.peerHashToStatesToRecord.values.first()) + assertEquals(ALICE_NAME, partyInfoCache.getCordaX500NameByPartyId(record.initiatorPartyId)) + assertEquals(setOf(BOB_NAME), distList.peerHashToStatesToRecord.map { (peer) -> partyInfoCache.getCordaX500NameByPartyId(peer) }.toSet() ) } } @@ -323,7 +326,7 @@ class DBTransactionStorageLedgerRecoveryTests { assertThat(roundtrip).isEqualTo(hashedDistList) } - private fun readTransactionFromDB(id: SecureHash): DBTransactionStorage.DBTransaction { + private fun readTransactionFromDB(txId: SecureHash): DBTransactionStorage.DBTransaction { val fromDb = database.transaction { session.createQuery( "from ${DBTransactionStorage.DBTransaction::class.java.name} where txId = :transactionId", @@ -334,22 +337,22 @@ class DBTransactionStorageLedgerRecoveryTests { return fromDb[0] } - private fun readSenderDistributionRecordFromDB(id: SecureHash? = null): List { + private fun readSenderDistributionRecordFromDB(txId: SecureHash? = null): List { return database.transaction { - if (id != null) + if (txId != null) session.createQuery( - "from ${DBTransactionStorageLedgerRecovery.DBSenderDistributionRecord::class.java.name} where txId = :transactionId", - DBTransactionStorageLedgerRecovery.DBSenderDistributionRecord::class.java - ).setParameter("transactionId", id.toString()).resultList.map { it.toSenderDistributionRecord() } + "from ${DBSenderDistributionRecord::class.java.name} where txId = :transactionId", + DBSenderDistributionRecord::class.java + ).setParameter("transactionId", txId.toString()).resultList.map { it.toSenderDistributionRecord() } else session.createQuery( - "from ${DBTransactionStorageLedgerRecovery.DBSenderDistributionRecord::class.java.name}", - DBTransactionStorageLedgerRecovery.DBSenderDistributionRecord::class.java + "from ${DBSenderDistributionRecord::class.java.name}", + DBSenderDistributionRecord::class.java ).resultList.map { it.toSenderDistributionRecord() } } } - private fun readReceiverDistributionRecordFromDB(id: SecureHash): ReceiverDistributionRecord { + private fun readReceiverDistributionRecordFromDB(txId: SecureHash): ReceiverDistributionRecord { val fromDb = database.transaction { session.createQuery( "from ${DBTransactionStorageLedgerRecovery.DBReceiverDistributionRecord::class.java.name} where txId = :transactionId", diff --git a/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt b/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt index def6530e5e..9c2628ff45 100644 --- a/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt @@ -58,6 +58,7 @@ import net.corda.testing.internal.IS_OPENJ9 import net.corda.testing.internal.LogHelper import net.corda.testing.node.InMemoryMessagingNetwork.MessageTransfer import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin +import net.corda.testing.node.internal.CustomCordapp import net.corda.testing.node.internal.DUMMY_CONTRACTS_CORDAPP import net.corda.testing.node.internal.FINANCE_CONTRACTS_CORDAPP import net.corda.testing.node.internal.InternalMockNetwork @@ -124,7 +125,7 @@ class FlowFrameworkTests { @Before fun setUpMockNet() { mockNet = InternalMockNetwork( - cordappsForAllNodes = listOf(DUMMY_CONTRACTS_CORDAPP, FINANCE_CONTRACTS_CORDAPP), + cordappsForAllNodes = listOf(DUMMY_CONTRACTS_CORDAPP, FINANCE_CONTRACTS_CORDAPP, CustomCordapp(setOf("net.corda.node.services.statemachine"))), servicePeerAllocationStrategy = RoundRobin() ) diff --git a/testing/cordapps/cashobservers/build.gradle b/testing/cordapps/cashobservers/build.gradle index e8f0d47d5f..8222caae16 100644 --- a/testing/cordapps/cashobservers/build.gradle +++ b/testing/cordapps/cashobservers/build.gradle @@ -1,10 +1,10 @@ apply plugin: 'kotlin' -//apply plugin: 'net.corda.plugins.cordapp' +apply plugin: 'net.corda.plugins.cordapp' //apply plugin: 'net.corda.plugins.quasar-utils' dependencies { - compile project(":core") - compile project(':finance:workflows') + cordaCompile project(":core") + cordapp project(':finance:workflows') } jar { @@ -14,4 +14,18 @@ jar { // Driver will not include it as part of an out-of-process node. attributes('Corda-Testing': true) } +} + +cordapp { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + workflow { + name "Corda Cash Observers Test CorDapp" + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" + } + signing { + enabled false + } } \ No newline at end of file diff --git a/testing/cordapps/dbfailure/dbfworkflows/build.gradle b/testing/cordapps/dbfailure/dbfworkflows/build.gradle index 26e0058cc5..221b063236 100644 --- a/testing/cordapps/dbfailure/dbfworkflows/build.gradle +++ b/testing/cordapps/dbfailure/dbfworkflows/build.gradle @@ -1,10 +1,10 @@ apply plugin: 'kotlin' -//apply plugin: 'net.corda.plugins.cordapp' +apply plugin: 'net.corda.plugins.cordapp' //apply plugin: 'net.corda.plugins.quasar-utils' dependencies { - compile project(":core") - compile project(":testing:cordapps:dbfailure:dbfcontracts") + cordaCompile project(":core") + cordapp project(":testing:cordapps:dbfailure:dbfcontracts") } jar { @@ -14,4 +14,18 @@ jar { // Driver will not include it as part of an out-of-process node. attributes('Corda-Testing': true) } +} + +cordapp { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + workflow { + name "Corda DB Failure Test CorDapp" + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" + } + signing { + enabled false + } } \ No newline at end of file