Merge remote-tracking branch 'community/master'

This commit is contained in:
Michal Kit 2017-08-15 17:42:57 +01:00
commit a3ab62341c
26 changed files with 150 additions and 78 deletions

View File

@ -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)

View File

@ -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

View File

@ -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]
}

View File

@ -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>() {

View File

@ -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.
*/

View File

@ -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,

View File

@ -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"

View File

@ -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) {

View File

@ -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,

View File

@ -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()

View File

@ -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

View File

@ -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) {

View File

@ -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()}")

View File

@ -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()

View File

@ -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
}

View File

@ -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 }
}

View File

@ -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

View File

@ -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" }

View File

@ -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 {

View File

@ -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()

View File

@ -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)
}

View File

@ -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) {

View File

@ -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')
}

View File

@ -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%"

View File

@ -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

View File

@ -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")