mirror of
https://github.com/corda/corda.git
synced 2025-06-01 23:20:54 +00:00
CORDA-4123 Change MockNetworkParameterStorage to not rehash NetworkParameters (#6872)
* CORDA-4123 Change Mock Network Parameter Storage to not rehash the Network Parameters * Fix Detekt
This commit is contained in:
parent
1a7401472f
commit
7261442c98
@ -29,6 +29,7 @@ import net.corda.core.identity.Party
|
|||||||
import net.corda.core.internal.concurrent.transpose
|
import net.corda.core.internal.concurrent.transpose
|
||||||
import net.corda.core.internal.copyBytes
|
import net.corda.core.internal.copyBytes
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
|
import net.corda.core.node.ServiceHub
|
||||||
import net.corda.core.serialization.CustomSerializationScheme
|
import net.corda.core.serialization.CustomSerializationScheme
|
||||||
import net.corda.core.serialization.SerializationSchemeContext
|
import net.corda.core.serialization.SerializationSchemeContext
|
||||||
import net.corda.core.serialization.internal.CustomSerializationSchemeUtils.Companion.getSchemeIdIfCustomSerializationMagic
|
import net.corda.core.serialization.internal.CustomSerializationSchemeUtils.Companion.getSchemeIdIfCustomSerializationMagic
|
||||||
@ -55,12 +56,28 @@ import org.objenesis.strategy.InstantiatorStrategy
|
|||||||
import org.objenesis.strategy.StdInstantiatorStrategy
|
import org.objenesis.strategy.StdInstantiatorStrategy
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
|
import java.security.PublicKey
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class CustomSerializationSchemeDriverTest {
|
class CustomSerializationSchemeDriverTest {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private fun createWireTx(serviceHub: ServiceHub, notary: Party, key: PublicKey, schemeId: Int): WireTransaction {
|
||||||
|
val outputState = TransactionState(
|
||||||
|
data = DummyContract.DummyState(),
|
||||||
|
contract = DummyContract::class.java.name,
|
||||||
|
notary = notary,
|
||||||
|
constraint = AlwaysAcceptAttachmentConstraint
|
||||||
|
)
|
||||||
|
val builder = TransactionBuilder()
|
||||||
|
.addOutputState(outputState)
|
||||||
|
.addCommand(DummyCommandData, key)
|
||||||
|
return builder.toWireTransaction(serviceHub, schemeId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test(timeout = 300_000)
|
@Test(timeout = 300_000)
|
||||||
fun `flow can send wire transaction serialized with custom kryo serializer`() {
|
fun `flow can send wire transaction serialized with custom kryo serializer`() {
|
||||||
driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true, cordappsForAllNodes = listOf(enclosedCordapp()))) {
|
driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true, cordappsForAllNodes = listOf(enclosedCordapp()))) {
|
||||||
@ -120,16 +137,7 @@ class CustomSerializationSchemeDriverTest {
|
|||||||
class WriteTxToLedgerFlow(val counterparty: Party, val notary: Party) : FlowLogic<SecureHash>() {
|
class WriteTxToLedgerFlow(val counterparty: Party, val notary: Party) : FlowLogic<SecureHash>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call(): SecureHash {
|
override fun call(): SecureHash {
|
||||||
val outputState = TransactionState(
|
val wireTx = createWireTx(serviceHub, notary, counterparty.owningKey, KryoScheme.SCHEME_ID)
|
||||||
data = DummyContract.DummyState(),
|
|
||||||
contract = DummyContract::class.java.name,
|
|
||||||
notary = notary,
|
|
||||||
constraint = AlwaysAcceptAttachmentConstraint
|
|
||||||
)
|
|
||||||
val builder = TransactionBuilder()
|
|
||||||
.addOutputState(outputState)
|
|
||||||
.addCommand(DummyCommandData, counterparty.owningKey)
|
|
||||||
val wireTx = builder.toWireTransaction(serviceHub, KryoScheme.SCHEME_ID)
|
|
||||||
val partSignedTx = signWireTx(wireTx)
|
val partSignedTx = signWireTx(wireTx)
|
||||||
val session = initiateFlow(counterparty)
|
val session = initiateFlow(counterparty)
|
||||||
val fullySignedTx = subFlow(CollectSignaturesFlow(partSignedTx, setOf(session)))
|
val fullySignedTx = subFlow(CollectSignaturesFlow(partSignedTx, setOf(session)))
|
||||||
@ -174,17 +182,7 @@ class CustomSerializationSchemeDriverTest {
|
|||||||
class CheckComponentGroupsFlow(val notary: Party) : FlowLogic<Boolean>() {
|
class CheckComponentGroupsFlow(val notary: Party) : FlowLogic<Boolean>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call(): Boolean {
|
override fun call(): Boolean {
|
||||||
val outputState = TransactionState(
|
val wtx = createWireTx(serviceHub, notary, notary.owningKey, KryoScheme.SCHEME_ID)
|
||||||
data = DummyContract.DummyState(),
|
|
||||||
contract = DummyContract::class.java.name,
|
|
||||||
notary = notary,
|
|
||||||
constraint = AlwaysAcceptAttachmentConstraint
|
|
||||||
)
|
|
||||||
val builder = TransactionBuilder()
|
|
||||||
.addOutputState(outputState)
|
|
||||||
.addCommand(DummyCommandData, notary.owningKey)
|
|
||||||
|
|
||||||
val wtx = builder.toWireTransaction(serviceHub, KryoScheme.SCHEME_ID)
|
|
||||||
var success = true
|
var success = true
|
||||||
for (group in wtx.componentGroups) {
|
for (group in wtx.componentGroups) {
|
||||||
//Component groups are lazily serialized as we iterate through.
|
//Component groups are lazily serialized as we iterate through.
|
||||||
@ -230,23 +228,21 @@ class CustomSerializationSchemeDriverTest {
|
|||||||
class SendFlow(val counterparty: Party) : FlowLogic<Boolean>() {
|
class SendFlow(val counterparty: Party) : FlowLogic<Boolean>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call(): Boolean {
|
override fun call(): Boolean {
|
||||||
val outputState = TransactionState(
|
val wtx = createWireTx(serviceHub, counterparty, counterparty.owningKey, KryoScheme.SCHEME_ID)
|
||||||
data = DummyContract.DummyState(),
|
|
||||||
contract = DummyContract::class.java.name,
|
|
||||||
notary = counterparty,
|
|
||||||
constraint = AlwaysAcceptAttachmentConstraint
|
|
||||||
)
|
|
||||||
val builder = TransactionBuilder()
|
|
||||||
.addOutputState(outputState)
|
|
||||||
.addCommand(DummyCommandData, counterparty.owningKey)
|
|
||||||
|
|
||||||
val wtx = builder.toWireTransaction(serviceHub, KryoScheme.SCHEME_ID)
|
|
||||||
val session = initiateFlow(counterparty)
|
val session = initiateFlow(counterparty)
|
||||||
session.send(wtx)
|
session.send(wtx)
|
||||||
return session.receive<Boolean>().unwrap {it}
|
return session.receive<Boolean>().unwrap {it}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@StartableByRPC
|
||||||
|
class CreateWireTxFlow(val counterparty: Party) : FlowLogic<WireTransaction>() {
|
||||||
|
@Suspendable
|
||||||
|
override fun call(): WireTransaction {
|
||||||
|
return createWireTx(serviceHub, counterparty, counterparty.owningKey, KryoScheme.SCHEME_ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@InitiatedBy(SendFlow::class)
|
@InitiatedBy(SendFlow::class)
|
||||||
class ReceiveFlow(private val session: FlowSession): FlowLogic<Unit>() {
|
class ReceiveFlow(private val session: FlowSession): FlowLogic<Unit>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
package net.corda.node
|
||||||
|
|
||||||
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.serialization.SerializedBytes
|
||||||
|
import net.corda.core.serialization.deserialize
|
||||||
|
import net.corda.node.CustomSerializationSchemeDriverTest.CreateWireTxFlow
|
||||||
|
import net.corda.node.CustomSerializationSchemeDriverTest.WriteTxToLedgerFlow
|
||||||
|
import net.corda.testing.core.ALICE_NAME
|
||||||
|
import net.corda.testing.core.BOB_NAME
|
||||||
|
import net.corda.testing.node.internal.CustomCordapp
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
|
import net.corda.testing.node.internal.InternalMockNodeParameters
|
||||||
|
import net.corda.testing.node.internal.enclosedCordapp
|
||||||
|
import net.corda.testing.node.internal.startFlow
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertNotNull
|
||||||
|
|
||||||
|
class CustomSerializationSchemeMockNetworkTest {
|
||||||
|
|
||||||
|
private lateinit var mockNetwork : InternalMockNetwork
|
||||||
|
|
||||||
|
val customSchemeCordapp: CustomCordapp = CustomSerializationSchemeDriverTest().enclosedCordapp()
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
mockNetwork = InternalMockNetwork(cordappsForAllNodes = listOf(customSchemeCordapp))
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun shutdown() {
|
||||||
|
mockNetwork.stopNodes()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `transactions network parameter hash is correct`() {
|
||||||
|
val alice = mockNetwork.createNode(InternalMockNodeParameters(legalName = ALICE_NAME))
|
||||||
|
val bob = mockNetwork.createNode(InternalMockNodeParameters(legalName = BOB_NAME))
|
||||||
|
val flow = alice.services.startFlow (CreateWireTxFlow(bob.info.legalIdentities.single()))
|
||||||
|
mockNetwork.runNetwork()
|
||||||
|
val wireTx = flow.resultFuture.get()
|
||||||
|
/** The NetworkParmeters is the last component in the list of component groups. If we ever change this this
|
||||||
|
* in [net.corda.core.internal.createComponentGroups] this test will need to be updated.*/
|
||||||
|
val serializedHash = SerializedBytes<SecureHash>(wireTx.componentGroups.last().components.single().bytes)
|
||||||
|
assertEquals(alice.internals.networkParametersStorage.defaultHash, serializedHash.deserialize())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `transaction can be written to the ledger`() {
|
||||||
|
val alice = mockNetwork.createNode(InternalMockNodeParameters(legalName = ALICE_NAME))
|
||||||
|
val bob = mockNetwork.createNode(InternalMockNodeParameters(legalName = BOB_NAME))
|
||||||
|
val flow = alice.services.startFlow (WriteTxToLedgerFlow(bob.info.legalIdentities.single(),
|
||||||
|
mockNetwork.notaryNodes.single().info.legalIdentities.single()))
|
||||||
|
mockNetwork.runNetwork()
|
||||||
|
val txId = flow.resultFuture.get()
|
||||||
|
val getTxFlow = bob.services.startFlow(CustomSerializationSchemeDriverTest.GetTxFromDBFlow(txId))
|
||||||
|
mockNetwork.runNetwork()
|
||||||
|
assertNotNull(getTxFlow.resultFuture.get())
|
||||||
|
}
|
||||||
|
}
|
@ -20,17 +20,28 @@ import java.time.Instant
|
|||||||
class MockNetworkParametersStorage(private var currentParameters: NetworkParameters = testNetworkParameters(modifiedTime = Instant.MIN)) : NetworkParametersStorage {
|
class MockNetworkParametersStorage(private var currentParameters: NetworkParameters = testNetworkParameters(modifiedTime = Instant.MIN)) : NetworkParametersStorage {
|
||||||
private val hashToParametersMap: HashMap<SecureHash, NetworkParameters> = HashMap()
|
private val hashToParametersMap: HashMap<SecureHash, NetworkParameters> = HashMap()
|
||||||
private val hashToSignedParametersMap: HashMap<SecureHash, SignedNetworkParameters> = HashMap()
|
private val hashToSignedParametersMap: HashMap<SecureHash, SignedNetworkParameters> = HashMap()
|
||||||
|
override var currentHash = currentParameters.computeHash()
|
||||||
|
override val defaultHash: SecureHash get() = currentHash
|
||||||
init {
|
init {
|
||||||
storeCurrentParameters()
|
storeCurrentParameters()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun NetworkParameters.computeHash(): SecureHash {
|
||||||
|
return withTestSerializationEnvIfNotSet {
|
||||||
|
this.serialize().hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun setCurrentParametersUnverified(networkParameters: NetworkParameters) {
|
fun setCurrentParametersUnverified(networkParameters: NetworkParameters) {
|
||||||
currentParameters = networkParameters
|
currentParameters = networkParameters
|
||||||
|
currentHash = currentParameters.computeHash()
|
||||||
storeCurrentParameters()
|
storeCurrentParameters()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setCurrentParameters(currentSignedParameters: SignedDataWithCert<NetworkParameters>, trustRoots: Set<X509Certificate>) {
|
override fun setCurrentParameters(currentSignedParameters: SignedDataWithCert<NetworkParameters>, trustRoots: Set<X509Certificate>) {
|
||||||
setCurrentParametersUnverified(currentSignedParameters.verifiedNetworkParametersCert(trustRoots))
|
currentParameters = currentSignedParameters.verifiedNetworkParametersCert(trustRoots)
|
||||||
|
currentHash = currentSignedParameters.raw.hash
|
||||||
|
storeCurrentParameters()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun lookupSigned(hash: SecureHash): SignedDataWithCert<NetworkParameters>? {
|
override fun lookupSigned(hash: SecureHash): SignedDataWithCert<NetworkParameters>? {
|
||||||
@ -39,13 +50,6 @@ class MockNetworkParametersStorage(private var currentParameters: NetworkParamet
|
|||||||
|
|
||||||
override fun hasParameters(hash: SecureHash): Boolean = hash in hashToParametersMap
|
override fun hasParameters(hash: SecureHash): Boolean = hash in hashToParametersMap
|
||||||
|
|
||||||
override val currentHash: SecureHash
|
|
||||||
get() {
|
|
||||||
return withTestSerializationEnvIfNotSet {
|
|
||||||
currentParameters.serialize().hash
|
|
||||||
}
|
|
||||||
}
|
|
||||||
override val defaultHash: SecureHash get() = currentHash
|
|
||||||
override fun lookup(hash: SecureHash): NetworkParameters? = hashToParametersMap[hash]
|
override fun lookup(hash: SecureHash): NetworkParameters? = hashToParametersMap[hash]
|
||||||
override fun getEpochFromHash(hash: SecureHash): Int? = lookup(hash)?.epoch
|
override fun getEpochFromHash(hash: SecureHash): Int? = lookup(hash)?.epoch
|
||||||
override fun saveParameters(signedNetworkParameters: SignedDataWithCert<NetworkParameters>) {
|
override fun saveParameters(signedNetworkParameters: SignedDataWithCert<NetworkParameters>) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user