mirror of
https://github.com/corda/corda.git
synced 2024-12-28 00:38:55 +00:00
Merge remote-tracking branch 'community/master'
This commit is contained in:
commit
a3ab62341c
@ -19,6 +19,7 @@ import net.corda.core.messaging.RPCOps
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.utilities.*
|
||||
import net.corda.nodeapi.*
|
||||
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration
|
||||
import org.apache.activemq.artemis.api.core.SimpleString
|
||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient.DEFAULT_ACK_BATCH_SIZE
|
||||
import org.apache.activemq.artemis.api.core.client.ClientMessage
|
||||
@ -164,7 +165,7 @@ class RPCClientProxyHandler(
|
||||
TimeUnit.MILLISECONDS
|
||||
)
|
||||
sessionAndProducerPool.run {
|
||||
it.session.createTemporaryQueue(clientAddress, clientAddress)
|
||||
it.session.createTemporaryQueue(clientAddress, ActiveMQDefaultConfiguration.getDefaultRoutingType(), clientAddress)
|
||||
}
|
||||
val sessionFactory = serverLocator.createSessionFactory()
|
||||
val session = sessionFactory.createSession(rpcUsername, rpcPassword, false, true, true, false, DEFAULT_ACK_BATCH_SIZE)
|
||||
|
@ -65,8 +65,8 @@ public class StandaloneCordaRPCJavaClientTest {
|
||||
}
|
||||
|
||||
private NodeInfo fetchNotaryIdentity() {
|
||||
DataFeed<List<NodeInfo>, NetworkMapCache.MapChange> nodeDataFeed = rpcProxy.networkMapFeed();
|
||||
return nodeDataFeed.getSnapshot().get(0);
|
||||
List<NodeInfo> nodeDataSnapshot = rpcProxy.networkMapSnapshot();
|
||||
return nodeDataSnapshot.get(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -202,8 +202,7 @@ class StandaloneCordaRPClientTest {
|
||||
}
|
||||
|
||||
private fun fetchNotaryIdentity(): NodeInfo {
|
||||
val (nodeInfo, nodeUpdates) = rpcProxy.networkMapFeed()
|
||||
nodeUpdates.notUsed()
|
||||
val nodeInfo = rpcProxy.networkMapSnapshot()
|
||||
assertEquals(1, nodeInfo.size)
|
||||
return nodeInfo[0]
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ import java.security.PublicKey
|
||||
* builder.toWireTransaction().toLedgerTransaction(serviceHub).verify()
|
||||
*
|
||||
* // Transaction creator signs transaction.
|
||||
* val ptx = builder.signWith(serviceHub.legalIdentityKey).toSignedTransaction(false)
|
||||
* val ptx = serviceHub.signInitialTransaction(builder)
|
||||
*
|
||||
* // Call to CollectSignaturesFlow.
|
||||
* // The returned signed transaction will have all signatures appended apart from the notary's.
|
||||
@ -58,7 +58,7 @@ import java.security.PublicKey
|
||||
* @param partiallySignedTx Transaction to collect the remaining signatures for
|
||||
*/
|
||||
// TODO: AbstractStateReplacementFlow needs updating to use this flow.
|
||||
// TODO: Update this flow to handle randomly generated keys when that works is complete.
|
||||
// TODO: Update this flow to handle randomly generated keys when that work is complete.
|
||||
class CollectSignaturesFlow(val partiallySignedTx: SignedTransaction,
|
||||
override val progressTracker: ProgressTracker = CollectSignaturesFlow.tracker()) : FlowLogic<SignedTransaction>() {
|
||||
|
||||
|
@ -60,6 +60,11 @@ interface CordaRPCOps : RPCOps {
|
||||
*/
|
||||
override val protocolVersion: Int get() = nodeIdentity().platformVersion
|
||||
|
||||
/**
|
||||
* Returns a list of currently in-progress state machine infos.
|
||||
*/
|
||||
fun stateMachinesSnapshot(): List<StateMachineInfo>
|
||||
|
||||
/**
|
||||
* Returns a data feed of currently in-progress state machine infos and an observable of future state machine adds/removes.
|
||||
*/
|
||||
@ -151,12 +156,22 @@ interface CordaRPCOps : RPCOps {
|
||||
}
|
||||
// DOCEND VaultTrackAPIHelpers
|
||||
|
||||
/**
|
||||
* Returns a list of all recorded transactions.
|
||||
*/
|
||||
fun verifiedTransactionsSnapshot(): List<SignedTransaction>
|
||||
|
||||
/**
|
||||
* Returns a data feed of all recorded transactions and an observable of future recorded ones.
|
||||
*/
|
||||
@RPCReturnsObservables
|
||||
fun verifiedTransactionsFeed(): DataFeed<List<SignedTransaction>, SignedTransaction>
|
||||
|
||||
/**
|
||||
* Returns a snapshot list of existing state machine id - recorded transaction hash mappings.
|
||||
*/
|
||||
fun stateMachineRecordedTransactionMappingSnapshot(): List<StateMachineTransactionMapping>
|
||||
|
||||
/**
|
||||
* Returns a snapshot list of existing state machine id - recorded transaction hash mappings, and a stream of future
|
||||
* such mappings as well.
|
||||
@ -164,6 +179,11 @@ interface CordaRPCOps : RPCOps {
|
||||
@RPCReturnsObservables
|
||||
fun stateMachineRecordedTransactionMappingFeed(): DataFeed<List<StateMachineTransactionMapping>, StateMachineTransactionMapping>
|
||||
|
||||
/**
|
||||
* Returns all parties currently visible on the network with their advertised services.
|
||||
*/
|
||||
fun networkMapSnapshot(): List<NodeInfo>
|
||||
|
||||
/**
|
||||
* Returns all parties currently visible on the network with their advertised services and an observable of future updates to the network.
|
||||
*/
|
||||
|
@ -16,6 +16,7 @@ import java.security.cert.*
|
||||
interface IdentityService {
|
||||
val trustRoot: X509Certificate
|
||||
val trustRootHolder: X509CertificateHolder
|
||||
val trustAnchor: TrustAnchor
|
||||
val caCertStore: CertStore
|
||||
|
||||
/**
|
||||
@ -31,11 +32,12 @@ interface IdentityService {
|
||||
/**
|
||||
* Verify and then store an identity.
|
||||
*
|
||||
* @param identity a party representing a legal entity and the certificate path linking them to the network trust root.
|
||||
* @param identity a party and the certificate path linking them to the network trust root.
|
||||
* @return the issuing entity, if known.
|
||||
* @throws IllegalArgumentException if the certificate path is invalid.
|
||||
*/
|
||||
@Throws(CertificateExpiredException::class, CertificateNotYetValidException::class, InvalidAlgorithmParameterException::class)
|
||||
fun verifyAndRegisterIdentity(identity: PartyAndCertificate)
|
||||
fun verifyAndRegisterIdentity(identity: PartyAndCertificate): PartyAndCertificate?
|
||||
|
||||
/**
|
||||
* Asserts that an anonymous party maps to the given full party, by looking up the certificate chain associated with
|
||||
@ -62,9 +64,11 @@ interface IdentityService {
|
||||
/**
|
||||
* Get the certificate and path for a well known identity.
|
||||
*
|
||||
* @return the party and certificate, or null if unknown.
|
||||
* @return the party and certificate.
|
||||
* @throws IllegalArgumentException if the certificate and path are unknown. This should never happen for a well
|
||||
* known identity.
|
||||
*/
|
||||
fun certificateFromParty(party: Party): PartyAndCertificate?
|
||||
fun certificateFromParty(party: Party): PartyAndCertificate
|
||||
|
||||
// There is no method for removing identities, as once we are made aware of a Party we want to keep track of them
|
||||
// indefinitely. It may be that in the long term we need to drop or archive very old Party information for space,
|
||||
|
@ -33,9 +33,9 @@ sourceSets {
|
||||
compileTestJava.dependsOn tasks.getByPath(':node:capsule:buildCordaJAR')
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile project(':client:jfx')
|
||||
compile project(':test-utils')
|
||||
cordaCompile project(':core')
|
||||
cordaCompile project(':client:jfx')
|
||||
cordaCompile project(':test-utils')
|
||||
testCompile project(':verifier')
|
||||
|
||||
compile "org.graphstream:gs-core:1.3"
|
||||
@ -43,8 +43,8 @@ dependencies {
|
||||
exclude group: "bouncycastle"
|
||||
}
|
||||
|
||||
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
|
||||
cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
cordaCompile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
|
||||
}
|
||||
|
||||
mainClassName = "net.corda.docs.ClientRpcTutorialKt"
|
||||
|
@ -112,8 +112,7 @@ fun generateTransactions(proxy: CordaRPCOps) {
|
||||
sum + state.state.data.amount.quantity
|
||||
}
|
||||
val issueRef = OpaqueBytes.of(0)
|
||||
val (parties, partyUpdates) = proxy.networkMapFeed()
|
||||
partyUpdates.notUsed()
|
||||
val parties = proxy.networkMapSnapshot()
|
||||
val notary = parties.first { it.advertisedServices.any { it.info.type.isNotary() } }.notaryIdentity
|
||||
val me = proxy.nodeIdentity().legalIdentity
|
||||
while (true) {
|
||||
|
@ -67,6 +67,7 @@ import net.corda.node.utilities.*
|
||||
import net.corda.node.utilities.AddOrRemove.ADD
|
||||
import org.apache.activemq.artemis.utils.ReusableLatch
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import org.slf4j.Logger
|
||||
import rx.Observable
|
||||
import java.io.IOException
|
||||
@ -298,7 +299,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
.map { (initiatingFlow, initiatedFlows) ->
|
||||
val sorted = initiatedFlows.sortedWith(FlowTypeHierarchyComparator(initiatingFlow))
|
||||
if (sorted.size > 1) {
|
||||
log.warn("${initiatingFlow.name} has been specified as the inititating flow by multiple flows " +
|
||||
log.warn("${initiatingFlow.name} has been specified as the initiating flow by multiple flows " +
|
||||
"in the same type hierarchy: ${sorted.joinToString { it.name }}. Choosing the most " +
|
||||
"specific sub-type for registration: ${sorted[0].name}.")
|
||||
}
|
||||
@ -657,11 +658,11 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
.filterNotNull()
|
||||
.toTypedArray()
|
||||
val service = InMemoryIdentityService(setOf(info.legalIdentityAndCert), trustRoot = trustRoot, caCertificates = *caCertificates)
|
||||
services.networkMapCache.partyNodes.forEach { service.registerIdentity(it.legalIdentityAndCert) }
|
||||
services.networkMapCache.partyNodes.forEach { service.verifyAndRegisterIdentity(it.legalIdentityAndCert) }
|
||||
services.networkMapCache.changed.subscribe { mapChange ->
|
||||
// TODO how should we handle network map removal
|
||||
if (mapChange is MapChange.Added) {
|
||||
service.registerIdentity(mapChange.node.legalIdentityAndCert)
|
||||
service.verifyAndRegisterIdentity(mapChange.node.legalIdentityAndCert)
|
||||
}
|
||||
}
|
||||
return service
|
||||
@ -718,24 +719,26 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
}
|
||||
}
|
||||
|
||||
val (cert, keyPair) = keyStore.certificateAndKeyPair(privateKeyAlias)
|
||||
|
||||
val (cert, keys) = keyStore.certificateAndKeyPair(privateKeyAlias)
|
||||
// Get keys from keystore.
|
||||
val loadedServiceName = cert.subject
|
||||
if (loadedServiceName != serviceName)
|
||||
throw ConfigurationException("The legal name in the config file doesn't match the stored identity keystore:$serviceName vs $loadedServiceName")
|
||||
|
||||
val certPath = CertificateFactory.getInstance("X509").generateCertPath(keyStore.getCertificateChain(privateKeyAlias).toList())
|
||||
// Use composite key instead if exists
|
||||
// TODO: Use configuration to indicate composite key should be used instead of public key for the identity.
|
||||
val publicKey = if (keyStore.containsAlias(compositeKeyAlias)) {
|
||||
Crypto.toSupportedPublicKey(keyStore.getCertificate(compositeKeyAlias).publicKey)
|
||||
val (keyPair, certs) = if (keyStore.containsAlias(compositeKeyAlias)) {
|
||||
val compositeKey = Crypto.toSupportedPublicKey(keyStore.getCertificate(compositeKeyAlias).publicKey)
|
||||
val compositeKeyCert = keyStore.getCertificate(compositeKeyAlias)
|
||||
// We have to create the certificate chain for the composite key manually, this is because in order to store
|
||||
// the chain in keystore we need a private key, however there are no corresponding private key for composite key.
|
||||
Pair(KeyPair(compositeKey, keys.private), listOf(compositeKeyCert, *keyStore.getCertificateChain(X509Utilities.CORDA_CLIENT_CA)))
|
||||
} else {
|
||||
keyPair.public
|
||||
Pair(keys, keyStore.getCertificateChain(privateKeyAlias).toList())
|
||||
}
|
||||
|
||||
partyKeys += keyPair
|
||||
return Pair(PartyAndCertificate(loadedServiceName, publicKey, cert, certPath), keyPair)
|
||||
val certPath = CertificateFactory.getInstance("X509").generateCertPath(certs)
|
||||
partyKeys += keys
|
||||
return Pair(PartyAndCertificate(loadedServiceName, keyPair.public, X509CertificateHolder(certs.first().encoded), certPath), keyPair)
|
||||
}
|
||||
|
||||
private fun migrateKeysFromFile(keyStore: KeyStoreWrapper, serviceName: X500Name,
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.corda.node.internal
|
||||
|
||||
import net.corda.client.rpc.notUsed
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.StateAndRef
|
||||
import net.corda.core.contracts.UpgradedContract
|
||||
@ -39,6 +40,12 @@ class CordaRPCOpsImpl(
|
||||
private val smm: StateMachineManager,
|
||||
private val database: CordaPersistence
|
||||
) : CordaRPCOps {
|
||||
override fun networkMapSnapshot(): List<NodeInfo> {
|
||||
val (snapshot, updates) = networkMapFeed()
|
||||
updates.notUsed()
|
||||
return snapshot
|
||||
}
|
||||
|
||||
override fun networkMapFeed(): DataFeed<List<NodeInfo>, NetworkMapCache.MapChange> {
|
||||
return database.transaction {
|
||||
services.networkMapCache.track()
|
||||
@ -64,12 +71,24 @@ class CordaRPCOpsImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun verifiedTransactionsSnapshot(): List<SignedTransaction> {
|
||||
val (snapshot, updates) = verifiedTransactionsFeed()
|
||||
updates.notUsed()
|
||||
return snapshot
|
||||
}
|
||||
|
||||
override fun verifiedTransactionsFeed(): DataFeed<List<SignedTransaction>, SignedTransaction> {
|
||||
return database.transaction {
|
||||
services.validatedTransactions.track()
|
||||
}
|
||||
}
|
||||
|
||||
override fun stateMachinesSnapshot(): List<StateMachineInfo> {
|
||||
val (snapshot, updates) = stateMachinesFeed()
|
||||
updates.notUsed()
|
||||
return snapshot
|
||||
}
|
||||
|
||||
override fun stateMachinesFeed(): DataFeed<List<StateMachineInfo>, StateMachineUpdate> {
|
||||
return database.transaction {
|
||||
val (allStateMachines, changes) = smm.track()
|
||||
@ -80,6 +99,12 @@ class CordaRPCOpsImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun stateMachineRecordedTransactionMappingSnapshot(): List<StateMachineTransactionMapping> {
|
||||
val (snapshot, updates) = stateMachineRecordedTransactionMappingFeed()
|
||||
updates.notUsed()
|
||||
return snapshot
|
||||
}
|
||||
|
||||
override fun stateMachineRecordedTransactionMappingFeed(): DataFeed<List<StateMachineTransactionMapping>, StateMachineTransactionMapping> {
|
||||
return database.transaction {
|
||||
services.stateMachineRecordedTransactionMapping.track()
|
||||
|
@ -24,6 +24,7 @@ import net.corda.node.services.messaging.MessagingService
|
||||
import net.corda.node.services.messaging.NodeMessagingClient
|
||||
import net.corda.node.utilities.AddressUtils
|
||||
import net.corda.node.utilities.AffinityExecutor
|
||||
import net.corda.node.utilities.TestClock
|
||||
import net.corda.nodeapi.ArtemisMessagingComponent
|
||||
import net.corda.nodeapi.ArtemisMessagingComponent.Companion.IP_REQUEST_PREFIX
|
||||
import net.corda.nodeapi.ArtemisMessagingComponent.Companion.PEER_USER
|
||||
@ -58,8 +59,8 @@ import kotlin.system.exitProcess
|
||||
open class Node(override val configuration: FullNodeConfiguration,
|
||||
advertisedServices: Set<ServiceInfo>,
|
||||
val versionInfo: VersionInfo,
|
||||
clock: Clock = NodeClock(),
|
||||
val initialiseSerialization: Boolean = true) : AbstractNode(configuration, advertisedServices, clock) {
|
||||
val initialiseSerialization: Boolean = true
|
||||
) : AbstractNode(configuration, advertisedServices, createClock(configuration)) {
|
||||
companion object {
|
||||
private val logger = loggerFor<Node>()
|
||||
var renderBasicInfoToConsole = true
|
||||
@ -76,6 +77,10 @@ open class Node(override val configuration: FullNodeConfiguration,
|
||||
println("Corda will now exit...")
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
private fun createClock(configuration: FullNodeConfiguration): Clock {
|
||||
return if (configuration.useTestClock) TestClock() else NodeClock()
|
||||
}
|
||||
}
|
||||
|
||||
override val log: Logger get() = logger
|
||||
|
@ -97,7 +97,7 @@ open class NodeStartup(val args: Array<String>) {
|
||||
open protected fun preNetworkRegistration(conf: FullNodeConfiguration) = Unit
|
||||
|
||||
open protected fun createNode(conf: FullNodeConfiguration, versionInfo: VersionInfo, services: Set<ServiceInfo>): Node {
|
||||
return Node(conf, services, versionInfo, if (conf.useTestClock) TestClock() else NodeClock())
|
||||
return Node(conf, services, versionInfo)
|
||||
}
|
||||
|
||||
open protected fun startNode(conf: FullNodeConfiguration, versionInfo: VersionInfo, startTime: Long, cmdlineOptions: CmdLineOptions) {
|
||||
|
@ -44,9 +44,8 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
|
||||
*/
|
||||
override val caCertStore: CertStore
|
||||
override val trustRootHolder = X509CertificateHolder(trustRoot.encoded)
|
||||
private val trustAnchor: TrustAnchor = TrustAnchor(trustRoot, null)
|
||||
override val trustAnchor: TrustAnchor = TrustAnchor(trustRoot, null)
|
||||
private val keyToParties = ConcurrentHashMap<PublicKey, PartyAndCertificate>()
|
||||
private val keyToIssuingParty = ConcurrentHashMap<PublicKey, PartyAndCertificate>()
|
||||
private val principalToParties = ConcurrentHashMap<X500Name, PartyAndCertificate>()
|
||||
|
||||
init {
|
||||
@ -56,16 +55,17 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
|
||||
principalToParties.putAll(identities.associateBy { it.name })
|
||||
confidentialIdentities.forEach { identity ->
|
||||
require(identity.certPath.certificates.size >= 2) { "Certificate path must at least include subject and issuing certificates" }
|
||||
keyToIssuingParty[identity.owningKey] = keyToParties[identity.certPath.certificates[1].publicKey]!!
|
||||
principalToParties.computeIfAbsent(identity.name) { identity }
|
||||
}
|
||||
}
|
||||
|
||||
override fun registerIdentity(party: PartyAndCertificate) = verifyAndRegisterIdentity(party)
|
||||
override fun registerIdentity(party: PartyAndCertificate) {
|
||||
verifyAndRegisterIdentity(party)
|
||||
}
|
||||
|
||||
// TODO: Check the certificate validation logic
|
||||
@Throws(CertificateExpiredException::class, CertificateNotYetValidException::class, InvalidAlgorithmParameterException::class)
|
||||
override fun verifyAndRegisterIdentity(identity: PartyAndCertificate) {
|
||||
override fun verifyAndRegisterIdentity(identity: PartyAndCertificate): PartyAndCertificate? {
|
||||
require(identity.certPath.certificates.size >= 2) { "Certificate path must at least include subject and issuing certificates" }
|
||||
// Validate the chain first, before we do anything clever with it
|
||||
identity.verify(trustAnchor)
|
||||
@ -74,25 +74,32 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
|
||||
require(Arrays.equals(identity.certificate.subjectPublicKeyInfo.encoded, identity.owningKey.encoded)) { "Party certificate must end with party's public key" }
|
||||
|
||||
keyToParties[identity.owningKey] = identity
|
||||
// TODO: This map should only be deanonymised parties, not all issuers, but we have no good way of checking for
|
||||
// confidential vs anonymous identities
|
||||
val issuer = keyToParties[identity.certPath.certificates[1].publicKey]
|
||||
if (issuer != null) {
|
||||
keyToIssuingParty[identity.owningKey] = issuer
|
||||
}
|
||||
// Always keep the first party we registered, as that's the well known identity
|
||||
principalToParties.computeIfAbsent(identity.name) { identity }
|
||||
return keyToParties[identity.certPath.certificates[1].publicKey]
|
||||
}
|
||||
|
||||
override fun certificateFromKey(owningKey: PublicKey): PartyAndCertificate? = keyToParties[owningKey]
|
||||
override fun certificateFromParty(party: Party): PartyAndCertificate? = principalToParties[party.name]
|
||||
override fun certificateFromParty(party: Party): PartyAndCertificate = principalToParties[party.name] ?: throw IllegalArgumentException("Unknown identity ${party.name}")
|
||||
|
||||
// We give the caller a copy of the data set to avoid any locking problems
|
||||
override fun getAllIdentities(): Iterable<PartyAndCertificate> = java.util.ArrayList(keyToParties.values)
|
||||
|
||||
override fun partyFromKey(key: PublicKey): Party? = keyToParties[key]?.party
|
||||
override fun partyFromX500Name(principal: X500Name): Party? = principalToParties[principal]?.party
|
||||
override fun partyFromAnonymous(party: AbstractParty) = party as? Party ?: keyToIssuingParty[party.owningKey]?.party
|
||||
override fun partyFromAnonymous(party: AbstractParty): Party? {
|
||||
// Expand the anonymous party to a full party (i.e. has a name) if possible
|
||||
val candidate = party as? Party ?: keyToParties[party.owningKey]?.party
|
||||
// TODO: This should be done via the network map cache, which is the authoritative source of well known identities
|
||||
// Look up the well known identity for that name
|
||||
return if (candidate != null) {
|
||||
// If we have a well known identity by that name, use it in preference to the candidate. Otherwise default
|
||||
// back to the candidate.
|
||||
principalToParties[candidate.name]?.party ?: candidate
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
override fun partyFromAnonymous(partyRef: PartyAndReference) = partyFromAnonymous(partyRef.party)
|
||||
override fun requirePartyFromAnonymous(party: AbstractParty): Party {
|
||||
return partyFromAnonymous(party) ?: throw IllegalStateException("Could not deanonymise party ${party.owningKey.toStringShort()}")
|
||||
|
@ -200,8 +200,8 @@ class TwoPartyTradeFlowTests {
|
||||
val cashIssuer = bankNode.info.legalIdentity.ref(1)
|
||||
val cpIssuer = bankNode.info.legalIdentity.ref(1, 2, 3)
|
||||
|
||||
aliceNode.services.identityService.registerIdentity(bobNode.info.legalIdentityAndCert)
|
||||
bobNode.services.identityService.registerIdentity(aliceNode.info.legalIdentityAndCert)
|
||||
aliceNode.services.identityService.verifyAndRegisterIdentity(bobNode.info.legalIdentityAndCert)
|
||||
bobNode.services.identityService.verifyAndRegisterIdentity(aliceNode.info.legalIdentityAndCert)
|
||||
aliceNode.disableDBCloseOnStop()
|
||||
bobNode.disableDBCloseOnStop()
|
||||
|
||||
|
@ -7,6 +7,7 @@ import net.corda.core.toFuture
|
||||
import net.corda.core.internal.concurrent.transpose
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.core.utilities.seconds
|
||||
import net.corda.irs.api.NodeInterestRates
|
||||
import net.corda.irs.contract.InterestRateSwap
|
||||
@ -29,6 +30,11 @@ import java.time.Duration
|
||||
import java.time.LocalDate
|
||||
|
||||
class IRSDemoTest : IntegrationTestCategory {
|
||||
|
||||
companion object {
|
||||
val log = loggerFor<IRSDemoTest>()
|
||||
}
|
||||
|
||||
val rpcUser = User("user", "password", emptySet())
|
||||
val currentDate: LocalDate = LocalDate.now()
|
||||
val futureDate: LocalDate = currentDate.plusMonths(6)
|
||||
@ -43,7 +49,7 @@ class IRSDemoTest : IntegrationTestCategory {
|
||||
startNode(DUMMY_BANK_B.name)
|
||||
).transpose().getOrThrow()
|
||||
|
||||
println("All nodes started")
|
||||
log.info("All nodes started")
|
||||
|
||||
val (controllerAddr, nodeAAddr, nodeBAddr) = listOf(
|
||||
startWebserver(controller),
|
||||
@ -51,7 +57,7 @@ class IRSDemoTest : IntegrationTestCategory {
|
||||
startWebserver(nodeB)
|
||||
).transpose().getOrThrow().map { it.listenAddress }
|
||||
|
||||
println("All webservers started")
|
||||
log.info("All webservers started")
|
||||
|
||||
val (_, nodeAApi, nodeBApi) = listOf(controller, nodeA, nodeB).zip(listOf(controllerAddr, nodeAAddr, nodeBAddr)).map {
|
||||
val mapper = net.corda.jackson.JacksonSupport.createDefaultMapper(it.first.rpc)
|
||||
@ -85,25 +91,25 @@ class IRSDemoTest : IntegrationTestCategory {
|
||||
val vaultUpdates = proxy.vaultTrackBy<InterestRateSwap.State>().updates
|
||||
|
||||
return vaultUpdates.map { update ->
|
||||
val irsStates = update.produced.map { it.state.data }.filterIsInstance<InterestRateSwap.State>()
|
||||
val irsStates = update.produced.map { it.state.data }
|
||||
irsStates.mapNotNull { it.calculation.nextFixingDate() }.max()
|
||||
}.cache()
|
||||
}
|
||||
|
||||
private fun runDateChange(nodeApi: HttpApi) {
|
||||
println("Running date change against ${nodeApi.root}")
|
||||
log.info("Running date change against ${nodeApi.root}")
|
||||
assertThat(nodeApi.putJson("demodate", "\"$futureDate\"")).isTrue()
|
||||
}
|
||||
|
||||
private fun runTrade(nodeApi: HttpApi) {
|
||||
println("Running trade against ${nodeApi.root}")
|
||||
log.info("Running trade against ${nodeApi.root}")
|
||||
val fileContents = loadResourceFile("net/corda/irs/simulation/example-irs-trade.json")
|
||||
val tradeFile = fileContents.replace("tradeXXX", "trade1")
|
||||
assertThat(nodeApi.postJson("deals", tradeFile)).isTrue()
|
||||
}
|
||||
|
||||
private fun runUploadRates(host: NetworkHostAndPort) {
|
||||
println("Running upload rates against $host")
|
||||
log.info("Running upload rates against $host")
|
||||
val fileContents = loadResourceFile("net/corda/irs/simulation/example.rates.txt")
|
||||
val url = URL("http://$host/api/irs/fixes")
|
||||
assertThat(uploadFile(url, fileContents)).isTrue()
|
||||
@ -114,13 +120,13 @@ class IRSDemoTest : IntegrationTestCategory {
|
||||
}
|
||||
|
||||
private fun getTradeCount(nodeApi: HttpApi): Int {
|
||||
println("Getting trade count from ${nodeApi.root}")
|
||||
log.info("Getting trade count from ${nodeApi.root}")
|
||||
val deals = nodeApi.getJson<Array<*>>("deals")
|
||||
return deals.size
|
||||
}
|
||||
|
||||
private fun getTrades(nodeApi: HttpApi): Array<InterestRateSwap.State> {
|
||||
println("Getting trades from ${nodeApi.root}")
|
||||
log.info("Getting trades from ${nodeApi.root}")
|
||||
val deals = nodeApi.getJson<Array<InterestRateSwap.State>>("deals")
|
||||
return deals
|
||||
}
|
||||
|
@ -27,15 +27,13 @@ fun main(args: Array<String>) {
|
||||
/** Interface for using the notary demo API from a client. */
|
||||
private class NotaryDemoClientApi(val rpc: CordaRPCOps) {
|
||||
private val notary by lazy {
|
||||
val (parties, partyUpdates) = rpc.networkMapFeed()
|
||||
partyUpdates.notUsed()
|
||||
val parties = rpc.networkMapSnapshot()
|
||||
val id = parties.stream().filter { it.advertisedServices.any { it.info.type.isNotary() } }.map { it.notaryIdentity }.distinct().asSequence().singleOrNull()
|
||||
checkNotNull(id) { "No unique notary identity, try cleaning the node directories." }
|
||||
}
|
||||
|
||||
private val counterpartyNode by lazy {
|
||||
val (parties, partyUpdates) = rpc.networkMapFeed()
|
||||
partyUpdates.notUsed()
|
||||
val parties = rpc.networkMapSnapshot()
|
||||
parties.single { it.legalIdentity.name == BOB.name }
|
||||
}
|
||||
|
||||
|
@ -253,8 +253,7 @@ class PortfolioApi(val rpc: CordaRPCOps) {
|
||||
@Path("whoami")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
fun getWhoAmI(): AvailableParties {
|
||||
val (parties, partyUpdates) = rpc.networkMapFeed()
|
||||
partyUpdates.notUsed()
|
||||
val parties = rpc.networkMapSnapshot()
|
||||
val counterParties = parties.filterNot {
|
||||
it.advertisedServices.any { it.info.type in setOf(ServiceType.networkMap, ServiceType.notary) }
|
||||
|| it.legalIdentity == ownParty
|
||||
|
@ -13,7 +13,7 @@ data class OGTrade(override val legalContractReference: SecureHash = SecureHash.
|
||||
requireNotNull(tx.timeWindow) { "must have a time-window" }
|
||||
val groups: List<LedgerTransaction.InOutGroup<IRSState, UniqueIdentifier>> = tx.groupStates { state -> state.linearId }
|
||||
var atLeastOneCommandProcessed = false
|
||||
for ((inputs, outputs, key) in groups) {
|
||||
for ((inputs, outputs, _) in groups) {
|
||||
val command = tx.commands.select<Commands.Agree>().firstOrNull()
|
||||
if (command != null) {
|
||||
require(inputs.isEmpty()) { "Inputs must be empty" }
|
||||
|
@ -13,7 +13,7 @@ data class PortfolioSwap(override val legalContractReference: SecureHash = Secur
|
||||
override fun verify(tx: LedgerTransaction) {
|
||||
requireNotNull(tx.timeWindow) { "must have a time-window)" }
|
||||
val groups: List<LedgerTransaction.InOutGroup<PortfolioState, UniqueIdentifier>> = tx.groupStates { state -> state.linearId }
|
||||
for ((inputs, outputs, key) in groups) {
|
||||
for ((inputs, outputs, _) in groups) {
|
||||
val agreeCommand = tx.commands.select<Commands.Agree>().firstOrNull()
|
||||
if (agreeCommand != null) {
|
||||
requireThat {
|
||||
|
@ -772,9 +772,8 @@ class DriverDSL(
|
||||
log.info("Starting in-process Node ${nodeConf.myLegalName.commonName}")
|
||||
// Write node.conf
|
||||
writeConfig(nodeConf.baseDirectory, "node.conf", config)
|
||||
val clock: Clock = if (nodeConf.useTestClock) TestClock() else NodeClock()
|
||||
// TODO pass the version in?
|
||||
val node = Node(nodeConf, nodeConf.calculateServices(), MOCK_VERSION_INFO, clock, initialiseSerialization = false)
|
||||
val node = Node(nodeConf, nodeConf.calculateServices(), MOCK_VERSION_INFO, initialiseSerialization = false)
|
||||
node.start()
|
||||
val nodeThread = thread(name = nodeConf.myLegalName.commonName) {
|
||||
node.run()
|
||||
|
@ -356,7 +356,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
||||
nodes += createPartyNode(mapAddress)
|
||||
}
|
||||
nodes.forEach { itNode ->
|
||||
nodes.map { it.info.legalIdentityAndCert }.forEach(itNode.services.identityService::verifyAndRegisterIdentity)
|
||||
nodes.map { it.info.legalIdentityAndCert }.map(itNode.services.identityService::verifyAndRegisterIdentity)
|
||||
}
|
||||
return BasketOfNodes(nodes, notaryNode, mapNode)
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
||||
|
||||
val parsedConfig = config.parseAs<FullNodeConfiguration>()
|
||||
val node = Node(parsedConfig, parsedConfig.calculateServices(), MOCK_VERSION_INFO.copy(platformVersion = platformVersion),
|
||||
if (parsedConfig.useTestClock) TestClock() else NodeClock(), initialiseSerialization = false)
|
||||
initialiseSerialization = false)
|
||||
node.start()
|
||||
nodes += node
|
||||
thread(name = legalName.commonName) {
|
||||
|
@ -8,7 +8,7 @@ buildscript {
|
||||
ext.pkg_source = "$buildDir/packagesrc"
|
||||
ext.pkg_outDir = "$buildDir/javapackage"
|
||||
ext.dist_source = "$pkg_source/demobench-$version"
|
||||
ext.pkg_version = "$version".indexOf('-') >= 0 ? "$version".substring(0, "$version".indexOf('-')) : version
|
||||
ext.pkg_version = version.indexOf('-') >= 0 ? version.substring(0, version.indexOf('-')) : version
|
||||
ext.pkg_macosxKeyUserName = 'R3CEV'
|
||||
|
||||
repositories {
|
||||
@ -25,8 +25,8 @@ evaluationDependsOn(':tools:explorer:capsule')
|
||||
|
||||
mainClassName = 'net.corda.demobench.DemoBench'
|
||||
applicationDefaultJvmArgs = [
|
||||
'-Djava.util.logging.config.class=net.corda.demobench.config.LoggingConfig',
|
||||
'-Dorg.jboss.logging.provider=slf4j'
|
||||
'-Djava.util.logging.config.class=net.corda.demobench.config.LoggingConfig',
|
||||
'-Dorg.jboss.logging.provider=slf4j'
|
||||
]
|
||||
|
||||
repositories {
|
||||
@ -78,7 +78,7 @@ jar {
|
||||
manifest {
|
||||
attributes(
|
||||
'Main-Class': mainClassName,
|
||||
'Class-Path': configurations.compile.collect { it.getName() }.join(' ')
|
||||
'Class-Path': configurations.runtime.collect { it.getName() }.join(' ')
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -165,13 +165,14 @@ task javapackage(dependsOn: distZip) {
|
||||
}
|
||||
|
||||
ant.taskdef(
|
||||
resource: 'com/sun/javafx/tools/ant/antlib.xml',
|
||||
classpath: "$pkg_source:$java_home/../lib/ant-javafx.jar"
|
||||
resource: 'com/sun/javafx/tools/ant/antlib.xml',
|
||||
classpath: "$pkg_source:$java_home/../lib/ant-javafx.jar"
|
||||
)
|
||||
|
||||
ant.deploy(nativeBundles: packageType, outdir: pkg_outDir, outfile: 'DemoBench', verbose: 'true') {
|
||||
application(name: 'Corda DemoBench', version: pkg_version, mainClass: mainClassName)
|
||||
info(title: 'Corda DemoBench', vendor: 'R3', description: 'A sales and educational tool for demonstrating Corda.')
|
||||
//noinspection GroovyAssignabilityCheck
|
||||
resources {
|
||||
fileset(dir: "$dist_source/lib", type: 'jar') {
|
||||
include(name: '*.jar')
|
||||
@ -199,7 +200,9 @@ task javapackage(dependsOn: distZip) {
|
||||
bundleArgument(arg: 'mac.signing-key-user-name', value: pkg_macosxKeyUserName)
|
||||
|
||||
platform {
|
||||
//noinspection GroovyAssignabilityCheck
|
||||
property(name: 'java.util.logging.config.class', value: 'net.corda.demobench.config.LoggingConfig')
|
||||
//noinspection GroovyAssignabilityCheck
|
||||
property(name: 'org.jboss.logging.provider', value: 'slf4j')
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,12 @@ if not exist %1 (
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
rem Bugfixes:
|
||||
rem =========
|
||||
rem
|
||||
rem sun.swing.JLightweightFrame:473
|
||||
rem https://bugs.openjdk.java.net/browse/JDK-8185890
|
||||
|
||||
if exist "%BUILDDIR%" rmdir /s /q "%BUILDDIR%"
|
||||
mkdir "%BUILDDIR%"
|
||||
|
||||
|
@ -20,8 +20,7 @@ fi
|
||||
# =========
|
||||
#
|
||||
# sun.swing.JLightweightFrame:473
|
||||
# https://github.com/JetBrains/jdk8u_jdk/issues/6
|
||||
# https://github.com/JetBrains/jdk8u/issues/8
|
||||
# https://bugs.openjdk.java.net/browse/JDK-8185890
|
||||
|
||||
rm -rf $BUILDDIR && mkdir $BUILDDIR
|
||||
if (javac -O -d $BUILDDIR $(find $SOURCEDIR -name "*.java")); then
|
||||
|
@ -181,8 +181,7 @@ fun runLoadTests(configuration: LoadTestConfiguration, tests: List<Pair<LoadTest
|
||||
log.info("Getting node info of ${connection.remoteNode.hostname}")
|
||||
val info = connection.info
|
||||
log.info("Got node info of ${connection.remoteNode.hostname}: $info!")
|
||||
val (otherInfo, infoUpdates) = connection.proxy.networkMapFeed()
|
||||
infoUpdates.notUsed()
|
||||
val otherInfo = connection.proxy.networkMapSnapshot()
|
||||
val pubKeysString = otherInfo.map {
|
||||
" ${it.legalIdentity.name}: ${it.legalIdentity.owningKey.toBase58String()}"
|
||||
}.joinToString("\n")
|
||||
|
Loading…
Reference in New Issue
Block a user