mirror of
https://github.com/corda/corda.git
synced 2024-12-20 21:43:14 +00:00
parent
e4f5e16bf4
commit
953a4a3790
@ -1684,27 +1684,6 @@ public @interface net.corda.core.messaging.RPCReturnsObservables
|
|||||||
@org.jetbrains.annotations.NotNull public abstract net.corda.core.messaging.FlowHandle startFlow(net.corda.core.flows.FlowLogic)
|
@org.jetbrains.annotations.NotNull public abstract net.corda.core.messaging.FlowHandle startFlow(net.corda.core.flows.FlowLogic)
|
||||||
@org.jetbrains.annotations.NotNull public abstract net.corda.core.messaging.FlowProgressHandle startTrackedFlow(net.corda.core.flows.FlowLogic)
|
@org.jetbrains.annotations.NotNull public abstract net.corda.core.messaging.FlowProgressHandle startTrackedFlow(net.corda.core.flows.FlowLogic)
|
||||||
##
|
##
|
||||||
@net.corda.core.serialization.CordaSerializable public final class net.corda.core.node.NetworkParameters extends java.lang.Object
|
|
||||||
public <init>(int, List, java.time.Duration, int, int, java.time.Instant, int)
|
|
||||||
public final int component1()
|
|
||||||
@org.jetbrains.annotations.NotNull public final List component2()
|
|
||||||
@org.jetbrains.annotations.NotNull public final java.time.Duration component3()
|
|
||||||
public final int component4()
|
|
||||||
public final int component5()
|
|
||||||
@org.jetbrains.annotations.NotNull public final java.time.Instant component6()
|
|
||||||
public final int component7()
|
|
||||||
@org.jetbrains.annotations.NotNull public final net.corda.core.node.NetworkParameters copy(int, List, java.time.Duration, int, int, java.time.Instant, int)
|
|
||||||
public boolean equals(Object)
|
|
||||||
public final int getEpoch()
|
|
||||||
@org.jetbrains.annotations.NotNull public final java.time.Duration getEventHorizon()
|
|
||||||
public final int getMaxMessageSize()
|
|
||||||
public final int getMaxTransactionSize()
|
|
||||||
public final int getMinimumPlatformVersion()
|
|
||||||
@org.jetbrains.annotations.NotNull public final java.time.Instant getModifiedTime()
|
|
||||||
@org.jetbrains.annotations.NotNull public final List getNotaries()
|
|
||||||
public int hashCode()
|
|
||||||
public String toString()
|
|
||||||
##
|
|
||||||
@net.corda.core.serialization.CordaSerializable public final class net.corda.core.node.NodeInfo extends java.lang.Object
|
@net.corda.core.serialization.CordaSerializable public final class net.corda.core.node.NodeInfo extends java.lang.Object
|
||||||
public <init>(List, List, int, long)
|
public <init>(List, List, int, long)
|
||||||
@org.jetbrains.annotations.NotNull public final List component1()
|
@org.jetbrains.annotations.NotNull public final List component1()
|
||||||
@ -1723,17 +1702,6 @@ public @interface net.corda.core.messaging.RPCReturnsObservables
|
|||||||
public final boolean isLegalIdentity(net.corda.core.identity.Party)
|
public final boolean isLegalIdentity(net.corda.core.identity.Party)
|
||||||
public String toString()
|
public String toString()
|
||||||
##
|
##
|
||||||
@net.corda.core.serialization.CordaSerializable public final class net.corda.core.node.NotaryInfo extends java.lang.Object
|
|
||||||
public <init>(net.corda.core.identity.Party, boolean)
|
|
||||||
@org.jetbrains.annotations.NotNull public final net.corda.core.identity.Party component1()
|
|
||||||
public final boolean component2()
|
|
||||||
@org.jetbrains.annotations.NotNull public final net.corda.core.node.NotaryInfo copy(net.corda.core.identity.Party, boolean)
|
|
||||||
public boolean equals(Object)
|
|
||||||
@org.jetbrains.annotations.NotNull public final net.corda.core.identity.Party getIdentity()
|
|
||||||
public final boolean getValidating()
|
|
||||||
public int hashCode()
|
|
||||||
public String toString()
|
|
||||||
##
|
|
||||||
@net.corda.core.DoNotImplement public interface net.corda.core.node.ServiceHub extends net.corda.core.node.ServicesForResolution
|
@net.corda.core.DoNotImplement public interface net.corda.core.node.ServiceHub extends net.corda.core.node.ServicesForResolution
|
||||||
@org.jetbrains.annotations.NotNull public abstract net.corda.core.transactions.SignedTransaction addSignature(net.corda.core.transactions.SignedTransaction)
|
@org.jetbrains.annotations.NotNull public abstract net.corda.core.transactions.SignedTransaction addSignature(net.corda.core.transactions.SignedTransaction)
|
||||||
@org.jetbrains.annotations.NotNull public abstract net.corda.core.transactions.SignedTransaction addSignature(net.corda.core.transactions.SignedTransaction, java.security.PublicKey)
|
@org.jetbrains.annotations.NotNull public abstract net.corda.core.transactions.SignedTransaction addSignature(net.corda.core.transactions.SignedTransaction, java.security.PublicKey)
|
||||||
|
2
.idea/compiler.xml
generated
2
.idea/compiler.xml
generated
@ -43,6 +43,8 @@
|
|||||||
<module name="docs_source_example-code_main" target="1.8" />
|
<module name="docs_source_example-code_main" target="1.8" />
|
||||||
<module name="docs_source_example-code_test" target="1.8" />
|
<module name="docs_source_example-code_test" target="1.8" />
|
||||||
<module name="docs_test" target="1.8" />
|
<module name="docs_test" target="1.8" />
|
||||||
|
<module name="experimental-kryo-hook_main" target="1.8" />
|
||||||
|
<module name="experimental-kryo-hook_test" target="1.8" />
|
||||||
<module name="example-code_integrationTest" target="1.8" />
|
<module name="example-code_integrationTest" target="1.8" />
|
||||||
<module name="example-code_main" target="1.8" />
|
<module name="example-code_main" target="1.8" />
|
||||||
<module name="example-code_test" target="1.8" />
|
<module name="example-code_test" target="1.8" />
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
package net.corda.core.node
|
|
||||||
|
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
|
||||||
import java.time.Duration
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @property minimumPlatformVersion
|
|
||||||
* @property notaries
|
|
||||||
* @property eventHorizon
|
|
||||||
* @property maxMessageSize Maximum P2P message sent over the wire in bytes.
|
|
||||||
* @property maxTransactionSize Maximum permitted transaction size in bytes.
|
|
||||||
* @property modifiedTime
|
|
||||||
* @property epoch Version number of the network parameters. Starting from 1, this will always increment on each new set
|
|
||||||
* of parameters.
|
|
||||||
*/
|
|
||||||
// TODO Wire up the parameters
|
|
||||||
@CordaSerializable
|
|
||||||
data class NetworkParameters(
|
|
||||||
val minimumPlatformVersion: Int,
|
|
||||||
val notaries: List<NotaryInfo>,
|
|
||||||
val eventHorizon: Duration,
|
|
||||||
val maxMessageSize: Int,
|
|
||||||
val maxTransactionSize: Int,
|
|
||||||
val modifiedTime: Instant,
|
|
||||||
val epoch: Int
|
|
||||||
) {
|
|
||||||
init {
|
|
||||||
require(minimumPlatformVersion > 0) { "minimumPlatformVersion must be at least 1" }
|
|
||||||
require(notaries.distinctBy { it.identity } == notaries) { "Duplicate notary identities" }
|
|
||||||
require(epoch > 0) { "epoch must be at least 1" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@CordaSerializable
|
|
||||||
data class NotaryInfo(val identity: Party, val validating: Boolean)
|
|
@ -53,6 +53,7 @@ interface NetworkMapCacheBase {
|
|||||||
*
|
*
|
||||||
* Note that the identities are sorted based on legal name, and the ordering might change once new notaries are introduced.
|
* Note that the identities are sorted based on legal name, and the ordering might change once new notaries are introduced.
|
||||||
*/
|
*/
|
||||||
|
// TODO this list will be taken from NetworkParameters distributed by NetworkMap.
|
||||||
val notaryIdentities: List<Party>
|
val notaryIdentities: List<Party>
|
||||||
// DOCEND 1
|
// DOCEND 1
|
||||||
|
|
||||||
@ -116,7 +117,7 @@ interface NetworkMapCacheBase {
|
|||||||
fun getNotary(name: CordaX500Name): Party? = notaryIdentities.firstOrNull { it.name == name }
|
fun getNotary(name: CordaX500Name): Party? = notaryIdentities.firstOrNull { it.name == name }
|
||||||
// DOCEND 2
|
// DOCEND 2
|
||||||
|
|
||||||
/** Returns true if and only if the given [Party] is a notary, which is defined by the network parameters. */
|
/** Checks whether a given party is an advertised notary identity. */
|
||||||
fun isNotary(party: Party): Boolean = party in notaryIdentities
|
fun isNotary(party: Party): Boolean = party in notaryIdentities
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,8 +13,6 @@ import net.corda.core.identity.CordaX500Name
|
|||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.deleteIfExists
|
import net.corda.core.internal.deleteIfExists
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.node.NotaryInfo
|
|
||||||
import net.corda.core.node.services.NotaryService
|
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
@ -23,12 +21,11 @@ import net.corda.core.utilities.getOrThrow
|
|||||||
import net.corda.node.internal.StartedNode
|
import net.corda.node.internal.StartedNode
|
||||||
import net.corda.node.services.config.BFTSMaRtConfiguration
|
import net.corda.node.services.config.BFTSMaRtConfiguration
|
||||||
import net.corda.node.services.config.NotaryConfig
|
import net.corda.node.services.config.NotaryConfig
|
||||||
|
import net.corda.node.services.transactions.BFTNonValidatingNotaryService
|
||||||
import net.corda.node.services.transactions.minClusterSize
|
import net.corda.node.services.transactions.minClusterSize
|
||||||
import net.corda.node.services.transactions.minCorrectReplicas
|
import net.corda.node.services.transactions.minCorrectReplicas
|
||||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||||
import net.corda.testing.chooseIdentity
|
import net.corda.testing.chooseIdentity
|
||||||
import net.corda.testing.common.internal.NetworkParametersCopier
|
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.dummyCommand
|
import net.corda.testing.dummyCommand
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
@ -57,26 +54,19 @@ class BFTNotaryServiceTests {
|
|||||||
|
|
||||||
notary = ServiceIdentityGenerator.generateToDisk(
|
notary = ServiceIdentityGenerator.generateToDisk(
|
||||||
replicaIds.map { mockNet.baseDirectory(mockNet.nextNodeId + it) },
|
replicaIds.map { mockNet.baseDirectory(mockNet.nextNodeId + it) },
|
||||||
CordaX500Name("BFT", "Zurich", "CH"),
|
CordaX500Name(BFTNonValidatingNotaryService.id, "BFT", "Zurich", "CH")
|
||||||
NotaryService.constructId(validating = false, bft = true))
|
)
|
||||||
|
|
||||||
val networkParameters = NetworkParametersCopier(testNetworkParameters(listOf(NotaryInfo(notary, false))))
|
|
||||||
|
|
||||||
val clusterAddresses = replicaIds.map { NetworkHostAndPort("localhost", 11000 + it * 10) }
|
val clusterAddresses = replicaIds.map { NetworkHostAndPort("localhost", 11000 + it * 10) }
|
||||||
|
|
||||||
val nodes = replicaIds.map { replicaId ->
|
replicaIds.forEach { replicaId ->
|
||||||
mockNet.createUnstartedNode(MockNodeParameters(configOverrides = {
|
mockNet.createNode(MockNodeParameters(configOverrides = {
|
||||||
val notary = NotaryConfig(validating = false, bftSMaRt = BFTSMaRtConfiguration(replicaId, clusterAddresses, exposeRaces = exposeRaces))
|
val notary = NotaryConfig(validating = false, bftSMaRt = BFTSMaRtConfiguration(replicaId, clusterAddresses, exposeRaces = exposeRaces))
|
||||||
doReturn(notary).whenever(it).notary
|
doReturn(notary).whenever(it).notary
|
||||||
}))
|
}))
|
||||||
} + mockNet.createUnstartedNode()
|
}
|
||||||
|
|
||||||
// MockNetwork doesn't support BFT clusters, so we create all the nodes we need unstarted, and then install the
|
node = mockNet.createNode()
|
||||||
// network-parameters in their directories before they're started.
|
|
||||||
node = nodes.map { node ->
|
|
||||||
networkParameters.install(mockNet.baseDirectory(node.id))
|
|
||||||
node.start()
|
|
||||||
}.last()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Failure mode is the redundant replica gets stuck in startup, so we can't dispose it cleanly at the end. */
|
/** Failure mode is the redundant replica gets stuck in startup, so we can't dispose it cleanly at the end. */
|
||||||
|
@ -13,6 +13,7 @@ import net.corda.finance.flows.CashIssueFlow
|
|||||||
import net.corda.finance.flows.CashPaymentFlow
|
import net.corda.finance.flows.CashPaymentFlow
|
||||||
import net.corda.node.services.Permissions.Companion.invokeRpc
|
import net.corda.node.services.Permissions.Companion.invokeRpc
|
||||||
import net.corda.node.services.Permissions.Companion.startFlow
|
import net.corda.node.services.Permissions.Companion.startFlow
|
||||||
|
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.driver.NodeHandle
|
||||||
@ -41,7 +42,7 @@ class DistributedServiceTests {
|
|||||||
|
|
||||||
driver(
|
driver(
|
||||||
extraCordappPackagesToScan = listOf("net.corda.finance.contracts"),
|
extraCordappPackagesToScan = listOf("net.corda.finance.contracts"),
|
||||||
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, rpcUsers = listOf(testUser), cluster = ClusterSpec.Raft(clusterSize = 3))))
|
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name.copy(commonName = RaftValidatingNotaryService.id), rpcUsers = listOf(testUser), cluster = ClusterSpec.Raft(clusterSize = 3))))
|
||||||
{
|
{
|
||||||
alice = startNode(providedName = ALICE.name, rpcUsers = listOf(testUser)).getOrThrow()
|
alice = startNode(providedName = ALICE.name, rpcUsers = listOf(testUser)).getOrThrow()
|
||||||
raftNotaryIdentity = defaultNotaryIdentity
|
raftNotaryIdentity = defaultNotaryIdentity
|
||||||
|
@ -20,7 +20,10 @@ import net.corda.core.internal.concurrent.openFuture
|
|||||||
import net.corda.core.messaging.*
|
import net.corda.core.messaging.*
|
||||||
import net.corda.core.node.*
|
import net.corda.core.node.*
|
||||||
import net.corda.core.node.services.*
|
import net.corda.core.node.services.*
|
||||||
import net.corda.core.serialization.*
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
|
import net.corda.core.serialization.SerializeAsToken
|
||||||
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.debug
|
import net.corda.core.utilities.debug
|
||||||
@ -43,15 +46,8 @@ import net.corda.node.services.events.ScheduledActivityObserver
|
|||||||
import net.corda.node.services.identity.PersistentIdentityService
|
import net.corda.node.services.identity.PersistentIdentityService
|
||||||
import net.corda.node.services.keys.PersistentKeyManagementService
|
import net.corda.node.services.keys.PersistentKeyManagementService
|
||||||
import net.corda.node.services.messaging.MessagingService
|
import net.corda.node.services.messaging.MessagingService
|
||||||
import net.corda.node.services.network.NetworkMapCacheImpl
|
|
||||||
import net.corda.node.services.network.NodeInfoWatcher
|
|
||||||
import net.corda.node.services.network.PersistentNetworkMapCache
|
|
||||||
import net.corda.node.services.persistence.*
|
|
||||||
import net.corda.node.services.network.*
|
import net.corda.node.services.network.*
|
||||||
import net.corda.node.services.persistence.DBCheckpointStorage
|
import net.corda.node.services.persistence.*
|
||||||
import net.corda.node.services.persistence.DBTransactionMappingStorage
|
|
||||||
import net.corda.node.services.persistence.DBTransactionStorage
|
|
||||||
import net.corda.node.services.persistence.NodeAttachmentService
|
|
||||||
import net.corda.node.services.schema.HibernateObserver
|
import net.corda.node.services.schema.HibernateObserver
|
||||||
import net.corda.node.services.schema.NodeSchemaService
|
import net.corda.node.services.schema.NodeSchemaService
|
||||||
import net.corda.node.services.statemachine.*
|
import net.corda.node.services.statemachine.*
|
||||||
@ -89,8 +85,6 @@ import net.corda.core.crypto.generateKeyPair as cryptoGenerateKeyPair
|
|||||||
* Marked as SingletonSerializeAsToken to prevent the invisible reference to AbstractNode in the ServiceHub accidentally
|
* Marked as SingletonSerializeAsToken to prevent the invisible reference to AbstractNode in the ServiceHub accidentally
|
||||||
* sweeping up the Node into the Kryo checkpoint serialization via any flows holding a reference to ServiceHub.
|
* sweeping up the Node into the Kryo checkpoint serialization via any flows holding a reference to ServiceHub.
|
||||||
*/
|
*/
|
||||||
// TODO Log warning if this node is a notary but not one of the ones specified in the network parameters, both for core and custom
|
|
||||||
|
|
||||||
// In theory the NodeInfo for the node should be passed in, instead, however currently this is constructed by the
|
// In theory the NodeInfo for the node should be passed in, instead, however currently this is constructed by the
|
||||||
// AbstractNode. It should be possible to generate the NodeInfo outside of AbstractNode, so it can be passed in.
|
// AbstractNode. It should be possible to generate the NodeInfo outside of AbstractNode, so it can be passed in.
|
||||||
abstract class AbstractNode(val configuration: NodeConfiguration,
|
abstract class AbstractNode(val configuration: NodeConfiguration,
|
||||||
@ -120,7 +114,6 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
|||||||
// low-performance prototyping period.
|
// low-performance prototyping period.
|
||||||
protected abstract val serverThread: AffinityExecutor
|
protected abstract val serverThread: AffinityExecutor
|
||||||
|
|
||||||
protected lateinit var networkParameters: NetworkParameters
|
|
||||||
private val cordappServices = MutableClassToInstanceMap.create<SerializeAsToken>()
|
private val cordappServices = MutableClassToInstanceMap.create<SerializeAsToken>()
|
||||||
private val flowFactories = ConcurrentHashMap<Class<out FlowLogic<*>>, InitiatedFlowFactory<*>>()
|
private val flowFactories = ConcurrentHashMap<Class<out FlowLogic<*>>, InitiatedFlowFactory<*>>()
|
||||||
|
|
||||||
@ -186,7 +179,6 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
|||||||
log.info("Node starting up ...")
|
log.info("Node starting up ...")
|
||||||
initCertificate()
|
initCertificate()
|
||||||
val keyPairs = initNodeInfo()
|
val keyPairs = initNodeInfo()
|
||||||
readNetworkParameters()
|
|
||||||
val schemaService = NodeSchemaService(cordappLoader)
|
val schemaService = NodeSchemaService(cordappLoader)
|
||||||
// Do all of this in a database transaction so anything that might need a connection has one.
|
// Do all of this in a database transaction so anything that might need a connection has one.
|
||||||
val (startedImpl, schedulerService) = initialiseDatabasePersistence(schemaService) { database ->
|
val (startedImpl, schedulerService) = initialiseDatabasePersistence(schemaService) { database ->
|
||||||
@ -257,18 +249,13 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
|||||||
val keyPairs = mutableSetOf(identityKeyPair)
|
val keyPairs = mutableSetOf(identityKeyPair)
|
||||||
|
|
||||||
myNotaryIdentity = configuration.notary?.let {
|
myNotaryIdentity = configuration.notary?.let {
|
||||||
if (it.isClusterConfig) {
|
|
||||||
val (notaryIdentity, notaryIdentityKeyPair) = obtainIdentity(it)
|
val (notaryIdentity, notaryIdentityKeyPair) = obtainIdentity(it)
|
||||||
keyPairs += notaryIdentityKeyPair
|
keyPairs += notaryIdentityKeyPair
|
||||||
notaryIdentity
|
notaryIdentity
|
||||||
} else {
|
|
||||||
// In case of a single notary service myNotaryIdentity will be the node's single identity.
|
|
||||||
identity
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
info = NodeInfo(
|
info = NodeInfo(
|
||||||
myAddresses(),
|
myAddresses(),
|
||||||
setOf(identity, myNotaryIdentity).filterNotNull(),
|
listOf(identity, myNotaryIdentity).filterNotNull(),
|
||||||
versionInfo.platformVersion,
|
versionInfo.platformVersion,
|
||||||
platformClock.instant().toEpochMilli()
|
platformClock.instant().toEpochMilli()
|
||||||
)
|
)
|
||||||
@ -596,13 +583,6 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
|||||||
return PersistentKeyManagementService(identityService, keyPairs)
|
return PersistentKeyManagementService(identityService, keyPairs)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readNetworkParameters() {
|
|
||||||
val file = configuration.baseDirectory / "network-parameters"
|
|
||||||
networkParameters = file.readAll().deserialize<SignedData<NetworkParameters>>().verified()
|
|
||||||
log.info(networkParameters.toString())
|
|
||||||
check(networkParameters.minimumPlatformVersion <= versionInfo.platformVersion) { "Node is too old for the network" }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun makeCoreNotaryService(notaryConfig: NotaryConfig, database: CordaPersistence): NotaryService {
|
private fun makeCoreNotaryService(notaryConfig: NotaryConfig, database: CordaPersistence): NotaryService {
|
||||||
val notaryKey = myNotaryIdentity?.owningKey ?: throw IllegalArgumentException("No notary identity initialized when creating a notary service")
|
val notaryKey = myNotaryIdentity?.owningKey ?: throw IllegalArgumentException("No notary identity initialized when creating a notary service")
|
||||||
return notaryConfig.run {
|
return notaryConfig.run {
|
||||||
@ -661,16 +641,22 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
|||||||
private fun obtainIdentity(notaryConfig: NotaryConfig?): Pair<PartyAndCertificate, KeyPair> {
|
private fun obtainIdentity(notaryConfig: NotaryConfig?): Pair<PartyAndCertificate, KeyPair> {
|
||||||
val keyStore = KeyStoreWrapper(configuration.nodeKeystore, configuration.keyStorePassword)
|
val keyStore = KeyStoreWrapper(configuration.nodeKeystore, configuration.keyStorePassword)
|
||||||
|
|
||||||
val (id, singleName) = if (notaryConfig == null || !notaryConfig.isClusterConfig) {
|
val (id, singleName) = if (notaryConfig == null) {
|
||||||
// Node's main identity or if it's a single node notary
|
// Node's main identity
|
||||||
Pair("identity", myLegalName)
|
Pair("identity", myLegalName)
|
||||||
} else {
|
} else {
|
||||||
val notaryId = notaryConfig.run {
|
val notaryId = notaryConfig.run {
|
||||||
NotaryService.constructId(validating, raft != null, bftSMaRt != null, custom)
|
NotaryService.constructId(validating, raft != null, bftSMaRt != null, custom)
|
||||||
}
|
}
|
||||||
// The node is part of a distributed notary whose identity must already be generated beforehand.
|
if (!notaryConfig.isClusterConfig) {
|
||||||
|
// Node's notary identity
|
||||||
|
Pair(notaryId, myLegalName.copy(commonName = notaryId))
|
||||||
|
} else {
|
||||||
|
// The node is part of a distributed notary whose identity must already be generated beforehand
|
||||||
Pair(notaryId, null)
|
Pair(notaryId, null)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Integrate with Key management service?
|
// TODO: Integrate with Key management service?
|
||||||
val privateKeyAlias = "$id-private-key"
|
val privateKeyAlias = "$id-private-key"
|
||||||
|
|
||||||
@ -734,13 +720,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
|||||||
override val stateMachineRecordedTransactionMapping = DBTransactionMappingStorage()
|
override val stateMachineRecordedTransactionMapping = DBTransactionMappingStorage()
|
||||||
override val auditService = DummyAuditService()
|
override val auditService = DummyAuditService()
|
||||||
override val transactionVerifierService by lazy { makeTransactionVerifierService() }
|
override val transactionVerifierService by lazy { makeTransactionVerifierService() }
|
||||||
override val networkMapCache by lazy {
|
override val networkMapCache by lazy { NetworkMapCacheImpl(PersistentNetworkMapCache(database), identityService) }
|
||||||
NetworkMapCacheImpl(
|
|
||||||
PersistentNetworkMapCache(
|
|
||||||
database,
|
|
||||||
networkParameters.notaries),
|
|
||||||
identityService)
|
|
||||||
}
|
|
||||||
override val vaultService by lazy { makeVaultService(keyManagementService, stateLoader, database.hibernateConfig) }
|
override val vaultService by lazy { makeVaultService(keyManagementService, stateLoader, database.hibernateConfig) }
|
||||||
override val contractUpgradeService by lazy { ContractUpgradeServiceImpl() }
|
override val contractUpgradeService by lazy { ContractUpgradeServiceImpl() }
|
||||||
override val attachments: AttachmentStorage get() = this@AbstractNode.attachments
|
override val attachments: AttachmentStorage get() = this@AbstractNode.attachments
|
||||||
|
@ -117,6 +117,7 @@ data class NodeConfigurationImpl(
|
|||||||
// This is a sanity feature do not remove.
|
// This is a sanity feature do not remove.
|
||||||
require(!useTestClock || devMode) { "Cannot use test clock outside of dev mode" }
|
require(!useTestClock || devMode) { "Cannot use test clock outside of dev mode" }
|
||||||
require(devModeOptions == null || devMode) { "Cannot use devModeOptions outside of dev mode" }
|
require(devModeOptions == null || devMode) { "Cannot use devModeOptions outside of dev mode" }
|
||||||
|
require(myLegalName.commonName == null) { "Common name must be null: $myLegalName" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@ import net.corda.core.internal.concurrent.openFuture
|
|||||||
import net.corda.core.internal.schemas.NodeInfoSchemaV1
|
import net.corda.core.internal.schemas.NodeInfoSchemaV1
|
||||||
import net.corda.core.messaging.DataFeed
|
import net.corda.core.messaging.DataFeed
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.NotaryInfo
|
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.node.services.NetworkMapCache.MapChange
|
import net.corda.core.node.services.NetworkMapCache.MapChange
|
||||||
|
import net.corda.core.node.services.NotaryService
|
||||||
import net.corda.core.node.services.PartyInfo
|
import net.corda.core.node.services.PartyInfo
|
||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
@ -32,7 +32,6 @@ import java.security.PublicKey
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.annotation.concurrent.ThreadSafe
|
import javax.annotation.concurrent.ThreadSafe
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
import kotlin.collections.HashSet
|
|
||||||
|
|
||||||
class NetworkMapCacheImpl(
|
class NetworkMapCacheImpl(
|
||||||
networkMapCacheBase: NetworkMapCacheBaseInternal,
|
networkMapCacheBase: NetworkMapCacheBaseInternal,
|
||||||
@ -62,15 +61,13 @@ class NetworkMapCacheImpl(
|
|||||||
* Extremely simple in-memory cache of the network map.
|
* Extremely simple in-memory cache of the network map.
|
||||||
*/
|
*/
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
open class PersistentNetworkMapCache(
|
open class PersistentNetworkMapCache(private val database: CordaPersistence) : SingletonSerializeAsToken(), NetworkMapCacheBaseInternal {
|
||||||
private val database: CordaPersistence,
|
|
||||||
notaries: List<NotaryInfo>
|
|
||||||
) : SingletonSerializeAsToken(), NetworkMapCacheBaseInternal {
|
|
||||||
companion object {
|
companion object {
|
||||||
val logger = loggerFor<PersistentNetworkMapCache>()
|
val logger = loggerFor<PersistentNetworkMapCache>()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Cleanup registered and party nodes
|
// TODO Small explanation, partyNodes and registeredNodes is left in memory as it was before, because it will be removed in
|
||||||
|
// next PR that gets rid of services. These maps are used only for queries by service.
|
||||||
protected val registeredNodes: MutableMap<PublicKey, NodeInfo> = Collections.synchronizedMap(HashMap())
|
protected val registeredNodes: MutableMap<PublicKey, NodeInfo> = Collections.synchronizedMap(HashMap())
|
||||||
protected val partyNodes: MutableList<NodeInfo> get() = registeredNodes.map { it.value }.toMutableList()
|
protected val partyNodes: MutableList<NodeInfo> get() = registeredNodes.map { it.value }.toMutableList()
|
||||||
private val _changed = PublishSubject.create<MapChange>()
|
private val _changed = PublishSubject.create<MapChange>()
|
||||||
@ -84,9 +81,22 @@ open class PersistentNetworkMapCache(
|
|||||||
override val nodeReady: CordaFuture<Void?> get() = _registrationFuture
|
override val nodeReady: CordaFuture<Void?> get() = _registrationFuture
|
||||||
private var _loadDBSuccess: Boolean = false
|
private var _loadDBSuccess: Boolean = false
|
||||||
override val loadDBSuccess get() = _loadDBSuccess
|
override val loadDBSuccess get() = _loadDBSuccess
|
||||||
|
// TODO From the NetworkMapService redesign doc: Remove the concept of network services.
|
||||||
override val notaryIdentities: List<Party> = notaries.map { it.identity }
|
// As a temporary hack, just assume for now that every network has a notary service named "Notary Service" that can be looked up in the map.
|
||||||
private val validatingNotaries = notaries.mapNotNullTo(HashSet()) { if (it.validating) it.identity else null }
|
// This should eliminate the only required usage of services.
|
||||||
|
// It is ensured on node startup when constructing a notary that the name contains "notary".
|
||||||
|
override val notaryIdentities: List<Party>
|
||||||
|
get() {
|
||||||
|
return partyNodes
|
||||||
|
.flatMap {
|
||||||
|
// TODO: validate notary identity certificates before loading into network map cache.
|
||||||
|
// Notary certificates have to be signed by the doorman directly
|
||||||
|
it.legalIdentities
|
||||||
|
}
|
||||||
|
.filter { it.name.commonName?.startsWith(NotaryService.ID_PREFIX) ?: false }
|
||||||
|
.toSet() // Distinct, because of distributed service nodes
|
||||||
|
.sortedBy { it.name.toString() }
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
database.transaction { loadFromDB(session) }
|
database.transaction { loadFromDB(session) }
|
||||||
@ -117,7 +127,7 @@ open class PersistentNetworkMapCache(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isValidatingNotary(party: Party): Boolean = party in validatingNotaries
|
override fun isValidatingNotary(party: Party): Boolean = isNotary(party) && "validating" in party.name.commonName!!
|
||||||
|
|
||||||
override fun getPartyInfo(party: Party): PartyInfo? {
|
override fun getPartyInfo(party: Party): PartyInfo? {
|
||||||
val nodes = database.transaction { queryByIdentityKey(session, party.owningKey) }
|
val nodes = database.transaction { queryByIdentityKey(session, party.owningKey) }
|
||||||
@ -300,6 +310,7 @@ open class PersistentNetworkMapCache(
|
|||||||
id = 0,
|
id = 0,
|
||||||
hash = nodeInfo.serialize().hash.toString(),
|
hash = nodeInfo.serialize().hash.toString(),
|
||||||
addresses = nodeInfo.addresses.map { NodeInfoSchemaV1.DBHostAndPort.fromHostAndPort(it) },
|
addresses = nodeInfo.addresses.map { NodeInfoSchemaV1.DBHostAndPort.fromHostAndPort(it) },
|
||||||
|
// TODO Another ugly hack with special first identity...
|
||||||
legalIdentitiesAndCerts = nodeInfo.legalIdentitiesAndCerts.mapIndexed { idx, elem ->
|
legalIdentitiesAndCerts = nodeInfo.legalIdentitiesAndCerts.mapIndexed { idx, elem ->
|
||||||
NodeInfoSchemaV1.DBPartyAndCertificate(elem, isMain = idx == 0)
|
NodeInfoSchemaV1.DBPartyAndCertificate(elem, isMain = idx == 0)
|
||||||
},
|
},
|
||||||
|
@ -20,12 +20,11 @@ object ServiceIdentityGenerator {
|
|||||||
* This method should be called *before* any of the nodes are started.
|
* This method should be called *before* any of the nodes are started.
|
||||||
*
|
*
|
||||||
* @param dirs List of node directories to place the generated identity and key pairs in.
|
* @param dirs List of node directories to place the generated identity and key pairs in.
|
||||||
* @param serviceName The legal name of the distributed service.
|
* @param serviceName The legal name of the distributed service, with service id as CN.
|
||||||
* @param threshold The threshold for the generated group [CompositeKey].
|
* @param threshold The threshold for the generated group [CompositeKey].
|
||||||
*/
|
*/
|
||||||
fun generateToDisk(dirs: List<Path>,
|
fun generateToDisk(dirs: List<Path>,
|
||||||
serviceName: CordaX500Name,
|
serviceName: CordaX500Name,
|
||||||
serviceId: String,
|
|
||||||
threshold: Int = 1): Party {
|
threshold: Int = 1): Party {
|
||||||
log.trace { "Generating a group identity \"serviceName\" for nodes: ${dirs.joinToString()}" }
|
log.trace { "Generating a group identity \"serviceName\" for nodes: ${dirs.joinToString()}" }
|
||||||
val keyPairs = (1..dirs.size).map { generateKeyPair() }
|
val keyPairs = (1..dirs.size).map { generateKeyPair() }
|
||||||
@ -40,6 +39,7 @@ object ServiceIdentityGenerator {
|
|||||||
val compositeKeyCert = X509Utilities.createCertificate(CertificateType.CLIENT_CA, issuer.certificate, issuer.keyPair, serviceName, notaryKey)
|
val compositeKeyCert = X509Utilities.createCertificate(CertificateType.CLIENT_CA, issuer.certificate, issuer.keyPair, serviceName, notaryKey)
|
||||||
val certPath = (dir / "certificates").createDirectories() / "distributedService.jks"
|
val certPath = (dir / "certificates").createDirectories() / "distributedService.jks"
|
||||||
val keystore = loadOrCreateKeyStore(certPath, "cordacadevpass")
|
val keystore = loadOrCreateKeyStore(certPath, "cordacadevpass")
|
||||||
|
val serviceId = serviceName.commonName
|
||||||
keystore.setCertificateEntry("$serviceId-composite-key", compositeKeyCert.cert)
|
keystore.setCertificateEntry("$serviceId-composite-key", compositeKeyCert.cert)
|
||||||
keystore.setKeyEntry("$serviceId-private-key", keyPair.private, "cordacadevkeypass".toCharArray(), arrayOf(serviceKeyCert.cert, issuer.certificate.cert, rootCert))
|
keystore.setKeyEntry("$serviceId-private-key", keyPair.private, "cordacadevkeypass".toCharArray(), arrayOf(serviceKeyCert.cert, issuer.certificate.cert, rootCert))
|
||||||
keystore.save(certPath, "cordacadevpass")
|
keystore.save(certPath, "cordacadevpass")
|
||||||
|
@ -27,6 +27,10 @@ import kotlin.test.assertEquals
|
|||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class NotaryChangeTests {
|
class NotaryChangeTests {
|
||||||
|
companion object {
|
||||||
|
private val DUMMY_NOTARY_SERVICE_NAME: CordaX500Name = DUMMY_NOTARY.name.copy(commonName = "corda.notary.validating")
|
||||||
|
}
|
||||||
|
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private lateinit var oldNotaryNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var oldNotaryNode: StartedNode<MockNetwork.MockNode>
|
||||||
private lateinit var clientNodeA: StartedNode<MockNetwork.MockNode>
|
private lateinit var clientNodeA: StartedNode<MockNetwork.MockNode>
|
||||||
@ -36,7 +40,7 @@ class NotaryChangeTests {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
val oldNotaryName = DUMMY_REGULATOR.name
|
val oldNotaryName = DUMMY_NOTARY.name.copy(organisation = "Old Dummy Notary")
|
||||||
mockNet = MockNetwork(
|
mockNet = MockNetwork(
|
||||||
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name), NotarySpec(oldNotaryName)),
|
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name), NotarySpec(oldNotaryName)),
|
||||||
cordappPackages = listOf("net.corda.testing.contracts")
|
cordappPackages = listOf("net.corda.testing.contracts")
|
||||||
@ -44,8 +48,8 @@ class NotaryChangeTests {
|
|||||||
clientNodeA = mockNet.createNode()
|
clientNodeA = mockNet.createNode()
|
||||||
clientNodeB = mockNet.createNode()
|
clientNodeB = mockNet.createNode()
|
||||||
oldNotaryNode = mockNet.notaryNodes[1]
|
oldNotaryNode = mockNet.notaryNodes[1]
|
||||||
newNotaryParty = clientNodeA.services.networkMapCache.getNotary(DUMMY_NOTARY.name)!!
|
newNotaryParty = clientNodeA.services.networkMapCache.getNotary(DUMMY_NOTARY_SERVICE_NAME)!!
|
||||||
oldNotaryParty = clientNodeA.services.networkMapCache.getNotary(oldNotaryName)!!
|
oldNotaryParty = clientNodeA.services.networkMapCache.getNotary(DUMMY_NOTARY_SERVICE_NAME.copy(organisation = "Old Dummy Notary"))!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -80,7 +80,7 @@ class ArtemisMessagingTests {
|
|||||||
LogHelper.setLevel(PersistentUniquenessProvider::class)
|
LogHelper.setLevel(PersistentUniquenessProvider::class)
|
||||||
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), ::makeTestIdentityService)
|
database = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), ::makeTestIdentityService)
|
||||||
networkMapRegistrationFuture = doneFuture(Unit)
|
networkMapRegistrationFuture = doneFuture(Unit)
|
||||||
networkMapCache = NetworkMapCacheImpl(PersistentNetworkMapCache(database, emptyList()), rigorousMock())
|
networkMapCache = NetworkMapCacheImpl(PersistentNetworkMapCache(database), rigorousMock())
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -5,7 +5,6 @@ import net.corda.cordform.CordformDefinition
|
|||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.node.services.NotaryService
|
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.node.services.config.BFTSMaRtConfiguration
|
import net.corda.node.services.config.BFTSMaRtConfiguration
|
||||||
import net.corda.node.services.config.NotaryConfig
|
import net.corda.node.services.config.NotaryConfig
|
||||||
@ -63,10 +62,6 @@ class BFTNotaryCordform : CordformDefinition("build" / "notary-demo-nodes") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setup(context: CordformContext) {
|
override fun setup(context: CordformContext) {
|
||||||
ServiceIdentityGenerator.generateToDisk(
|
ServiceIdentityGenerator.generateToDisk(notaryNames.map { context.baseDirectory(it.toString()) }, clusterName, threshold = minCorrectReplicas(clusterSize))
|
||||||
notaryNames.map { context.baseDirectory(it.toString()) },
|
|
||||||
clusterName,
|
|
||||||
NotaryService.constructId(validating = false, bft = true),
|
|
||||||
minCorrectReplicas(clusterSize))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import net.corda.cordform.CordformDefinition
|
|||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.node.services.NotaryService
|
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.node.services.config.NotaryConfig
|
import net.corda.node.services.config.NotaryConfig
|
||||||
import net.corda.node.services.config.RaftConfig
|
import net.corda.node.services.config.RaftConfig
|
||||||
@ -59,9 +58,6 @@ class RaftNotaryCordform : CordformDefinition("build" / "notary-demo-nodes") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setup(context: CordformContext) {
|
override fun setup(context: CordformContext) {
|
||||||
ServiceIdentityGenerator.generateToDisk(
|
ServiceIdentityGenerator.generateToDisk(notaryNames.map { context.baseDirectory(it.toString()) }, clusterName)
|
||||||
notaryNames.map { context.baseDirectory(it.toString()) },
|
|
||||||
clusterName,
|
|
||||||
NotaryService.constructId(validating = true, raft = true))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,7 @@ import net.corda.core.identity.Party
|
|||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.concurrent.*
|
import net.corda.core.internal.concurrent.*
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.node.NetworkParameters
|
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.NotaryInfo
|
|
||||||
import net.corda.core.node.services.NetworkMapCache
|
import net.corda.core.node.services.NetworkMapCache
|
||||||
import net.corda.core.node.services.NotaryService
|
import net.corda.core.node.services.NotaryService
|
||||||
import net.corda.core.toFuture
|
import net.corda.core.toFuture
|
||||||
@ -35,8 +33,6 @@ import net.corda.nodeapi.User
|
|||||||
import net.corda.nodeapi.config.toConfig
|
import net.corda.nodeapi.config.toConfig
|
||||||
import net.corda.nodeapi.internal.addShutdownHook
|
import net.corda.nodeapi.internal.addShutdownHook
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.common.internal.NetworkParametersCopier
|
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
|
||||||
import net.corda.testing.internal.ProcessUtilities
|
import net.corda.testing.internal.ProcessUtilities
|
||||||
import net.corda.testing.node.ClusterSpec
|
import net.corda.testing.node.ClusterSpec
|
||||||
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
||||||
@ -585,7 +581,6 @@ class DriverDSL(
|
|||||||
private val countObservables = mutableMapOf<CordaX500Name, Observable<Int>>()
|
private val countObservables = mutableMapOf<CordaX500Name, Observable<Int>>()
|
||||||
private lateinit var _notaries: List<NotaryHandle>
|
private lateinit var _notaries: List<NotaryHandle>
|
||||||
override val notaryHandles: List<NotaryHandle> get() = _notaries
|
override val notaryHandles: List<NotaryHandle> get() = _notaries
|
||||||
private lateinit var networkParameters: NetworkParametersCopier
|
|
||||||
|
|
||||||
class State {
|
class State {
|
||||||
val processes = ArrayList<Process>()
|
val processes = ArrayList<Process>()
|
||||||
@ -713,33 +708,29 @@ class DriverDSL(
|
|||||||
_shutdownManager = ShutdownManager(executorService)
|
_shutdownManager = ShutdownManager(executorService)
|
||||||
shutdownManager.registerShutdown { nodeInfoFilesCopier.close() }
|
shutdownManager.registerShutdown { nodeInfoFilesCopier.close() }
|
||||||
val notaryInfos = generateNotaryIdentities()
|
val notaryInfos = generateNotaryIdentities()
|
||||||
// The network parameters must be serialised before starting any of the nodes
|
|
||||||
networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos))
|
|
||||||
val nodeHandles = startNotaries()
|
val nodeHandles = startNotaries()
|
||||||
_notaries = notaryInfos.zip(nodeHandles) { (identity, validating), nodes -> NotaryHandle(identity, validating, nodes) }
|
_notaries = notaryInfos.zip(nodeHandles) { (identity, validating), nodes -> NotaryHandle(identity, validating, nodes) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateNotaryIdentities(): List<NotaryInfo> {
|
private fun generateNotaryIdentities(): List<Pair<Party, Boolean>> {
|
||||||
return notarySpecs.map { spec ->
|
return notarySpecs.map { spec ->
|
||||||
val identity = if (spec.cluster == null) {
|
val identity = if (spec.cluster == null) {
|
||||||
ServiceIdentityGenerator.generateToDisk(
|
ServiceIdentityGenerator.generateToDisk(
|
||||||
dirs = listOf(baseDirectory(spec.name)),
|
dirs = listOf(baseDirectory(spec.name)),
|
||||||
serviceName = spec.name,
|
serviceName = spec.name.copy(commonName = NotaryService.constructId(validating = spec.validating))
|
||||||
serviceId = "identity")
|
)
|
||||||
} else {
|
} else {
|
||||||
ServiceIdentityGenerator.generateToDisk(
|
ServiceIdentityGenerator.generateToDisk(
|
||||||
dirs = generateNodeNames(spec).map { baseDirectory(it) },
|
dirs = generateNodeNames(spec).map { baseDirectory(it) },
|
||||||
serviceName = spec.name,
|
serviceName = spec.name
|
||||||
serviceId = NotaryService.constructId(
|
)
|
||||||
validating = spec.validating,
|
|
||||||
raft = spec.cluster is ClusterSpec.Raft))
|
|
||||||
}
|
}
|
||||||
NotaryInfo(identity, spec.validating)
|
Pair(identity, spec.validating)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateNodeNames(spec: NotarySpec): List<CordaX500Name> {
|
private fun generateNodeNames(spec: NotarySpec): List<CordaX500Name> {
|
||||||
return (0 until spec.cluster!!.clusterSize).map { spec.name.copy(organisation = "${spec.name.organisation}-$it") }
|
return (0 until spec.cluster!!.clusterSize).map { spec.name.copy(commonName = null, organisation = "${spec.name.organisation}-$it") }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startNotaries(): List<CordaFuture<List<NodeHandle>>> {
|
private fun startNotaries(): List<CordaFuture<List<NodeHandle>>> {
|
||||||
@ -862,7 +853,6 @@ class DriverDSL(
|
|||||||
maximumHeapSize: String): CordaFuture<NodeHandle> {
|
maximumHeapSize: String): CordaFuture<NodeHandle> {
|
||||||
val configuration = config.parseAsNodeConfiguration()
|
val configuration = config.parseAsNodeConfiguration()
|
||||||
val baseDirectory = configuration.baseDirectory.createDirectories()
|
val baseDirectory = configuration.baseDirectory.createDirectories()
|
||||||
networkParameters.install(baseDirectory)
|
|
||||||
nodeInfoFilesCopier.addConfig(baseDirectory)
|
nodeInfoFilesCopier.addConfig(baseDirectory)
|
||||||
val onNodeExit: () -> Unit = {
|
val onNodeExit: () -> Unit = {
|
||||||
nodeInfoFilesCopier.removeConfig(baseDirectory)
|
nodeInfoFilesCopier.removeConfig(baseDirectory)
|
||||||
|
@ -16,14 +16,11 @@ import net.corda.node.services.config.parseAsNodeConfiguration
|
|||||||
import net.corda.node.services.config.plus
|
import net.corda.node.services.config.plus
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.testing.SerializationEnvironmentRule
|
import net.corda.testing.SerializationEnvironmentRule
|
||||||
import net.corda.testing.common.internal.NetworkParametersCopier
|
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
|
||||||
import net.corda.testing.driver.addressMustNotBeBoundFuture
|
import net.corda.testing.driver.addressMustNotBeBoundFuture
|
||||||
import net.corda.testing.getFreeLocalPorts
|
import net.corda.testing.getFreeLocalPorts
|
||||||
import net.corda.testing.node.MockServices
|
import net.corda.testing.node.MockServices
|
||||||
import org.apache.logging.log4j.Level
|
import org.apache.logging.log4j.Level
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.rules.TemporaryFolder
|
import org.junit.rules.TemporaryFolder
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@ -43,7 +40,6 @@ abstract class NodeBasedTest(private val cordappPackages: List<String> = emptyLi
|
|||||||
@JvmField
|
@JvmField
|
||||||
val tempFolder = TemporaryFolder()
|
val tempFolder = TemporaryFolder()
|
||||||
|
|
||||||
private lateinit var defaultNetworkParameters: NetworkParametersCopier
|
|
||||||
private val nodes = mutableListOf<StartedNode<Node>>()
|
private val nodes = mutableListOf<StartedNode<Node>>()
|
||||||
private val nodeInfos = mutableListOf<NodeInfo>()
|
private val nodeInfos = mutableListOf<NodeInfo>()
|
||||||
|
|
||||||
@ -51,11 +47,6 @@ abstract class NodeBasedTest(private val cordappPackages: List<String> = emptyLi
|
|||||||
System.setProperty("consoleLogLevel", Level.DEBUG.name().toLowerCase())
|
System.setProperty("consoleLogLevel", Level.DEBUG.name().toLowerCase())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
|
||||||
fun init() {
|
|
||||||
defaultNetworkParameters = NetworkParametersCopier(testNetworkParameters(emptyList()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the network map node and all the nodes started by [startNode]. This is called automatically after each test
|
* Stops the network map node and all the nodes started by [startNode]. This is called automatically after each test
|
||||||
* but can also be called manually within a test.
|
* but can also be called manually within a test.
|
||||||
@ -99,7 +90,6 @@ abstract class NodeBasedTest(private val cordappPackages: List<String> = emptyLi
|
|||||||
)
|
)
|
||||||
|
|
||||||
val parsedConfig = config.parseAsNodeConfiguration()
|
val parsedConfig = config.parseAsNodeConfiguration()
|
||||||
defaultNetworkParameters.install(baseDirectory)
|
|
||||||
val node = Node(
|
val node = Node(
|
||||||
parsedConfig,
|
parsedConfig,
|
||||||
MockServices.MOCK_VERSION_INFO.copy(platformVersion = platformVersion),
|
MockServices.MOCK_VERSION_INFO.copy(platformVersion = platformVersion),
|
||||||
|
@ -15,7 +15,6 @@ fun CordformDefinition.clean() {
|
|||||||
/**
|
/**
|
||||||
* Creates and starts all nodes required for the demo.
|
* Creates and starts all nodes required for the demo.
|
||||||
*/
|
*/
|
||||||
// TODO add notaries to cordform!
|
|
||||||
fun CordformDefinition.runNodes() {
|
fun CordformDefinition.runNodes() {
|
||||||
driver(isDebug = true, driverDirectory = driverDirectory, portAllocation = PortAllocation.Incremental(10001), waitForAllNodesToFinish = true) {
|
driver(isDebug = true, driverDirectory = driverDirectory, portAllocation = PortAllocation.Incremental(10001), waitForAllNodesToFinish = true) {
|
||||||
setup(this)
|
setup(this)
|
||||||
|
@ -7,7 +7,6 @@ import net.corda.core.internal.concurrent.doneFuture
|
|||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.NetworkMapCache
|
import net.corda.core.node.services.NetworkMapCache
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
|
||||||
import net.corda.node.services.network.PersistentNetworkMapCache
|
import net.corda.node.services.network.PersistentNetworkMapCache
|
||||||
import net.corda.node.utilities.CordaPersistence
|
import net.corda.node.utilities.CordaPersistence
|
||||||
import net.corda.testing.getTestPartyAndCertificate
|
import net.corda.testing.getTestPartyAndCertificate
|
||||||
@ -18,7 +17,7 @@ import java.math.BigInteger
|
|||||||
/**
|
/**
|
||||||
* Network map cache with no backing map service.
|
* Network map cache with no backing map service.
|
||||||
*/
|
*/
|
||||||
class MockNetworkMapCache(database: CordaPersistence) : PersistentNetworkMapCache(database, emptyList()) {
|
class MockNetworkMapCache(database: CordaPersistence) : PersistentNetworkMapCache(database) {
|
||||||
private companion object {
|
private companion object {
|
||||||
val BANK_C = getTestPartyAndCertificate(CordaX500Name(organisation = "Bank C", locality = "London", country = "GB"), entropyToKeyPair(BigInteger.valueOf(1000)).public)
|
val BANK_C = getTestPartyAndCertificate(CordaX500Name(organisation = "Bank C", locality = "London", country = "GB"), entropyToKeyPair(BigInteger.valueOf(1000)).public)
|
||||||
val BANK_D = getTestPartyAndCertificate(CordaX500Name(organisation = "Bank D", locality = "London", country = "GB"), entropyToKeyPair(BigInteger.valueOf(2000)).public)
|
val BANK_D = getTestPartyAndCertificate(CordaX500Name(organisation = "Bank D", locality = "London", country = "GB"), entropyToKeyPair(BigInteger.valueOf(2000)).public)
|
||||||
|
@ -14,7 +14,6 @@ import net.corda.core.internal.uncheckedCast
|
|||||||
import net.corda.core.messaging.MessageRecipients
|
import net.corda.core.messaging.MessageRecipients
|
||||||
import net.corda.core.messaging.RPCOps
|
import net.corda.core.messaging.RPCOps
|
||||||
import net.corda.core.messaging.SingleMessageRecipient
|
import net.corda.core.messaging.SingleMessageRecipient
|
||||||
import net.corda.core.node.NotaryInfo
|
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.node.services.KeyManagementService
|
import net.corda.core.node.services.KeyManagementService
|
||||||
import net.corda.core.serialization.SerializationWhitelist
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
@ -36,13 +35,10 @@ import net.corda.node.services.transactions.InMemoryTransactionVerifierService
|
|||||||
import net.corda.node.utilities.AffinityExecutor
|
import net.corda.node.utilities.AffinityExecutor
|
||||||
import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
|
import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
|
||||||
import net.corda.node.utilities.CordaPersistence
|
import net.corda.node.utilities.CordaPersistence
|
||||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
|
||||||
import net.corda.testing.DUMMY_NOTARY
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
import net.corda.testing.common.internal.NetworkParametersCopier
|
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
|
||||||
import net.corda.testing.setGlobalSerialization
|
|
||||||
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||||
|
import net.corda.testing.setGlobalSerialization
|
||||||
import net.corda.testing.testNodeConfiguration
|
import net.corda.testing.testNodeConfiguration
|
||||||
import org.apache.activemq.artemis.utils.ReusableLatch
|
import org.apache.activemq.artemis.utils.ReusableLatch
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
@ -134,7 +130,6 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
|||||||
val messagingNetwork = InMemoryMessagingNetwork(networkSendManuallyPumped, servicePeerAllocationStrategy, busyLatch)
|
val messagingNetwork = InMemoryMessagingNetwork(networkSendManuallyPumped, servicePeerAllocationStrategy, busyLatch)
|
||||||
// A unique identifier for this network to segregate databases with the same nodeID but different networks.
|
// A unique identifier for this network to segregate databases with the same nodeID but different networks.
|
||||||
private val networkId = random63BitValue()
|
private val networkId = random63BitValue()
|
||||||
private val networkParameters: NetworkParametersCopier
|
|
||||||
private val _nodes = mutableListOf<MockNode>()
|
private val _nodes = mutableListOf<MockNode>()
|
||||||
private val serializationEnv = setGlobalSerialization(initialiseSerialization)
|
private val serializationEnv = setGlobalSerialization(initialiseSerialization)
|
||||||
private val sharedUserCount = AtomicInteger(0)
|
private val sharedUserCount = AtomicInteger(0)
|
||||||
@ -164,7 +159,7 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
|||||||
* @see defaultNotaryNode
|
* @see defaultNotaryNode
|
||||||
*/
|
*/
|
||||||
val defaultNotaryIdentity: Party get() {
|
val defaultNotaryIdentity: Party get() {
|
||||||
return defaultNotaryNode.info.legalIdentities.singleOrNull() ?: throw IllegalStateException("Default notary has multiple identities")
|
return defaultNotaryNode.info.legalIdentities[1] // TODO Resolve once network parameters is merged back in
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -191,22 +186,9 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
filesystem.getPath("/nodes").createDirectory()
|
filesystem.getPath("/nodes").createDirectory()
|
||||||
val notaryInfos = generateNotaryIdentities()
|
|
||||||
// The network parameters must be serialised before starting any of the nodes
|
|
||||||
networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos))
|
|
||||||
notaryNodes = createNotaries()
|
notaryNodes = createNotaries()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateNotaryIdentities(): List<NotaryInfo> {
|
|
||||||
return notarySpecs.mapIndexed { index, spec ->
|
|
||||||
val identity = ServiceIdentityGenerator.generateToDisk(
|
|
||||||
dirs = listOf(baseDirectory(nextNodeId + index)),
|
|
||||||
serviceName = spec.name,
|
|
||||||
serviceId = "identity")
|
|
||||||
NotaryInfo(identity, spec.validating)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createNotaries(): List<StartedNode<MockNode>> {
|
private fun createNotaries(): List<StartedNode<MockNode>> {
|
||||||
return notarySpecs.map { spec ->
|
return notarySpecs.map { spec ->
|
||||||
createNode(MockNodeParameters(legalName = spec.name, configOverrides = {
|
createNode(MockNodeParameters(legalName = spec.name, configOverrides = {
|
||||||
@ -240,7 +222,6 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
|||||||
override val started: StartedNode<MockNode>? get() = uncheckedCast(super.started)
|
override val started: StartedNode<MockNode>? get() = uncheckedCast(super.started)
|
||||||
|
|
||||||
override fun start(): StartedNode<MockNode> {
|
override fun start(): StartedNode<MockNode> {
|
||||||
mockNet.networkParameters.install(configuration.baseDirectory)
|
|
||||||
val started: StartedNode<MockNode> = uncheckedCast(super.start())
|
val started: StartedNode<MockNode> = uncheckedCast(super.start())
|
||||||
advertiseNodeToNetwork(started)
|
advertiseNodeToNetwork(started)
|
||||||
return started
|
return started
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.testing.node
|
|||||||
|
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.node.services.config.VerifierType
|
import net.corda.node.services.config.VerifierType
|
||||||
|
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
|
|
||||||
data class NotarySpec(
|
data class NotarySpec(
|
||||||
@ -10,7 +11,15 @@ data class NotarySpec(
|
|||||||
val rpcUsers: List<User> = emptyList(),
|
val rpcUsers: List<User> = emptyList(),
|
||||||
val verifierType: VerifierType = VerifierType.InMemory,
|
val verifierType: VerifierType = VerifierType.InMemory,
|
||||||
val cluster: ClusterSpec? = null
|
val cluster: ClusterSpec? = null
|
||||||
)
|
) {
|
||||||
|
init {
|
||||||
|
// TODO This will be removed once network parameters define the notaries
|
||||||
|
when (cluster) {
|
||||||
|
is ClusterSpec.Raft -> require(name.commonName == RaftValidatingNotaryService.id)
|
||||||
|
null -> require(name.commonName == null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class ClusterSpec {
|
sealed class ClusterSpec {
|
||||||
abstract val clusterSize: Int
|
abstract val clusterSize: Int
|
||||||
|
@ -2,15 +2,11 @@ package net.corda.smoketesting
|
|||||||
|
|
||||||
import net.corda.client.rpc.CordaRPCClient
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.client.rpc.CordaRPCConnection
|
import net.corda.client.rpc.CordaRPCConnection
|
||||||
import net.corda.client.rpc.internal.KryoClientSerializationScheme
|
|
||||||
import net.corda.core.internal.copyTo
|
import net.corda.core.internal.copyTo
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.testing.common.internal.NetworkParametersCopier
|
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
|
||||||
import net.corda.testing.common.internal.asContextEnv
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@ -53,14 +49,6 @@ class NodeProcess(
|
|||||||
private companion object {
|
private companion object {
|
||||||
val javaPath: Path = Paths.get(System.getProperty("java.home"), "bin", "java")
|
val javaPath: Path = Paths.get(System.getProperty("java.home"), "bin", "java")
|
||||||
val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(systemDefault())
|
val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(systemDefault())
|
||||||
val defaultNetworkParameters = run {
|
|
||||||
KryoClientSerializationScheme.createSerializationEnv().asContextEnv {
|
|
||||||
// There are no notaries in the network parameters for smoke test nodes. If this is required then we would
|
|
||||||
// need to introduce the concept of a "network" which predefines the notaries, like the driver and MockNetwork
|
|
||||||
NetworkParametersCopier(testNetworkParameters(emptyList()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
try {
|
try {
|
||||||
Class.forName("net.corda.node.Corda")
|
Class.forName("net.corda.node.Corda")
|
||||||
@ -80,7 +68,6 @@ class NodeProcess(
|
|||||||
log.info("Node directory: {}", nodeDir)
|
log.info("Node directory: {}", nodeDir)
|
||||||
|
|
||||||
config.toText().byteInputStream().copyTo(nodeDir / "node.conf")
|
config.toText().byteInputStream().copyTo(nodeDir / "node.conf")
|
||||||
defaultNetworkParameters.install(nodeDir)
|
|
||||||
|
|
||||||
val process = startNode(nodeDir)
|
val process = startNode(nodeDir)
|
||||||
val client = CordaRPCClient(NetworkHostAndPort("localhost", config.rpcPort))
|
val client = CordaRPCClient(NetworkHostAndPort("localhost", config.rpcPort))
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
package net.corda.testing.common.internal
|
|
||||||
|
|
||||||
import net.corda.core.crypto.SignedData
|
|
||||||
import net.corda.core.crypto.entropyToKeyPair
|
|
||||||
import net.corda.core.crypto.sign
|
|
||||||
import net.corda.core.internal.copyTo
|
|
||||||
import net.corda.core.internal.div
|
|
||||||
import net.corda.core.node.NetworkParameters
|
|
||||||
import net.corda.core.serialization.serialize
|
|
||||||
import java.math.BigInteger
|
|
||||||
import java.nio.file.FileAlreadyExistsException
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
class NetworkParametersCopier(networkParameters: NetworkParameters) {
|
|
||||||
private companion object {
|
|
||||||
val DUMMY_MAP_KEY = entropyToKeyPair(BigInteger.valueOf(123))
|
|
||||||
}
|
|
||||||
|
|
||||||
private val serializedNetworkParameters = networkParameters.let {
|
|
||||||
val serialize = it.serialize()
|
|
||||||
val signature = DUMMY_MAP_KEY.sign(serialize)
|
|
||||||
SignedData(serialize, signature).serialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun install(dir: Path) {
|
|
||||||
try {
|
|
||||||
serializedNetworkParameters.open().copyTo(dir / "network-parameters")
|
|
||||||
} catch (e: FileAlreadyExistsException) {
|
|
||||||
// Leave the file untouched if it already exists
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package net.corda.testing.common.internal
|
|
||||||
|
|
||||||
import net.corda.core.node.NetworkParameters
|
|
||||||
import net.corda.core.node.NotaryInfo
|
|
||||||
import net.corda.core.utilities.days
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
fun testNetworkParameters(notaries: List<NotaryInfo>): NetworkParameters {
|
|
||||||
return NetworkParameters(
|
|
||||||
minimumPlatformVersion = 1,
|
|
||||||
notaries = notaries,
|
|
||||||
modifiedTime = Instant.now(),
|
|
||||||
eventHorizon = 10000.days,
|
|
||||||
maxMessageSize = 40000,
|
|
||||||
maxTransactionSize = 40000,
|
|
||||||
epoch = 1
|
|
||||||
)
|
|
||||||
}
|
|
@ -24,7 +24,7 @@ val dummyNotarisationTest = LoadTest<NotariseCommand, Unit>(
|
|||||||
val issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY)
|
val issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY)
|
||||||
val generateTx = Generator.pickOne(simpleNodes).flatMap { node ->
|
val generateTx = Generator.pickOne(simpleNodes).flatMap { node ->
|
||||||
Generator.int().map {
|
Generator.int().map {
|
||||||
val issueBuilder = DummyContract.generateInitial(it, notary.info.legalIdentities[0], DUMMY_CASH_ISSUER) // TODO notary choice
|
val issueBuilder = DummyContract.generateInitial(it, notary.info.legalIdentities[1], DUMMY_CASH_ISSUER) // TODO notary choice
|
||||||
val issueTx = issuerServices.signInitialTransaction(issueBuilder)
|
val issueTx = issuerServices.signInitialTransaction(issueBuilder)
|
||||||
val asset = issueTx.tx.outRef<DummyContract.SingleOwnerState>(0)
|
val asset = issueTx.tx.outRef<DummyContract.SingleOwnerState>(0)
|
||||||
val moveBuilder = DummyContract.move(asset, DUMMY_CASH_ISSUER.party)
|
val moveBuilder = DummyContract.move(asset, DUMMY_CASH_ISSUER.party)
|
||||||
|
Loading…
Reference in New Issue
Block a user