From 2fae95c58f97d7052d171303399e06756b0bfbce Mon Sep 17 00:00:00 2001 From: Florian Friemel Date: Wed, 22 Aug 2018 13:16:07 +0100 Subject: [PATCH] [CORDA-1917] Fix smoke test (#3823) --- .../corda/core/cordapp/CordappSmokeTest.kt | 66 +++++++++++++++++-- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt b/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt index 6bc2743699..44195477d0 100644 --- a/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt +++ b/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt @@ -1,23 +1,36 @@ package net.corda.core.cordapp import co.paralleluniverse.fibers.Suspendable +import net.corda.core.crypto.Crypto.generateKeyPair +import net.corda.core.crypto.sign import net.corda.core.flows.* import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party -import net.corda.core.internal.copyToDirectory -import net.corda.core.internal.createDirectories -import net.corda.core.internal.div -import net.corda.core.internal.list +import net.corda.core.identity.PartyAndCertificate +import net.corda.core.internal.* import net.corda.core.messaging.startFlow +import net.corda.core.node.NodeInfo +import net.corda.core.serialization.serialize +import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.unwrap +import net.corda.nodeapi.internal.DEV_INTERMEDIATE_CA +import net.corda.nodeapi.internal.DEV_ROOT_CA +import net.corda.nodeapi.internal.SignedNodeInfo import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.createDevNodeCa +import net.corda.nodeapi.internal.crypto.CertificateType +import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.smoketesting.NodeConfig import net.corda.smoketesting.NodeProcess import net.corda.smoketesting.NodeProcess.Companion.CORDAPPS_DIR_NAME import org.assertj.core.api.Assertions.assertThat import org.junit.Test +import java.nio.file.Path import java.nio.file.Paths +import java.security.KeyPair +import java.security.PrivateKey +import java.security.PublicKey import java.util.concurrent.atomic.AtomicInteger import kotlin.streams.toList @@ -40,13 +53,21 @@ class CordappSmokeTest { @Test fun `FlowContent appName returns the filename of the CorDapp jar`() { - val cordappsDir = (factory.baseDirectory(aliceConfig) / CORDAPPS_DIR_NAME).createDirectories() + val baseDir = factory.baseDirectory(aliceConfig) + val cordappsDir = (baseDir / CORDAPPS_DIR_NAME).createDirectories() // Find the jar file for the smoke tests of this module val selfCordapp = Paths.get("build", "libs").list { it.filter { "-smokeTests" in it.toString() }.toList().single() } selfCordapp.copyToDirectory(cordappsDir) + // The `nodeReadyFuture` in the persistent network map cache will not complete unless there is at least one other + // node in the network. We work around this limitation by putting another node info file in the additional-node-info + // folder. + // TODO clean this up after we refactor the persistent network map cache / network map updater + val additionalNodeInfoDir = (baseDir / "additional-node-infos").createDirectories() + createDummyNodeInfo(additionalNodeInfoDir) + factory.create(aliceConfig).use { alice -> alice.connect().use { connectionToAlice -> val aliceIdentity = connectionToAlice.proxy.nodeInfo().legalIdentitiesAndCerts.first().party @@ -90,4 +111,39 @@ class CordappSmokeTest { otherPartySession.send(sessionInitContext) } } + + private fun createDummyNodeInfo(additionalNodeInfoDir: Path) { + val dummyKeyPair = generateKeyPair() + val nodeInfo = createNodeInfoWithSingleIdentity(CordaX500Name(organisation = "Bob Corp", locality = "Madrid", country = "ES"), dummyKeyPair, dummyKeyPair.public) + val signedNodeInfo = signWith(nodeInfo, listOf(dummyKeyPair.private)) + (additionalNodeInfoDir / "nodeInfo-41408E093F95EAD51F6892C34DEB65AE1A3569A4B0E5744769A1B485AF8E04B5").write(signedNodeInfo.serialize().bytes) + } + + private fun createNodeInfoWithSingleIdentity(name: CordaX500Name, nodeKeyPair: KeyPair, identityCertPublicKey: PublicKey): NodeInfo { + val nodeCertificateAndKeyPair = createDevNodeCa(DEV_INTERMEDIATE_CA, name, nodeKeyPair) + val identityCert = X509Utilities.createCertificate( + CertificateType.LEGAL_IDENTITY, + nodeCertificateAndKeyPair.certificate, + nodeCertificateAndKeyPair.keyPair, + nodeCertificateAndKeyPair.certificate.subjectX500Principal, + identityCertPublicKey) + val certPath = X509Utilities.buildCertPath( + identityCert, + nodeCertificateAndKeyPair.certificate, + DEV_INTERMEDIATE_CA.certificate, + DEV_ROOT_CA.certificate) + val partyAndCertificate = PartyAndCertificate(certPath) + return NodeInfo( + listOf(NetworkHostAndPort("my.${partyAndCertificate.party.name.organisation}.com", 1234)), + listOf(partyAndCertificate), + 1, + 1 + ) + } + + private fun signWith(nodeInfo: NodeInfo, keys: List): SignedNodeInfo { + val serialized = nodeInfo.serialize() + val signatures = keys.map { it.sign(serialized.bytes) } + return SignedNodeInfo(serialized, signatures) + } }