mirror of
https://github.com/corda/corda.git
synced 2025-02-21 09:51:57 +00:00
Revert "OS 4.3 to OS 4.4 merge on 2019/09/30 (#5534)"
This reverts commit 191fb83dec283259fb2f186c2df5a88659b0e3ac.
This commit is contained in:
parent
191fb83dec
commit
fa2720783a
@ -1,8 +1,8 @@
|
|||||||
package net.corda.client.jfx.model
|
package net.corda.client.jfx.model
|
||||||
|
|
||||||
import javafx.beans.property.SimpleObjectProperty
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
import net.corda.client.rpc.CordaRPCClient
|
import net.corda.client.rpc.CordaRPCClientConfiguration
|
||||||
import net.corda.client.rpc.CordaRPCConnection
|
import net.corda.client.rpc.internal.ReconnectingCordaRPCOps
|
||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
import net.corda.core.flows.StateMachineRunId
|
import net.corda.core.flows.StateMachineRunId
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
@ -48,7 +48,7 @@ class NodeMonitorModel : AutoCloseable {
|
|||||||
val progressTracking: Observable<ProgressTrackingEvent> = progressTrackingSubject
|
val progressTracking: Observable<ProgressTrackingEvent> = progressTrackingSubject
|
||||||
val networkMap: Observable<MapChange> = networkMapSubject
|
val networkMap: Observable<MapChange> = networkMapSubject
|
||||||
|
|
||||||
private lateinit var rpc: CordaRPCConnection
|
private lateinit var rpc: CordaRPCOps
|
||||||
val proxyObservable = SimpleObjectProperty<CordaRPCOps>()
|
val proxyObservable = SimpleObjectProperty<CordaRPCOps>()
|
||||||
lateinit var notaryIdentities: List<Party>
|
lateinit var notaryIdentities: List<Party>
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ class NodeMonitorModel : AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
override fun close() {
|
override fun close() {
|
||||||
try {
|
try {
|
||||||
rpc.close()
|
(rpc as ReconnectingCordaRPCOps).close()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.error("Error closing RPC connection to node", e)
|
logger.error("Error closing RPC connection to node", e)
|
||||||
}
|
}
|
||||||
@ -72,42 +72,35 @@ class NodeMonitorModel : AutoCloseable {
|
|||||||
* TODO provide an unsubscribe mechanism
|
* TODO provide an unsubscribe mechanism
|
||||||
*/
|
*/
|
||||||
fun register(nodeHostAndPort: NetworkHostAndPort, username: String, password: String) {
|
fun register(nodeHostAndPort: NetworkHostAndPort, username: String, password: String) {
|
||||||
rpc = CordaRPCClient(nodeHostAndPort).start(username, password)
|
rpc = ReconnectingCordaRPCOps(nodeHostAndPort, username, password, CordaRPCClientConfiguration.DEFAULT)
|
||||||
proxyObservable.value = rpc.proxy
|
|
||||||
|
proxyObservable.value = rpc
|
||||||
|
|
||||||
// Vault snapshot (force single page load with MAX_PAGE_SIZE) + updates
|
// Vault snapshot (force single page load with MAX_PAGE_SIZE) + updates
|
||||||
val (
|
val (statesSnapshot, vaultUpdates) = rpc.vaultTrackBy<ContractState>(QueryCriteria.VaultQueryCriteria(Vault.StateStatus.ALL),
|
||||||
statesSnapshot,
|
PageSpecification(DEFAULT_PAGE_NUM, MAX_PAGE_SIZE))
|
||||||
vaultUpdates
|
val unconsumedStates = statesSnapshot.states.filterIndexed { index, _ ->
|
||||||
) = rpc.proxy.vaultTrackBy<ContractState>(
|
statesSnapshot.statesMetadata[index].status == Vault.StateStatus.UNCONSUMED
|
||||||
QueryCriteria.VaultQueryCriteria(Vault.StateStatus.ALL),
|
|
||||||
PageSpecification(DEFAULT_PAGE_NUM, MAX_PAGE_SIZE)
|
|
||||||
)
|
|
||||||
val unconsumedStates =
|
|
||||||
statesSnapshot.states.filterIndexed { index, _ ->
|
|
||||||
statesSnapshot.statesMetadata[index].status == Vault.StateStatus.UNCONSUMED
|
|
||||||
}.toSet()
|
}.toSet()
|
||||||
val consumedStates = statesSnapshot.states.toSet() - unconsumedStates
|
val consumedStates = statesSnapshot.states.toSet() - unconsumedStates
|
||||||
val initialVaultUpdate = Vault.Update(consumedStates, unconsumedStates, references = emptySet())
|
val initialVaultUpdate = Vault.Update(consumedStates, unconsumedStates, references = emptySet())
|
||||||
vaultUpdates.startWith(initialVaultUpdate).subscribe(vaultUpdatesSubject::onNext)
|
vaultUpdates.startWith(initialVaultUpdate).subscribe(vaultUpdatesSubject::onNext)
|
||||||
|
|
||||||
// Transactions
|
// Transactions
|
||||||
val (transactions, newTransactions) =
|
val (transactions, newTransactions) = @Suppress("DEPRECATION") rpc.internalVerifiedTransactionsFeed()
|
||||||
@Suppress("DEPRECATION") rpc.proxy.internalVerifiedTransactionsFeed()
|
|
||||||
newTransactions.startWith(transactions).subscribe(transactionsSubject::onNext)
|
newTransactions.startWith(transactions).subscribe(transactionsSubject::onNext)
|
||||||
|
|
||||||
// SM -> TX mapping
|
// SM -> TX mapping
|
||||||
val (smTxMappings, futureSmTxMappings) =
|
val (smTxMappings, futureSmTxMappings) = rpc.stateMachineRecordedTransactionMappingFeed()
|
||||||
rpc.proxy.stateMachineRecordedTransactionMappingFeed()
|
|
||||||
futureSmTxMappings.startWith(smTxMappings).subscribe(stateMachineTransactionMappingSubject::onNext)
|
futureSmTxMappings.startWith(smTxMappings).subscribe(stateMachineTransactionMappingSubject::onNext)
|
||||||
|
|
||||||
// Parties on network
|
// Parties on network
|
||||||
val (parties, futurePartyUpdate) = rpc.proxy.networkMapFeed()
|
val (parties, futurePartyUpdate) = rpc.networkMapFeed()
|
||||||
futurePartyUpdate.startWith(parties.map(MapChange::Added)).subscribe(networkMapSubject::onNext)
|
futurePartyUpdate.startWith(parties.map(MapChange::Added)).subscribe(networkMapSubject::onNext)
|
||||||
|
|
||||||
val stateMachines = rpc.proxy.stateMachinesSnapshot()
|
val stateMachines = rpc.stateMachinesSnapshot()
|
||||||
|
|
||||||
notaryIdentities = rpc.proxy.notaryIdentities()
|
notaryIdentities = rpc.notaryIdentities()
|
||||||
|
|
||||||
// Extract the flow tracking stream
|
// Extract the flow tracking stream
|
||||||
// TODO is there a nicer way of doing this? Stream of streams in general results in code like this...
|
// TODO is there a nicer way of doing this? Stream of streams in general results in code like this...
|
||||||
|
@ -56,8 +56,8 @@ class CordaRPCClientReconnectionTest {
|
|||||||
maxReconnectAttempts = 5
|
maxReconnectAttempts = 5
|
||||||
))
|
))
|
||||||
|
|
||||||
(client.start(rpcUser.username, rpcUser.password, gracefulReconnect = gracefulReconnect)).use {
|
(client.start(rpcUser.username, rpcUser.password, gracefulReconnect = gracefulReconnect).proxy as ReconnectingCordaRPCOps).use {
|
||||||
val rpcOps = it.proxy as ReconnectingCordaRPCOps
|
val rpcOps = it
|
||||||
val networkParameters = rpcOps.networkParameters
|
val networkParameters = rpcOps.networkParameters
|
||||||
val cashStatesFeed = rpcOps.vaultTrack(Cash.State::class.java)
|
val cashStatesFeed = rpcOps.vaultTrack(Cash.State::class.java)
|
||||||
cashStatesFeed.updates.subscribe { latch.countDown() }
|
cashStatesFeed.updates.subscribe { latch.countDown() }
|
||||||
@ -96,8 +96,8 @@ class CordaRPCClientReconnectionTest {
|
|||||||
maxReconnectAttempts = 5
|
maxReconnectAttempts = 5
|
||||||
))
|
))
|
||||||
|
|
||||||
(client.start(rpcUser.username, rpcUser.password, gracefulReconnect = gracefulReconnect)).use {
|
(client.start(rpcUser.username, rpcUser.password, gracefulReconnect = gracefulReconnect).proxy as ReconnectingCordaRPCOps).use {
|
||||||
val rpcOps = it.proxy as ReconnectingCordaRPCOps
|
val rpcOps = it
|
||||||
val cashStatesFeed = rpcOps.vaultTrack(Cash.State::class.java)
|
val cashStatesFeed = rpcOps.vaultTrack(Cash.State::class.java)
|
||||||
val subscription = cashStatesFeed.updates.subscribe { latch.countDown() }
|
val subscription = cashStatesFeed.updates.subscribe { latch.countDown() }
|
||||||
rpcOps.startTrackedFlow(::CashIssueFlow, 10.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue.get()
|
rpcOps.startTrackedFlow(::CashIssueFlow, 10.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue.get()
|
||||||
@ -113,7 +113,6 @@ class CordaRPCClientReconnectionTest {
|
|||||||
latch.await(4, TimeUnit.SECONDS)
|
latch.await(4, TimeUnit.SECONDS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,8 +136,8 @@ class CordaRPCClientReconnectionTest {
|
|||||||
maxReconnectAttempts = 5
|
maxReconnectAttempts = 5
|
||||||
))
|
))
|
||||||
|
|
||||||
(client.start(rpcUser.username, rpcUser.password, gracefulReconnect = gracefulReconnect)).use {
|
(client.start(rpcUser.username, rpcUser.password, gracefulReconnect = gracefulReconnect).proxy as ReconnectingCordaRPCOps).use {
|
||||||
val rpcOps = it.proxy as ReconnectingCordaRPCOps
|
val rpcOps = it
|
||||||
val networkParameters = rpcOps.networkParameters
|
val networkParameters = rpcOps.networkParameters
|
||||||
val cashStatesFeed = rpcOps.vaultTrack(Cash.State::class.java)
|
val cashStatesFeed = rpcOps.vaultTrack(Cash.State::class.java)
|
||||||
cashStatesFeed.updates.subscribe { latch.countDown() }
|
cashStatesFeed.updates.subscribe { latch.countDown() }
|
||||||
|
@ -27,9 +27,6 @@ import net.corda.serialization.internal.amqp.SerializationFactoryCacheKey
|
|||||||
import net.corda.serialization.internal.amqp.SerializerFactory
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ExecutorService
|
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is essentially just a wrapper for an RPCConnection<CordaRPCOps> and can be treated identically.
|
* This class is essentially just a wrapper for an RPCConnection<CordaRPCOps> and can be treated identically.
|
||||||
@ -38,10 +35,9 @@ import java.util.concurrent.TimeUnit
|
|||||||
*/
|
*/
|
||||||
class CordaRPCConnection private constructor(
|
class CordaRPCConnection private constructor(
|
||||||
private val oneTimeConnection: RPCConnection<CordaRPCOps>?,
|
private val oneTimeConnection: RPCConnection<CordaRPCOps>?,
|
||||||
private val observersPool: ExecutorService?,
|
|
||||||
private val reconnectingCordaRPCOps: ReconnectingCordaRPCOps?
|
private val reconnectingCordaRPCOps: ReconnectingCordaRPCOps?
|
||||||
) : RPCConnection<CordaRPCOps> {
|
) : RPCConnection<CordaRPCOps> {
|
||||||
internal constructor(connection: RPCConnection<CordaRPCOps>?) : this(connection, null, null)
|
internal constructor(connection: RPCConnection<CordaRPCOps>?) : this(connection, null)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@CordaInternal
|
@CordaInternal
|
||||||
@ -50,20 +46,14 @@ class CordaRPCConnection private constructor(
|
|||||||
password: String,
|
password: String,
|
||||||
addresses: List<NetworkHostAndPort>,
|
addresses: List<NetworkHostAndPort>,
|
||||||
rpcConfiguration: CordaRPCClientConfiguration,
|
rpcConfiguration: CordaRPCClientConfiguration,
|
||||||
gracefulReconnect: GracefulReconnect,
|
gracefulReconnect: GracefulReconnect
|
||||||
sslConfiguration: ClientRpcSslOptions? = null,
|
|
||||||
classLoader: ClassLoader? = null
|
|
||||||
): CordaRPCConnection {
|
): CordaRPCConnection {
|
||||||
val observersPool: ExecutorService = Executors.newCachedThreadPool()
|
return CordaRPCConnection(null, ReconnectingCordaRPCOps(
|
||||||
return CordaRPCConnection(null, observersPool, ReconnectingCordaRPCOps(
|
|
||||||
addresses,
|
addresses,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
rpcConfiguration,
|
rpcConfiguration,
|
||||||
gracefulReconnect,
|
gracefulReconnect
|
||||||
sslConfiguration,
|
|
||||||
classLoader,
|
|
||||||
observersPool
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,18 +69,7 @@ class CordaRPCConnection private constructor(
|
|||||||
|
|
||||||
override fun forceClose() = actualConnection.forceClose()
|
override fun forceClose() = actualConnection.forceClose()
|
||||||
|
|
||||||
override fun close() {
|
override fun close() = actualConnection.close()
|
||||||
try {
|
|
||||||
actualConnection.close()
|
|
||||||
} finally {
|
|
||||||
observersPool?.apply {
|
|
||||||
shutdown()
|
|
||||||
if (!awaitTermination(@Suppress("MagicNumber")30, TimeUnit.SECONDS)) {
|
|
||||||
shutdownNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -343,36 +322,19 @@ class CordaRPCClient private constructor(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
constructor(
|
constructor(hostAndPort: NetworkHostAndPort, configuration: CordaRPCClientConfiguration = CordaRPCClientConfiguration.DEFAULT) : this(
|
||||||
hostAndPort: NetworkHostAndPort,
|
hostAndPort = hostAndPort, haAddressPool = emptyList(), configuration = configuration
|
||||||
configuration: CordaRPCClientConfiguration = CordaRPCClientConfiguration.DEFAULT
|
|
||||||
) : this(
|
|
||||||
hostAndPort = hostAndPort,
|
|
||||||
haAddressPool = emptyList(),
|
|
||||||
configuration = configuration
|
|
||||||
)
|
)
|
||||||
|
|
||||||
constructor(
|
constructor(hostAndPort: NetworkHostAndPort,
|
||||||
hostAndPort: NetworkHostAndPort,
|
configuration: CordaRPCClientConfiguration = CordaRPCClientConfiguration.DEFAULT,
|
||||||
configuration: CordaRPCClientConfiguration = CordaRPCClientConfiguration.DEFAULT,
|
classLoader: ClassLoader): this(hostAndPort, configuration, null, classLoader = classLoader)
|
||||||
classLoader: ClassLoader
|
|
||||||
): this(
|
|
||||||
hostAndPort,
|
|
||||||
configuration,
|
|
||||||
null,
|
|
||||||
classLoader = classLoader
|
|
||||||
)
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
hostAndPort: NetworkHostAndPort,
|
hostAndPort: NetworkHostAndPort,
|
||||||
sslConfiguration: ClientRpcSslOptions? = null,
|
sslConfiguration: ClientRpcSslOptions? = null,
|
||||||
classLoader: ClassLoader? = null
|
classLoader: ClassLoader? = null
|
||||||
) : this(
|
) : this(hostAndPort = hostAndPort, haAddressPool = emptyList(), sslConfiguration = sslConfiguration, classLoader = classLoader)
|
||||||
hostAndPort = hostAndPort,
|
|
||||||
haAddressPool = emptyList(),
|
|
||||||
sslConfiguration = sslConfiguration,
|
|
||||||
classLoader = classLoader
|
|
||||||
)
|
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
constructor(
|
constructor(
|
||||||
@ -380,13 +342,7 @@ class CordaRPCClient private constructor(
|
|||||||
configuration: CordaRPCClientConfiguration,
|
configuration: CordaRPCClientConfiguration,
|
||||||
sslConfiguration: ClientRpcSslOptions?,
|
sslConfiguration: ClientRpcSslOptions?,
|
||||||
classLoader: ClassLoader? = null
|
classLoader: ClassLoader? = null
|
||||||
) : this(
|
) : this(hostAndPort = hostAndPort, haAddressPool = emptyList(), configuration = configuration, sslConfiguration = sslConfiguration, classLoader = classLoader)
|
||||||
hostAndPort = hostAndPort,
|
|
||||||
haAddressPool = emptyList(),
|
|
||||||
configuration = configuration,
|
|
||||||
sslConfiguration = sslConfiguration,
|
|
||||||
classLoader = classLoader
|
|
||||||
)
|
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
constructor(
|
constructor(
|
||||||
@ -394,13 +350,7 @@ class CordaRPCClient private constructor(
|
|||||||
configuration: CordaRPCClientConfiguration = CordaRPCClientConfiguration.DEFAULT,
|
configuration: CordaRPCClientConfiguration = CordaRPCClientConfiguration.DEFAULT,
|
||||||
sslConfiguration: ClientRpcSslOptions? = null,
|
sslConfiguration: ClientRpcSslOptions? = null,
|
||||||
classLoader: ClassLoader? = null
|
classLoader: ClassLoader? = null
|
||||||
) : this(
|
) : this(hostAndPort = null, haAddressPool = haAddressPool, configuration = configuration, sslConfiguration = sslConfiguration, classLoader = classLoader)
|
||||||
hostAndPort = null,
|
|
||||||
haAddressPool = haAddressPool,
|
|
||||||
configuration = configuration,
|
|
||||||
sslConfiguration = sslConfiguration,
|
|
||||||
classLoader = classLoader
|
|
||||||
)
|
|
||||||
|
|
||||||
// Here to keep the keep ABI compatibility happy
|
// Here to keep the keep ABI compatibility happy
|
||||||
companion object {}
|
companion object {}
|
||||||
@ -412,23 +362,11 @@ class CordaRPCClient private constructor(
|
|||||||
try {
|
try {
|
||||||
val cache = Caffeine.newBuilder().maximumSize(128).build<SerializationFactoryCacheKey, SerializerFactory>().asMap()
|
val cache = Caffeine.newBuilder().maximumSize(128).build<SerializationFactoryCacheKey, SerializerFactory>().asMap()
|
||||||
|
|
||||||
// If the client has explicitly provided a classloader use this one to scan for custom serializers,
|
// If the client has explicitly provided a classloader use this one to scan for custom serializers, otherwise use the current one.
|
||||||
// otherwise use the current one.
|
|
||||||
val serializationClassLoader = this.classLoader ?: this.javaClass.classLoader
|
val serializationClassLoader = this.classLoader ?: this.javaClass.classLoader
|
||||||
val customSerializers = createInstancesOfClassesImplementing(
|
val customSerializers = createInstancesOfClassesImplementing(serializationClassLoader, SerializationCustomSerializer::class.java)
|
||||||
serializationClassLoader,
|
val serializationWhitelists = ServiceLoader.load(SerializationWhitelist::class.java, serializationClassLoader).toSet()
|
||||||
SerializationCustomSerializer::class.java
|
AMQPClientSerializationScheme.initialiseSerialization(serializationClassLoader, customSerializers, serializationWhitelists, cache)
|
||||||
)
|
|
||||||
val serializationWhitelists = ServiceLoader.load(
|
|
||||||
SerializationWhitelist::class.java,
|
|
||||||
serializationClassLoader
|
|
||||||
).toSet()
|
|
||||||
AMQPClientSerializationScheme.initialiseSerialization(
|
|
||||||
serializationClassLoader,
|
|
||||||
customSerializers,
|
|
||||||
serializationWhitelists,
|
|
||||||
cache
|
|
||||||
)
|
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: IllegalStateException) {
|
||||||
// Race e.g. two of these constructed in parallel, ignore.
|
// Race e.g. two of these constructed in parallel, ignore.
|
||||||
}
|
}
|
||||||
@ -463,11 +401,7 @@ class CordaRPCClient private constructor(
|
|||||||
* @throws RPCException if the server version is too low or if the server isn't reachable within a reasonable timeout.
|
* @throws RPCException if the server version is too low or if the server isn't reachable within a reasonable timeout.
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun start(
|
fun start(username: String, password: String, gracefulReconnect: GracefulReconnect? = null): CordaRPCConnection {
|
||||||
username: String,
|
|
||||||
password: String,
|
|
||||||
gracefulReconnect: GracefulReconnect? = null
|
|
||||||
): CordaRPCConnection {
|
|
||||||
return start(username, password, null, null, gracefulReconnect)
|
return start(username, password, null, null, gracefulReconnect)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,12 +418,7 @@ class CordaRPCClient private constructor(
|
|||||||
* @throws RPCException if the server version is too low or if the server isn't reachable within a reasonable timeout.
|
* @throws RPCException if the server version is too low or if the server isn't reachable within a reasonable timeout.
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun start(
|
fun start(username: String, password: String, targetLegalIdentity: CordaX500Name, gracefulReconnect: GracefulReconnect? = null): CordaRPCConnection {
|
||||||
username: String,
|
|
||||||
password: String,
|
|
||||||
targetLegalIdentity: CordaX500Name,
|
|
||||||
gracefulReconnect: GracefulReconnect? = null
|
|
||||||
): CordaRPCConnection {
|
|
||||||
return start(username, password, null, null, targetLegalIdentity, gracefulReconnect)
|
return start(username, password, null, null, targetLegalIdentity, gracefulReconnect)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,13 +436,7 @@ class CordaRPCClient private constructor(
|
|||||||
* @throws RPCException if the server version is too low or if the server isn't reachable within a reasonable timeout.
|
* @throws RPCException if the server version is too low or if the server isn't reachable within a reasonable timeout.
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun start(
|
fun start(username: String, password: String, externalTrace: Trace?, impersonatedActor: Actor?, gracefulReconnect: GracefulReconnect? = null): CordaRPCConnection {
|
||||||
username: String,
|
|
||||||
password: String,
|
|
||||||
externalTrace: Trace?,
|
|
||||||
impersonatedActor: Actor?,
|
|
||||||
gracefulReconnect: GracefulReconnect? = null
|
|
||||||
): CordaRPCConnection {
|
|
||||||
return start(username, password, externalTrace, impersonatedActor, null, gracefulReconnect)
|
return start(username, password, externalTrace, impersonatedActor, null, gracefulReconnect)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,14 +457,7 @@ class CordaRPCClient private constructor(
|
|||||||
* @throws RPCException if the server version is too low or if the server isn't reachable within a reasonable timeout.
|
* @throws RPCException if the server version is too low or if the server isn't reachable within a reasonable timeout.
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun start(
|
fun start(username: String, password: String, externalTrace: Trace?, impersonatedActor: Actor?, targetLegalIdentity: CordaX500Name?, gracefulReconnect: GracefulReconnect? = null): CordaRPCConnection {
|
||||||
username: String,
|
|
||||||
password: String,
|
|
||||||
externalTrace: Trace?,
|
|
||||||
impersonatedActor: Actor?,
|
|
||||||
targetLegalIdentity: CordaX500Name?,
|
|
||||||
gracefulReconnect: GracefulReconnect? = null
|
|
||||||
): CordaRPCConnection {
|
|
||||||
val addresses = if (haAddressPool.isEmpty()) {
|
val addresses = if (haAddressPool.isEmpty()) {
|
||||||
listOf(hostAndPort!!)
|
listOf(hostAndPort!!)
|
||||||
} else {
|
} else {
|
||||||
@ -549,23 +465,9 @@ class CordaRPCClient private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return if (gracefulReconnect != null) {
|
return if (gracefulReconnect != null) {
|
||||||
CordaRPCConnection.createWithGracefulReconnection(
|
CordaRPCConnection.createWithGracefulReconnection(username, password, addresses, configuration, gracefulReconnect)
|
||||||
username,
|
|
||||||
password,
|
|
||||||
addresses,
|
|
||||||
configuration,
|
|
||||||
gracefulReconnect,
|
|
||||||
sslConfiguration
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
CordaRPCConnection(getRpcClient().start(
|
CordaRPCConnection(getRpcClient().start(InternalCordaRPCOps::class.java, username, password, externalTrace, impersonatedActor, targetLegalIdentity))
|
||||||
InternalCordaRPCOps::class.java,
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
externalTrace,
|
|
||||||
impersonatedActor,
|
|
||||||
targetLegalIdentity
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,24 +32,37 @@ import java.util.concurrent.TimeUnit
|
|||||||
/**
|
/**
|
||||||
* Wrapper over [CordaRPCOps] that handles exceptions when the node or the connection to the node fail.
|
* Wrapper over [CordaRPCOps] that handles exceptions when the node or the connection to the node fail.
|
||||||
*
|
*
|
||||||
* All operations are retried on failure, except flow start operations that die before receiving a valid [FlowHandle], in which case a
|
* All operations are retried on failure, except flow start operations that die before receiving a valid [FlowHandle], in which case a [CouldNotStartFlowException] is thrown.
|
||||||
* [CouldNotStartFlowException] is thrown.
|
|
||||||
*
|
*
|
||||||
* When calling methods that return a [DataFeed] like [CordaRPCOps.vaultTrackBy], the returned [DataFeed.updates] object will no longer
|
* When calling methods that return a [DataFeed] like [CordaRPCOps.vaultTrackBy], the returned [DataFeed.updates] object will no longer
|
||||||
* be a usable [rx.Observable] but an instance of [ReconnectingObservable].
|
* be a usable [rx.Observable] but an instance of [ReconnectingObservable].
|
||||||
* The caller has to explicitly cast to [ReconnectingObservable] and call [ReconnectingObservable.subscribe]. If used as an [rx.Observable]
|
* The caller has to explicitly cast to [ReconnectingObservable] and call [ReconnectingObservable.subscribe]. If used as an [rx.Observable] it will just fail.
|
||||||
* it will just fail.
|
|
||||||
* The returned [DataFeed.snapshot] is the snapshot as it was when the feed was first retrieved.
|
* The returned [DataFeed.snapshot] is the snapshot as it was when the feed was first retrieved.
|
||||||
*
|
*
|
||||||
* Note: There is no guarantee that observations will not be lost.
|
* Note: There is no guarantee that observations will not be lost.
|
||||||
*
|
*
|
||||||
* *This class is not a stable API. Any project that wants to use it, must copy and paste it.*
|
* *This class is not a stable API. Any project that wants to use it, must copy and paste it.*
|
||||||
*/
|
*/
|
||||||
// TODO The executor service is not needed. All we need is a single thread that deals with reconnecting and onto which
|
// TODO The executor service is not needed. All we need is a single thread that deals with reconnecting and onto which ReconnectingObservables
|
||||||
// ReconnectingObservables and other things can attach themselves as listeners for reconnect events.
|
// and other things can attach themselves as listeners for reconnect events.
|
||||||
class ReconnectingCordaRPCOps private constructor(
|
class ReconnectingCordaRPCOps private constructor(
|
||||||
val reconnectingRPCConnection: ReconnectingRPCConnection
|
val reconnectingRPCConnection: ReconnectingRPCConnection,
|
||||||
) : InternalCordaRPCOps by proxy(reconnectingRPCConnection) {
|
private val observersPool: ExecutorService,
|
||||||
|
private val userPool: Boolean
|
||||||
|
) : AutoCloseable, InternalCordaRPCOps by proxy(reconnectingRPCConnection, observersPool) {
|
||||||
|
// Constructors that mirror CordaRPCClient.
|
||||||
|
constructor(
|
||||||
|
nodeHostAndPort: NetworkHostAndPort,
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
rpcConfiguration: CordaRPCClientConfiguration,
|
||||||
|
sslConfiguration: ClientRpcSslOptions? = null,
|
||||||
|
classLoader: ClassLoader? = null,
|
||||||
|
observersPool: ExecutorService? = null
|
||||||
|
) : this(
|
||||||
|
ReconnectingRPCConnection(listOf(nodeHostAndPort), username, password, rpcConfiguration, sslConfiguration, classLoader),
|
||||||
|
observersPool ?: Executors.newCachedThreadPool(),
|
||||||
|
observersPool != null)
|
||||||
constructor(
|
constructor(
|
||||||
nodeHostAndPorts: List<NetworkHostAndPort>,
|
nodeHostAndPorts: List<NetworkHostAndPort>,
|
||||||
username: String,
|
username: String,
|
||||||
@ -58,23 +71,18 @@ class ReconnectingCordaRPCOps private constructor(
|
|||||||
gracefulReconnect: GracefulReconnect? = null,
|
gracefulReconnect: GracefulReconnect? = null,
|
||||||
sslConfiguration: ClientRpcSslOptions? = null,
|
sslConfiguration: ClientRpcSslOptions? = null,
|
||||||
classLoader: ClassLoader? = null,
|
classLoader: ClassLoader? = null,
|
||||||
observersPool: ExecutorService
|
observersPool: ExecutorService? = null
|
||||||
) : this(ReconnectingRPCConnection(
|
) : this(
|
||||||
nodeHostAndPorts,
|
ReconnectingRPCConnection(nodeHostAndPorts, username, password, rpcConfiguration, sslConfiguration, classLoader, gracefulReconnect),
|
||||||
username,
|
observersPool ?: Executors.newCachedThreadPool(),
|
||||||
password,
|
observersPool != null)
|
||||||
rpcConfiguration,
|
|
||||||
sslConfiguration,
|
|
||||||
classLoader,
|
|
||||||
gracefulReconnect,
|
|
||||||
observersPool))
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private val log = contextLogger()
|
private val log = contextLogger()
|
||||||
private fun proxy(reconnectingRPCConnection: ReconnectingRPCConnection): InternalCordaRPCOps {
|
private fun proxy(reconnectingRPCConnection: ReconnectingRPCConnection, observersPool: ExecutorService): InternalCordaRPCOps {
|
||||||
return Proxy.newProxyInstance(
|
return Proxy.newProxyInstance(
|
||||||
this::class.java.classLoader,
|
this::class.java.classLoader,
|
||||||
arrayOf(InternalCordaRPCOps::class.java),
|
arrayOf(InternalCordaRPCOps::class.java),
|
||||||
ErrorInterceptingHandler(reconnectingRPCConnection)) as InternalCordaRPCOps
|
ErrorInterceptingHandler(reconnectingRPCConnection, observersPool)) as InternalCordaRPCOps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private val retryFlowsPool = Executors.newScheduledThreadPool(1)
|
private val retryFlowsPool = Executors.newScheduledThreadPool(1)
|
||||||
@ -117,8 +125,7 @@ class ReconnectingCordaRPCOps private constructor(
|
|||||||
val rpcConfiguration: CordaRPCClientConfiguration,
|
val rpcConfiguration: CordaRPCClientConfiguration,
|
||||||
val sslConfiguration: ClientRpcSslOptions? = null,
|
val sslConfiguration: ClientRpcSslOptions? = null,
|
||||||
val classLoader: ClassLoader?,
|
val classLoader: ClassLoader?,
|
||||||
val gracefulReconnect: GracefulReconnect? = null,
|
val gracefulReconnect: GracefulReconnect? = null
|
||||||
val observersPool: ExecutorService
|
|
||||||
) : RPCConnection<CordaRPCOps> {
|
) : RPCConnection<CordaRPCOps> {
|
||||||
private var currentRPCConnection: CordaRPCConnection? = null
|
private var currentRPCConnection: CordaRPCConnection? = null
|
||||||
enum class CurrentState {
|
enum class CurrentState {
|
||||||
@ -171,18 +178,12 @@ class ReconnectingCordaRPCOps private constructor(
|
|||||||
return currentRPCConnection!!
|
return currentRPCConnection!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private tailrec fun establishConnectionWithRetry(
|
private tailrec fun establishConnectionWithRetry(retryInterval: Duration = 1.seconds, roundRobinIndex: Int = 0): CordaRPCConnection {
|
||||||
retryInterval: Duration = 1.seconds,
|
|
||||||
roundRobinIndex: Int = 0
|
|
||||||
): CordaRPCConnection {
|
|
||||||
val attemptedAddress = nodeHostAndPorts[roundRobinIndex]
|
val attemptedAddress = nodeHostAndPorts[roundRobinIndex]
|
||||||
log.info("Connecting to: $attemptedAddress")
|
log.info("Connecting to: $attemptedAddress")
|
||||||
try {
|
try {
|
||||||
return CordaRPCClient(
|
return CordaRPCClient(
|
||||||
attemptedAddress,
|
attemptedAddress, rpcConfiguration.copy(connectionMaxRetryInterval = retryInterval, maxReconnectAttempts = 1), sslConfiguration, classLoader
|
||||||
rpcConfiguration.copy(connectionMaxRetryInterval = retryInterval, maxReconnectAttempts = 1),
|
|
||||||
sslConfiguration,
|
|
||||||
classLoader
|
|
||||||
).start(username, password).also {
|
).start(username, password).also {
|
||||||
// Check connection is truly operational before returning it.
|
// Check connection is truly operational before returning it.
|
||||||
require(it.proxy.nodeInfo().legalIdentitiesAndCerts.isNotEmpty()) {
|
require(it.proxy.nodeInfo().legalIdentitiesAndCerts.isNotEmpty()) {
|
||||||
@ -239,7 +240,7 @@ class ReconnectingCordaRPCOps private constructor(
|
|||||||
currentRPCConnection?.close()
|
currentRPCConnection?.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private class ErrorInterceptingHandler(val reconnectingRPCConnection: ReconnectingRPCConnection) : InvocationHandler {
|
private class ErrorInterceptingHandler(val reconnectingRPCConnection: ReconnectingRPCConnection, val observersPool: ExecutorService) : InvocationHandler {
|
||||||
private fun Method.isStartFlow() = name.startsWith("startFlow") || name.startsWith("startTrackedFlow")
|
private fun Method.isStartFlow() = name.startsWith("startFlow") || name.startsWith("startTrackedFlow")
|
||||||
|
|
||||||
private fun checkIfIsStartFlow(method: Method, e: InvocationTargetException) {
|
private fun checkIfIsStartFlow(method: Method, e: InvocationTargetException) {
|
||||||
@ -289,7 +290,7 @@ class ReconnectingCordaRPCOps private constructor(
|
|||||||
DataFeed::class.java -> {
|
DataFeed::class.java -> {
|
||||||
// Intercept the data feed methods and return a ReconnectingObservable instance
|
// Intercept the data feed methods and return a ReconnectingObservable instance
|
||||||
val initialFeed: DataFeed<Any, Any?> = uncheckedCast(doInvoke(method, args))
|
val initialFeed: DataFeed<Any, Any?> = uncheckedCast(doInvoke(method, args))
|
||||||
val observable = ReconnectingObservable(reconnectingRPCConnection, initialFeed) {
|
val observable = ReconnectingObservable(reconnectingRPCConnection, observersPool, initialFeed) {
|
||||||
// This handles reconnecting and creates new feeds.
|
// This handles reconnecting and creates new feeds.
|
||||||
uncheckedCast(this.invoke(reconnectingRPCConnection.proxy, method, args))
|
uncheckedCast(this.invoke(reconnectingRPCConnection.proxy, method, args))
|
||||||
}
|
}
|
||||||
@ -301,7 +302,8 @@ class ReconnectingCordaRPCOps private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun close() {
|
override fun close() {
|
||||||
|
if (!userPool) observersPool.shutdown()
|
||||||
retryFlowsPool.shutdown()
|
retryFlowsPool.shutdown()
|
||||||
reconnectingRPCConnection.forceClose()
|
reconnectingRPCConnection.forceClose()
|
||||||
}
|
}
|
||||||
|
@ -4,18 +4,21 @@ import net.corda.core.messaging.DataFeed
|
|||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Subscriber
|
import rx.Subscriber
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
|
import java.util.concurrent.ExecutorService
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
|
||||||
class ReconnectingObservable<T> private constructor(subscriber: ReconnectingSubscriber<T>) : Observable<T>(subscriber) {
|
class ReconnectingObservable<T> private constructor(subscriber: ReconnectingSubscriber<T>) : Observable<T>(subscriber) {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
reconnectingRPCConnection: ReconnectingCordaRPCOps.ReconnectingRPCConnection,
|
reconnectingRPCConnection: ReconnectingCordaRPCOps.ReconnectingRPCConnection,
|
||||||
|
executor: ExecutorService,
|
||||||
initialDataFeed: DataFeed<*, T>,
|
initialDataFeed: DataFeed<*, T>,
|
||||||
createDataFeed: () -> DataFeed<*, T>
|
createDataFeed: () -> DataFeed<*, T>
|
||||||
) : this(ReconnectingSubscriber(reconnectingRPCConnection, initialDataFeed, createDataFeed))
|
) : this(ReconnectingSubscriber(reconnectingRPCConnection, executor, initialDataFeed, createDataFeed))
|
||||||
|
|
||||||
private class ReconnectingSubscriber<T>(
|
private class ReconnectingSubscriber<T>(
|
||||||
private val reconnectingRPCConnection: ReconnectingCordaRPCOps.ReconnectingRPCConnection,
|
private val reconnectingRPCConnection: ReconnectingCordaRPCOps.ReconnectingRPCConnection,
|
||||||
|
private val executor: ExecutorService,
|
||||||
private val initialDataFeed: DataFeed<*, T>,
|
private val initialDataFeed: DataFeed<*, T>,
|
||||||
private val createDataFeed: () -> DataFeed<*, T>
|
private val createDataFeed: () -> DataFeed<*, T>
|
||||||
) : OnSubscribe<T>, Subscription {
|
) : OnSubscribe<T>, Subscription {
|
||||||
@ -56,7 +59,7 @@ class ReconnectingObservable<T> private constructor(subscriber: ReconnectingSubs
|
|||||||
|
|
||||||
private fun scheduleResubscribe(error: Throwable) {
|
private fun scheduleResubscribe(error: Throwable) {
|
||||||
if (unsubscribed) return
|
if (unsubscribed) return
|
||||||
reconnectingRPCConnection.observersPool.execute {
|
executor.execute {
|
||||||
if (unsubscribed) return@execute
|
if (unsubscribed) return@execute
|
||||||
reconnectingRPCConnection.reconnectOnError(error)
|
reconnectingRPCConnection.reconnectOnError(error)
|
||||||
val newDataFeed = createDataFeed()
|
val newDataFeed = createDataFeed()
|
||||||
|
@ -366,14 +366,7 @@ class Verifier(val ltx: LedgerTransaction, private val transactionClassLoader: C
|
|||||||
|
|
||||||
val contractInstances: List<Contract> = contractClasses.map { (contractClassName, contractClass) ->
|
val contractInstances: List<Contract> = contractClasses.map { (contractClassName, contractClass) ->
|
||||||
try {
|
try {
|
||||||
/**
|
contractClass.getDeclaredConstructor().newInstance()
|
||||||
* This function must execute with the DJVM's sandbox, which does not
|
|
||||||
* permit user code to access [java.lang.reflect.Constructor] objects.
|
|
||||||
*
|
|
||||||
* [Class.newInstance] is deprecated as of Java 9.
|
|
||||||
*/
|
|
||||||
@Suppress("deprecation")
|
|
||||||
contractClass.newInstance()
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw TransactionVerificationException.ContractCreationError(ltx.id, contractClassName, e)
|
throw TransactionVerificationException.ContractCreationError(ltx.id, contractClassName, e)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import net.corda.core.contracts.ContractState
|
|||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.contracts.UniqueIdentifier
|
import net.corda.core.contracts.UniqueIdentifier
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import net.corda.core.node.services.Vault
|
import net.corda.core.node.services.Vault
|
||||||
import net.corda.core.schemas.StatePersistable
|
import net.corda.core.schemas.StatePersistable
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
@ -83,7 +82,6 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
|||||||
open val participants: List<AbstractParty>? = null
|
open val participants: List<AbstractParty>? = null
|
||||||
abstract val contractStateTypes: Set<Class<out ContractState>>?
|
abstract val contractStateTypes: Set<Class<out ContractState>>?
|
||||||
open val externalIds: List<UUID> = emptyList()
|
open val externalIds: List<UUID> = emptyList()
|
||||||
open val exactParticipants: List<AbstractParty>? = null
|
|
||||||
override fun visit(parser: IQueryCriteriaParser): Collection<Predicate> {
|
override fun visit(parser: IQueryCriteriaParser): Collection<Predicate> {
|
||||||
return parser.parseCriteria(this)
|
return parser.parseCriteria(this)
|
||||||
}
|
}
|
||||||
@ -103,23 +101,8 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
|||||||
override val constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(),
|
override val constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(),
|
||||||
override val constraints: Set<Vault.ConstraintInfo> = emptySet(),
|
override val constraints: Set<Vault.ConstraintInfo> = emptySet(),
|
||||||
override val participants: List<AbstractParty>? = null,
|
override val participants: List<AbstractParty>? = null,
|
||||||
override val externalIds: List<UUID> = emptyList(),
|
override val externalIds: List<UUID> = emptyList()
|
||||||
override val exactParticipants: List<AbstractParty>? = null
|
|
||||||
) : CommonQueryCriteria() {
|
) : CommonQueryCriteria() {
|
||||||
@DeprecatedConstructorForDeserialization(version = 7)
|
|
||||||
constructor(
|
|
||||||
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
|
||||||
contractStateTypes: Set<Class<out ContractState>>? = null,
|
|
||||||
stateRefs: List<StateRef>? = null,
|
|
||||||
notary: List<AbstractParty>? = null,
|
|
||||||
softLockingCondition: SoftLockingCondition? = null,
|
|
||||||
timeCondition: TimeCondition? = null,
|
|
||||||
relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL,
|
|
||||||
constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(),
|
|
||||||
constraints: Set<Vault.ConstraintInfo> = emptySet(),
|
|
||||||
participants: List<AbstractParty>? = null,
|
|
||||||
externalIds: List<UUID> = emptyList()
|
|
||||||
) : this(status, contractStateTypes, stateRefs, notary, softLockingCondition, timeCondition, relevancyStatus, constraintTypes, constraints, participants, externalIds, null)
|
|
||||||
// V4 constructors.
|
// V4 constructors.
|
||||||
@DeprecatedConstructorForDeserialization(version = 7)
|
@DeprecatedConstructorForDeserialization(version = 7)
|
||||||
constructor(
|
constructor(
|
||||||
@ -179,36 +162,6 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
|||||||
fun withConstraints(constraints: Set<Vault.ConstraintInfo>): VaultQueryCriteria = copy(constraints = constraints)
|
fun withConstraints(constraints: Set<Vault.ConstraintInfo>): VaultQueryCriteria = copy(constraints = constraints)
|
||||||
fun withParticipants(participants: List<AbstractParty>): VaultQueryCriteria = copy(participants = participants)
|
fun withParticipants(participants: List<AbstractParty>): VaultQueryCriteria = copy(participants = participants)
|
||||||
fun withExternalIds(externalIds: List<UUID>): VaultQueryCriteria = copy(externalIds = externalIds)
|
fun withExternalIds(externalIds: List<UUID>): VaultQueryCriteria = copy(externalIds = externalIds)
|
||||||
fun withExactParticipants(exactParticipants: List<AbstractParty>): VaultQueryCriteria = copy(exactParticipants = exactParticipants)
|
|
||||||
|
|
||||||
fun copy(
|
|
||||||
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
|
||||||
contractStateTypes: Set<Class<out ContractState>>? = null,
|
|
||||||
stateRefs: List<StateRef>? = null,
|
|
||||||
notary: List<AbstractParty>? = null,
|
|
||||||
softLockingCondition: SoftLockingCondition? = null,
|
|
||||||
timeCondition: TimeCondition? = null,
|
|
||||||
relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL,
|
|
||||||
constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(),
|
|
||||||
constraints: Set<Vault.ConstraintInfo> = emptySet(),
|
|
||||||
participants: List<AbstractParty>? = null,
|
|
||||||
externalIds: List<UUID> = emptyList()
|
|
||||||
): VaultQueryCriteria {
|
|
||||||
return VaultQueryCriteria(
|
|
||||||
status,
|
|
||||||
contractStateTypes,
|
|
||||||
stateRefs,
|
|
||||||
notary,
|
|
||||||
softLockingCondition,
|
|
||||||
timeCondition,
|
|
||||||
relevancyStatus,
|
|
||||||
constraintTypes,
|
|
||||||
constraints,
|
|
||||||
participants,
|
|
||||||
externalIds,
|
|
||||||
exactParticipants
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copy(
|
fun copy(
|
||||||
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||||
@ -265,24 +218,13 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
|||||||
* LinearStateQueryCriteria: provides query by attributes defined in [VaultSchema.VaultLinearState]
|
* LinearStateQueryCriteria: provides query by attributes defined in [VaultSchema.VaultLinearState]
|
||||||
*/
|
*/
|
||||||
data class LinearStateQueryCriteria(
|
data class LinearStateQueryCriteria(
|
||||||
override val participants: List<AbstractParty>? = null,
|
override val participants: List<AbstractParty>?,
|
||||||
val uuid: List<UUID>? = null,
|
val uuid: List<UUID>? = null,
|
||||||
val externalId: List<String>? = null,
|
val externalId: List<String>? = null,
|
||||||
override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||||
override val contractStateTypes: Set<Class<out ContractState>>? = null,
|
override val contractStateTypes: Set<Class<out ContractState>>? = null,
|
||||||
override val relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL,
|
override val relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL
|
||||||
override val exactParticipants: List<AbstractParty>?
|
|
||||||
) : CommonQueryCriteria() {
|
) : CommonQueryCriteria() {
|
||||||
// V4 c'tor
|
|
||||||
@DeprecatedConstructorForDeserialization(version = 4)
|
|
||||||
constructor(
|
|
||||||
participants: List<AbstractParty>? = null,
|
|
||||||
uuid: List<UUID>? = null,
|
|
||||||
externalId: List<String>? = null,
|
|
||||||
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
|
||||||
contractStateTypes: Set<Class<out ContractState>>? = null,
|
|
||||||
relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL
|
|
||||||
) : this(participants, uuid, externalId, status, contractStateTypes, relevancyStatus, null)
|
|
||||||
// V3 c'tor
|
// V3 c'tor
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
@DeprecatedConstructorForDeserialization(version = 2)
|
@DeprecatedConstructorForDeserialization(version = 2)
|
||||||
@ -323,8 +265,6 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
|||||||
fun withStatus(status: Vault.StateStatus): LinearStateQueryCriteria = copy(status = status)
|
fun withStatus(status: Vault.StateStatus): LinearStateQueryCriteria = copy(status = status)
|
||||||
fun withContractStateTypes(contractStateTypes: Set<Class<out ContractState>>): LinearStateQueryCriteria = copy(contractStateTypes = contractStateTypes)
|
fun withContractStateTypes(contractStateTypes: Set<Class<out ContractState>>): LinearStateQueryCriteria = copy(contractStateTypes = contractStateTypes)
|
||||||
fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): LinearStateQueryCriteria = copy(relevancyStatus = relevancyStatus)
|
fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): LinearStateQueryCriteria = copy(relevancyStatus = relevancyStatus)
|
||||||
fun withExactParticipants(exactParticipants: List<AbstractParty>): LinearStateQueryCriteria =
|
|
||||||
copy(exactParticipants = exactParticipants)
|
|
||||||
|
|
||||||
fun copy(
|
fun copy(
|
||||||
participants: List<AbstractParty>? = this.participants,
|
participants: List<AbstractParty>? = this.participants,
|
||||||
@ -332,23 +272,6 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
|||||||
externalId: List<String>? = this.externalId,
|
externalId: List<String>? = this.externalId,
|
||||||
status: Vault.StateStatus = this.status,
|
status: Vault.StateStatus = this.status,
|
||||||
contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes
|
contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes
|
||||||
): LinearStateQueryCriteria {
|
|
||||||
return LinearStateQueryCriteria(
|
|
||||||
participants,
|
|
||||||
uuid,
|
|
||||||
externalId,
|
|
||||||
status,
|
|
||||||
contractStateTypes
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copy(
|
|
||||||
participants: List<AbstractParty>? = this.participants,
|
|
||||||
uuid: List<UUID>? = this.uuid,
|
|
||||||
externalId: List<String>? = this.externalId,
|
|
||||||
status: Vault.StateStatus = this.status,
|
|
||||||
contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes,
|
|
||||||
relevancyStatus: Vault.RelevancyStatus = this.relevancyStatus
|
|
||||||
): LinearStateQueryCriteria {
|
): LinearStateQueryCriteria {
|
||||||
return LinearStateQueryCriteria(
|
return LinearStateQueryCriteria(
|
||||||
participants,
|
participants,
|
||||||
@ -394,21 +317,8 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
|||||||
val issuerRef: List<OpaqueBytes>? = null,
|
val issuerRef: List<OpaqueBytes>? = null,
|
||||||
override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||||
override val contractStateTypes: Set<Class<out ContractState>>? = null,
|
override val contractStateTypes: Set<Class<out ContractState>>? = null,
|
||||||
override val relevancyStatus: Vault.RelevancyStatus,
|
override val relevancyStatus: Vault.RelevancyStatus
|
||||||
override val exactParticipants: List<AbstractParty>? = null
|
|
||||||
) : CommonQueryCriteria() {
|
) : CommonQueryCriteria() {
|
||||||
// V4 c'tor
|
|
||||||
@DeprecatedConstructorForDeserialization(version = 1)
|
|
||||||
constructor(
|
|
||||||
participants: List<AbstractParty>? = null,
|
|
||||||
owner: List<AbstractParty>? = null,
|
|
||||||
quantity: ColumnPredicate<Long>? = null,
|
|
||||||
issuer: List<AbstractParty>? = null,
|
|
||||||
issuerRef: List<OpaqueBytes>? = null,
|
|
||||||
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
|
||||||
contractStateTypes: Set<Class<out ContractState>>? = null,
|
|
||||||
relevancyStatus: Vault.RelevancyStatus
|
|
||||||
) : this(participants, owner, quantity, issuer, issuerRef, status, contractStateTypes, relevancyStatus, null)
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
@DeprecatedConstructorForDeserialization(version = 1)
|
@DeprecatedConstructorForDeserialization(version = 1)
|
||||||
constructor(
|
constructor(
|
||||||
@ -434,30 +344,6 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
|||||||
fun withStatus(status: Vault.StateStatus): FungibleAssetQueryCriteria = copy(status = status)
|
fun withStatus(status: Vault.StateStatus): FungibleAssetQueryCriteria = copy(status = status)
|
||||||
fun withContractStateTypes(contractStateTypes: Set<Class<out ContractState>>): FungibleAssetQueryCriteria = copy(contractStateTypes = contractStateTypes)
|
fun withContractStateTypes(contractStateTypes: Set<Class<out ContractState>>): FungibleAssetQueryCriteria = copy(contractStateTypes = contractStateTypes)
|
||||||
fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): FungibleAssetQueryCriteria = copy(relevancyStatus = relevancyStatus)
|
fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): FungibleAssetQueryCriteria = copy(relevancyStatus = relevancyStatus)
|
||||||
fun withExactParticipants(exactParticipants: List<AbstractParty>): FungibleAssetQueryCriteria
|
|
||||||
= copy(exactParticipants = exactParticipants)
|
|
||||||
|
|
||||||
fun copy(
|
|
||||||
participants: List<AbstractParty>? = this.participants,
|
|
||||||
owner: List<AbstractParty>? = this.owner,
|
|
||||||
quantity: ColumnPredicate<Long>? = this.quantity,
|
|
||||||
issuer: List<AbstractParty>? = this.issuer,
|
|
||||||
issuerRef: List<OpaqueBytes>? = this.issuerRef,
|
|
||||||
status: Vault.StateStatus = this.status,
|
|
||||||
contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes,
|
|
||||||
relevancyStatus: Vault.RelevancyStatus = this.relevancyStatus
|
|
||||||
): FungibleAssetQueryCriteria {
|
|
||||||
return FungibleAssetQueryCriteria(
|
|
||||||
participants,
|
|
||||||
owner,
|
|
||||||
quantity,
|
|
||||||
issuer,
|
|
||||||
issuerRef,
|
|
||||||
status,
|
|
||||||
contractStateTypes,
|
|
||||||
relevancyStatus
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copy(
|
fun copy(
|
||||||
participants: List<AbstractParty>? = this.participants,
|
participants: List<AbstractParty>? = this.participants,
|
||||||
|
File diff suppressed because one or more lines are too long
@ -86,8 +86,7 @@ There are four implementations of this interface which can be chained together t
|
|||||||
|
|
||||||
1. ``VaultQueryCriteria`` provides filterable criteria on attributes within the Vault states table: status (UNCONSUMED,
|
1. ``VaultQueryCriteria`` provides filterable criteria on attributes within the Vault states table: status (UNCONSUMED,
|
||||||
CONSUMED), state reference(s), contract state type(s), notaries, soft locked states, timestamps (RECORDED, CONSUMED),
|
CONSUMED), state reference(s), contract state type(s), notaries, soft locked states, timestamps (RECORDED, CONSUMED),
|
||||||
state constraints (see :ref:`Constraint Types <implicit_constraint_types>`), relevancy (ALL, RELEVANT, NON_RELEVANT),
|
state constraints (see :ref:`Constraint Types <implicit_constraint_types>`), relevancy (ALL, RELEVANT, NON_RELEVANT).
|
||||||
participants (exact or any match).
|
|
||||||
|
|
||||||
.. note:: Sensible defaults are defined for frequently used attributes (status = UNCONSUMED, always include soft
|
.. note:: Sensible defaults are defined for frequently used attributes (status = UNCONSUMED, always include soft
|
||||||
locked states).
|
locked states).
|
||||||
@ -95,7 +94,7 @@ There are four implementations of this interface which can be chained together t
|
|||||||
2. ``FungibleAssetQueryCriteria`` provides filterable criteria on attributes defined in the Corda Core
|
2. ``FungibleAssetQueryCriteria`` provides filterable criteria on attributes defined in the Corda Core
|
||||||
``FungibleAsset`` contract state interface, used to represent assets that are fungible, countable and issued by a
|
``FungibleAsset`` contract state interface, used to represent assets that are fungible, countable and issued by a
|
||||||
specific party (eg. ``Cash.State`` and ``CommodityContract.State`` in the Corda finance module). Filterable
|
specific party (eg. ``Cash.State`` and ``CommodityContract.State`` in the Corda finance module). Filterable
|
||||||
attributes include: participants (exact or any match), owner(s), quantity, issuer party(s) and issuer reference(s).
|
attributes include: participants(s), owner(s), quantity, issuer party(s) and issuer reference(s).
|
||||||
|
|
||||||
.. note:: All contract states that extend the ``FungibleAsset`` now automatically persist that interfaces common
|
.. note:: All contract states that extend the ``FungibleAsset`` now automatically persist that interfaces common
|
||||||
state attributes to the **vault_fungible_states** table.
|
state attributes to the **vault_fungible_states** table.
|
||||||
@ -103,7 +102,7 @@ There are four implementations of this interface which can be chained together t
|
|||||||
3. ``LinearStateQueryCriteria`` provides filterable criteria on attributes defined in the Corda Core ``LinearState``
|
3. ``LinearStateQueryCriteria`` provides filterable criteria on attributes defined in the Corda Core ``LinearState``
|
||||||
and ``DealState`` contract state interfaces, used to represent entities that continuously supersede themselves, all
|
and ``DealState`` contract state interfaces, used to represent entities that continuously supersede themselves, all
|
||||||
of which share the same ``linearId`` (e.g. trade entity states such as the ``IRSState`` defined in the SIMM
|
of which share the same ``linearId`` (e.g. trade entity states such as the ``IRSState`` defined in the SIMM
|
||||||
valuation demo). Filterable attributes include: participants (exact or any match), linearId(s), uuid(s), and externalId(s).
|
valuation demo). Filterable attributes include: participant(s), linearId(s), uuid(s), and externalId(s).
|
||||||
|
|
||||||
.. note:: All contract states that extend ``LinearState`` or ``DealState`` now automatically persist those
|
.. note:: All contract states that extend ``LinearState`` or ``DealState`` now automatically persist those
|
||||||
interfaces common state attributes to the **vault_linear_states** table.
|
interfaces common state attributes to the **vault_linear_states** table.
|
||||||
@ -293,7 +292,7 @@ Query for unconsumed states for a given notary:
|
|||||||
:end-before: DOCEND VaultQueryExample4
|
:end-before: DOCEND VaultQueryExample4
|
||||||
:dedent: 12
|
:dedent: 12
|
||||||
|
|
||||||
Query for unconsumed states for a given set of participants (matches any state that contains at least one of the specified participants):
|
Query for unconsumed states for a given set of participants:
|
||||||
|
|
||||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
||||||
:language: kotlin
|
:language: kotlin
|
||||||
@ -301,14 +300,6 @@ Query for unconsumed states for a given set of participants (matches any state t
|
|||||||
:end-before: DOCEND VaultQueryExample5
|
:end-before: DOCEND VaultQueryExample5
|
||||||
:dedent: 12
|
:dedent: 12
|
||||||
|
|
||||||
Query for unconsumed states for a given set of participants (exactly matches only states that contain all specified participants):
|
|
||||||
|
|
||||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
|
||||||
:language: kotlin
|
|
||||||
:start-after: DOCSTART VaultQueryExample51
|
|
||||||
:end-before: DOCEND VaultQueryExample51
|
|
||||||
:dedent: 12
|
|
||||||
|
|
||||||
Query for unconsumed states recorded between two time intervals:
|
Query for unconsumed states recorded between two time intervals:
|
||||||
|
|
||||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
||||||
@ -373,7 +364,7 @@ Query for unconsumed deal states with deals references:
|
|||||||
:end-before: DOCEND VaultQueryExample10
|
:end-before: DOCEND VaultQueryExample10
|
||||||
:dedent: 12
|
:dedent: 12
|
||||||
|
|
||||||
Query for unconsumed deal states with deals parties (any match):
|
Query for unconsumed deal states with deals parties:
|
||||||
|
|
||||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
||||||
:language: kotlin
|
:language: kotlin
|
||||||
@ -381,14 +372,6 @@ Query for unconsumed deal states with deals parties (any match):
|
|||||||
:end-before: DOCEND VaultQueryExample11
|
:end-before: DOCEND VaultQueryExample11
|
||||||
:dedent: 12
|
:dedent: 12
|
||||||
|
|
||||||
Query for unconsumed deal states with deals parties (exact match):
|
|
||||||
|
|
||||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
|
||||||
:language: kotlin
|
|
||||||
:start-after: DOCSTART VaultQueryExample52
|
|
||||||
:end-before: DOCEND VaultQueryExample52
|
|
||||||
:dedent: 12
|
|
||||||
|
|
||||||
Query for only relevant linear states in the vault:
|
Query for only relevant linear states in the vault:
|
||||||
|
|
||||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
||||||
|
@ -9,8 +9,6 @@ Unreleased
|
|||||||
|
|
||||||
* Moved and renamed the testing web server to the ``testing`` subproject. Also renamed the published artifact to ``corda-testserver.jar``.
|
* Moved and renamed the testing web server to the ``testing`` subproject. Also renamed the published artifact to ``corda-testserver.jar``.
|
||||||
|
|
||||||
* New Vault Query criteria to specify exact matches for specified participants.
|
|
||||||
|
|
||||||
* Support for Java 11 (compatibility mode). Please read https://github.com/corda/corda/pull/5356.
|
* Support for Java 11 (compatibility mode). Please read https://github.com/corda/corda/pull/5356.
|
||||||
|
|
||||||
* Updating FinalityFlow with functionality to indicate the appropriate StatesToRecord. This allows the initiating party to record states
|
* Updating FinalityFlow with functionality to indicate the appropriate StatesToRecord. This allows the initiating party to record states
|
||||||
|
@ -5,9 +5,8 @@ This document explains the coding style used in the Corda repository. You will b
|
|||||||
recommendations when submitting patches for review. Please take the time to read them and internalise them, to save
|
recommendations when submitting patches for review. Please take the time to read them and internalise them, to save
|
||||||
time during code review.
|
time during code review.
|
||||||
|
|
||||||
What follows are mostly *recommendations* and not *rules*. They are in places intentionally vague, so use your good judgement
|
What follows are *recommendations* and not *rules*. They are in places intentionally vague, so use your good judgement
|
||||||
when interpreting them. The rules that are currently being enforced via the Detekt PR gateway can be found `here
|
when interpreting them.
|
||||||
<https://github.com/corda/corda/blob/release/os/4.3/detekt-config.yml>`_.
|
|
||||||
|
|
||||||
1. General style
|
1. General style
|
||||||
################
|
################
|
||||||
@ -36,9 +35,10 @@ that doesn't mean it's always better. In particular:
|
|||||||
1.1 Line Length and Spacing
|
1.1 Line Length and Spacing
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
We aim for line widths of no more than 140 characters. That is wide enough to avoid lots of pointless wrapping but
|
We aim for line widths of no more than 120 characters. That is wide enough to avoid lots of pointless wrapping but
|
||||||
narrow enough that with a widescreen monitor and a 12 point fixed width font (like Menlo) you can fit two files
|
narrow enough that with a widescreen monitor and a 12 point fixed width font (like Menlo) you can fit two files
|
||||||
next to each other. This is a rule that we enforce.
|
next to each other. This is not a rigidly enforced rule and if wrapping a line would be excessively awkward, let it
|
||||||
|
overflow. Overflow of a few characters here and there isn't a big deal: the goal is general convenience.
|
||||||
|
|
||||||
Where the number of parameters in a function, class, etc. causes an overflow past the end of the first line, they should
|
Where the number of parameters in a function, class, etc. causes an overflow past the end of the first line, they should
|
||||||
be structured one parameter per line.
|
be structured one parameter per line.
|
||||||
|
@ -133,8 +133,7 @@ class RpcReconnectTests {
|
|||||||
}
|
}
|
||||||
val reconnect = GracefulReconnect(onDisconnect = { numDisconnects++ }, onReconnect = onReconnect)
|
val reconnect = GracefulReconnect(onDisconnect = { numDisconnects++ }, onReconnect = onReconnect)
|
||||||
val client = CordaRPCClient(addressesForRpc)
|
val client = CordaRPCClient(addressesForRpc)
|
||||||
val bankAReconnectingRPCConnection = client.start(demoUser.username, demoUser.password, gracefulReconnect = reconnect)
|
val bankAReconnectingRpc = client.start(demoUser.username, demoUser.password, gracefulReconnect = reconnect).proxy as ReconnectingCordaRPCOps
|
||||||
val bankAReconnectingRpc = bankAReconnectingRPCConnection.proxy as ReconnectingCordaRPCOps
|
|
||||||
// DOCEND rpcReconnectingRPC
|
// DOCEND rpcReconnectingRPC
|
||||||
|
|
||||||
// Observe the vault and collect the observations.
|
// Observe the vault and collect the observations.
|
||||||
@ -331,7 +330,7 @@ class RpcReconnectTests {
|
|||||||
// Stop the observers.
|
// Stop the observers.
|
||||||
vaultSubscription.unsubscribe()
|
vaultSubscription.unsubscribe()
|
||||||
stateMachineSubscription.unsubscribe()
|
stateMachineSubscription.unsubscribe()
|
||||||
bankAReconnectingRPCConnection.close()
|
bankAReconnectingRpc.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy.close()
|
proxy.close()
|
||||||
|
@ -471,12 +471,8 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
|||||||
predicateSet.add(criteriaBuilder.and(vaultFungibleStatesRoot.get<ByteArray>("issuerRef").`in`(issuerRefs)))
|
predicateSet.add(criteriaBuilder.and(vaultFungibleStatesRoot.get<ByteArray>("issuerRef").`in`(issuerRefs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (criteria.participants != null && criteria.exactParticipants != null)
|
|
||||||
throw VaultQueryException("Cannot specify both participants (${criteria.participants}) and exactParticipants " +
|
|
||||||
"(${criteria.exactParticipants}).")
|
|
||||||
|
|
||||||
// Participants.
|
// Participants.
|
||||||
if (criteria.participants != null || criteria.exactParticipants != null) {
|
criteria.participants?.let {
|
||||||
// Join VaultFungibleState and PersistentParty tables (participant values are added to the common query criteria predicate)
|
// Join VaultFungibleState and PersistentParty tables (participant values are added to the common query criteria predicate)
|
||||||
val statePartyToFungibleStatesJoin = criteriaBuilder.and(
|
val statePartyToFungibleStatesJoin = criteriaBuilder.and(
|
||||||
criteriaBuilder.equal(vaultFungibleStatesRoot.get<VaultSchemaV1.VaultFungibleStates>("stateRef"),
|
criteriaBuilder.equal(vaultFungibleStatesRoot.get<VaultSchemaV1.VaultFungibleStates>("stateRef"),
|
||||||
@ -512,12 +508,8 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
|||||||
predicateSet.add(criteriaBuilder.and(vaultLinearStatesRoot.get<String>("externalId").`in`(externalIds)))
|
predicateSet.add(criteriaBuilder.and(vaultLinearStatesRoot.get<String>("externalId").`in`(externalIds)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (criteria.participants != null && criteria.exactParticipants != null)
|
|
||||||
throw VaultQueryException("Cannot specify both participants (${criteria.participants}) " +
|
|
||||||
"and exactParticipants (${criteria.exactParticipants}).")
|
|
||||||
|
|
||||||
// Participants.
|
// Participants.
|
||||||
if (criteria.participants != null || criteria.exactParticipants != null) {
|
criteria.participants?.let {
|
||||||
// Join VaultLinearState and PersistentParty tables (participant values are added to the common query criteria predicate)
|
// Join VaultLinearState and PersistentParty tables (participant values are added to the common query criteria predicate)
|
||||||
val statePartyToLinearStatesJoin = criteriaBuilder.and(
|
val statePartyToLinearStatesJoin = criteriaBuilder.and(
|
||||||
criteriaBuilder.equal(vaultLinearStatesRoot.get<VaultSchemaV1.VaultLinearStates>("stateRef"),
|
criteriaBuilder.equal(vaultLinearStatesRoot.get<VaultSchemaV1.VaultLinearStates>("stateRef"),
|
||||||
@ -710,38 +702,6 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exact participants
|
|
||||||
// Requires a tricky SQL query to ensure *only* exact matches are selected (eg. a transaction cannot have more nor less than the
|
|
||||||
// exact participants specified in the query criteria).
|
|
||||||
criteria.exactParticipants?.let {
|
|
||||||
val exactParticipants = criteria.exactParticipants!!
|
|
||||||
|
|
||||||
// obtain all transactions where other participants are not present
|
|
||||||
val subQueryNotExists = criteriaQuery.subquery(Tuple::class.java)
|
|
||||||
val subRoot = subQueryNotExists.from(VaultSchemaV1.PersistentParty::class.java)
|
|
||||||
subQueryNotExists.select(subRoot.get("x500Name"))
|
|
||||||
subQueryNotExists.where(criteriaBuilder.and(
|
|
||||||
criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"),
|
|
||||||
subRoot.get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef"))),
|
|
||||||
criteriaBuilder.not(subRoot.get<VaultSchemaV1.PersistentParty>("x500Name").`in`(exactParticipants)))
|
|
||||||
val subQueryNotExistsPredicate = criteriaBuilder.and(criteriaBuilder.not(criteriaBuilder.exists(subQueryNotExists)))
|
|
||||||
constraintPredicates.add(subQueryNotExistsPredicate)
|
|
||||||
|
|
||||||
// join with transactions for each matching participant (only required where more than one)
|
|
||||||
if (exactParticipants.size > 1)
|
|
||||||
exactParticipants.forEach { participant ->
|
|
||||||
val subQueryExists = criteriaQuery.subquery(Tuple::class.java)
|
|
||||||
val subRootExists = subQueryExists.from(VaultSchemaV1.PersistentParty::class.java)
|
|
||||||
subQueryExists.select(subRootExists.get("x500Name"))
|
|
||||||
subQueryExists.where(criteriaBuilder.and(
|
|
||||||
criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"),
|
|
||||||
subRootExists.get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef"))),
|
|
||||||
criteriaBuilder.equal(subRootExists.get<VaultSchemaV1.PersistentParty>("x500Name"), participant))
|
|
||||||
val subQueryExistsPredicate = criteriaBuilder.and(criteriaBuilder.exists(subQueryExists))
|
|
||||||
constraintPredicates.add(subQueryExistsPredicate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return emptySet()
|
return emptySet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,19 +12,23 @@
|
|||||||
<include file="migration/node-core.changelog-v8.xml"/>
|
<include file="migration/node-core.changelog-v8.xml"/>
|
||||||
<include file="migration/node-core.changelog-tx-mapping.xml"/>
|
<include file="migration/node-core.changelog-tx-mapping.xml"/>
|
||||||
<include file="migration/node-core.changelog-v9.xml"/>
|
<include file="migration/node-core.changelog-v9.xml"/>
|
||||||
|
<!-- This migration was originally written within the same script as node-core.changelog-v14-data. However, node-core.changelog-v10
|
||||||
|
runs a service with mapped schema which now has the new table so the table should be created before hand. The transfer of data
|
||||||
|
can then happen later in node-core.changelog-v14-data. -->
|
||||||
|
<include file="migration/node-core.changelog-v14-table.xml"/>
|
||||||
<include file="migration/node-core.changelog-v10.xml"/>
|
<include file="migration/node-core.changelog-v10.xml"/>
|
||||||
<include file="migration/node-core.changelog-v11.xml"/>
|
<include file="migration/node-core.changelog-v11.xml"/>
|
||||||
<!-- This migration was originally written within the same script as node-core.changelog-v14-data. However, node-core.changelog-v12
|
|
||||||
runs a service with mapped schema which now has the new table so the table should be created before hand. The transfer of data
|
|
||||||
can then happen later in node-core.changelog-v14-data. -->
|
|
||||||
<include file="migration/node-core.changelog-v14-table.xml"/>
|
|
||||||
<include file="migration/node-core.changelog-v12.xml"/>
|
<include file="migration/node-core.changelog-v12.xml"/>
|
||||||
<!-- This migration (which creates extra columns in the transactions tables), must be run before the vault state migration (in
|
<!-- This changeset (which creates extra columns in the transactions tables), must be run before the vault state migration (in
|
||||||
vault-schema.changelog-v9.xml), as that will use the current hibernate mappings, and those require all DB columns to be created. -->
|
vault-schema.changelog-v9.xml), as that will use the current hibernate mappings, and those require all DB columns to be
|
||||||
|
created. -->
|
||||||
<include file="migration/node-core.changelog-v13.xml"/>
|
<include file="migration/node-core.changelog-v13.xml"/>
|
||||||
<!-- This change should be done before the v14-data migration. -->
|
<!-- This change should be done before the v14-data migration. -->
|
||||||
|
<include file="migration/node-core.changelog-v15-table.xml"/>
|
||||||
<include file="migration/node-core.changelog-v15.xml"/>
|
<include file="migration/node-core.changelog-v15.xml"/>
|
||||||
|
|
||||||
|
<include file="migration/node-core.changelog-v16.xml"/>
|
||||||
|
|
||||||
<!-- This must run after node-core.changelog-init.xml, to prevent database columns being created twice. -->
|
<!-- This must run after node-core.changelog-init.xml, to prevent database columns being created twice. -->
|
||||||
<include file="migration/vault-schema.changelog-v9.xml"/>
|
<include file="migration/vault-schema.changelog-v9.xml"/>
|
||||||
|
|
||||||
|
@ -20,18 +20,6 @@
|
|||||||
|
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
<changeSet author="R3.Corda" id="modify identity_value column type" dbms="postgresql">
|
|
||||||
<addColumn tableName="node_identities">
|
|
||||||
<column name="temp_identity_value" type="varbinary(64000)">
|
|
||||||
<constraints nullable="true"/>
|
|
||||||
</column>
|
|
||||||
</addColumn>
|
|
||||||
<sql>UPDATE node_identities SET temp_identity_value = lo_get(identity_value)</sql>
|
|
||||||
<addNotNullConstraint tableName="node_identities" columnName="temp_identity_value"/>
|
|
||||||
<dropColumn tableName="node_identities" columnName="identity_value"/>
|
|
||||||
<renameColumn tableName="node_identities" oldColumnName="temp_identity_value" newColumnName="identity_value"/>
|
|
||||||
</changeSet>
|
|
||||||
|
|
||||||
<changeSet author="R3.Corda" id="migrate_identity_service_to_use_publicKey.toShortString()">
|
<changeSet author="R3.Corda" id="migrate_identity_service_to_use_publicKey.toShortString()">
|
||||||
<customChange class="net.corda.node.migration.PersistentIdentityMigration">
|
<customChange class="net.corda.node.migration.PersistentIdentityMigration">
|
||||||
</customChange>
|
</customChange>
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd"
|
||||||
|
logicalFilePath="migration/node-services.changelog-init.xml">
|
||||||
|
|
||||||
|
<changeSet author="R3.Corda" id="add-new-pk-hash-to-pk-table">
|
||||||
|
<createTable tableName="node_hash_to_key">
|
||||||
|
<column name="pk_hash" type="NVARCHAR(130)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="public_key" type="blob">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</createTable>
|
||||||
|
<addPrimaryKey columnNames="pk_hash" constraintName="node_hash_to_key_pk_hash" tableName="node_hash_to_key"/>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
</databaseChangeLog>
|
@ -1,31 +1,25 @@
|
|||||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd"
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
|
||||||
logicalFilePath="migration/node-services.changelog-init.xml">
|
|
||||||
|
|
||||||
<changeSet author="R3.Corda" id="add-new-pk-hash-to-pk-table" dbms="h2,mssql">
|
<changeSet author="R3.Corda" id="modify identity_value column type" dbms="postgresql">
|
||||||
<createTable tableName="node_hash_to_key">
|
|
||||||
<column name="pk_hash" type="NVARCHAR(130)">
|
|
||||||
<constraints nullable="false"/>
|
|
||||||
</column>
|
|
||||||
<column name="public_key" type="blob">
|
|
||||||
<constraints nullable="false"/>
|
|
||||||
</column>
|
|
||||||
</createTable>
|
|
||||||
<addPrimaryKey columnNames="pk_hash" constraintName="node_hash_to_key_pk_hash" tableName="node_hash_to_key"/>
|
|
||||||
</changeSet>
|
|
||||||
|
|
||||||
<changeSet author="R3.Corda" id="add-new-pk-hash-to-pk-table-postgresql" dbms="postgresql">
|
<preConditions onFail="MARK_RAN">
|
||||||
<createTable tableName="node_hash_to_key">
|
<not>
|
||||||
<column name="pk_hash" type="NVARCHAR(130)">
|
<sqlCheck expectedResult="bytea">
|
||||||
|
SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'node_identities' AND COLUMN_NAME = 'identity_value'
|
||||||
|
</sqlCheck>
|
||||||
|
</not>
|
||||||
|
</preConditions>
|
||||||
|
|
||||||
|
<dropColumn tableName="node_identities" columnName="identity_value"/>
|
||||||
|
<addColumn tableName="node_identities">
|
||||||
|
<column name="identity_value" type="varbinary(64000)">
|
||||||
<constraints nullable="false"/>
|
<constraints nullable="false"/>
|
||||||
</column>
|
</column>
|
||||||
<column name="public_key" type="varbinary(64000)">
|
</addColumn>
|
||||||
<constraints nullable="false"/>
|
|
||||||
</column>
|
|
||||||
</createTable>
|
|
||||||
<addPrimaryKey columnNames="pk_hash" constraintName="node_hash_to_key_pk_hash" tableName="node_hash_to_key"/>
|
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
|
||||||
|
<changeSet author="R3.Corda" id="modify public_key column type" dbms="postgresql">
|
||||||
|
<preConditions onFail="MARK_RAN">
|
||||||
|
<not>
|
||||||
|
<sqlCheck expectedResult="bytea">
|
||||||
|
SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'node_hash_to_key' AND COLUMN_NAME = 'public_key'
|
||||||
|
</sqlCheck>
|
||||||
|
</not>
|
||||||
|
</preConditions>
|
||||||
|
<dropColumn tableName="node_hash_to_key" columnName="public_key"/>
|
||||||
|
<addColumn tableName="node_hash_to_key">
|
||||||
|
<column name="public_key" type="varbinary(64000)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
@ -241,11 +241,6 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
|||||||
val criteria = VaultQueryCriteria(participants = listOf(BIG_CORP))
|
val criteria = VaultQueryCriteria(participants = listOf(BIG_CORP))
|
||||||
val results = vaultService.queryBy<ContractState>(criteria)
|
val results = vaultService.queryBy<ContractState>(criteria)
|
||||||
assertThat(results.states).hasSize(1)
|
assertThat(results.states).hasSize(1)
|
||||||
|
|
||||||
// same query using strict participant matching
|
|
||||||
val strictCriteria = VaultQueryCriteria().withExactParticipants(listOf(BIG_CORP))
|
|
||||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
|
||||||
assertThat(strictResults.states).hasSize(0) // all states include node identity (MEGA_CORP)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,11 +254,6 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
|||||||
val criteria = VaultQueryCriteria(participants = listOf(MINI_CORP, BIG_CORP))
|
val criteria = VaultQueryCriteria(participants = listOf(MINI_CORP, BIG_CORP))
|
||||||
val results = vaultService.queryBy<ContractState>(criteria)
|
val results = vaultService.queryBy<ContractState>(criteria)
|
||||||
assertThat(results.states).hasSize(2)
|
assertThat(results.states).hasSize(2)
|
||||||
|
|
||||||
// same query using strict participant matching
|
|
||||||
val strictCriteria = VaultQueryCriteria().withExactParticipants(listOf(MEGA_CORP, BIG_CORP))
|
|
||||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
|
||||||
assertThat(strictResults.states).hasSize(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,48 +795,10 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
|||||||
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
|
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
|
||||||
vaultFiller.fillWithSomeTestLinearStates(2, "TEST", participants = listOf(MEGA_CORP, MINI_CORP))
|
vaultFiller.fillWithSomeTestLinearStates(2, "TEST", participants = listOf(MEGA_CORP, MINI_CORP))
|
||||||
vaultFiller.fillWithSomeTestDeals(listOf("456"), participants = listOf(MEGA_CORP, BIG_CORP))
|
vaultFiller.fillWithSomeTestDeals(listOf("456"), participants = listOf(MEGA_CORP, BIG_CORP))
|
||||||
vaultFiller.fillWithSomeTestDeals(listOf("123", "789"), participants = listOf(MEGA_CORP))
|
vaultFiller.fillWithSomeTestDeals(listOf("123", "789"), participants = listOf(BIG_CORP))
|
||||||
|
val criteria = LinearStateQueryCriteria(participants = listOf(BIG_CORP))
|
||||||
val criteria = LinearStateQueryCriteria(participants = listOf(MEGA_CORP))
|
|
||||||
val results = vaultService.queryBy<ContractState>(criteria)
|
val results = vaultService.queryBy<ContractState>(criteria)
|
||||||
assertThat(results.states).hasSize(5)
|
assertThat(results.states).hasSize(3)
|
||||||
|
|
||||||
// same query using strict participant matching
|
|
||||||
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(listOf(MEGA_CORP))
|
|
||||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
|
||||||
assertThat(strictResults.states).hasSize(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `unconsumed dummy states for exact single participant`() {
|
|
||||||
database.transaction {
|
|
||||||
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
|
|
||||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, MINI_CORP))
|
|
||||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, BIG_CORP))
|
|
||||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP)) // exact match
|
|
||||||
val strictCriteria = VaultQueryCriteria(exactParticipants = listOf(MEGA_CORP))
|
|
||||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
|
||||||
assertThat(strictResults.states).hasSize(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `unconsumed dummy states for exact two participants`() {
|
|
||||||
database.transaction {
|
|
||||||
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
|
|
||||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, MINI_CORP))
|
|
||||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, BIG_CORP)) // exact match
|
|
||||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP))
|
|
||||||
|
|
||||||
val strictCriteria = VaultQueryCriteria(exactParticipants = listOf(MEGA_CORP, BIG_CORP))
|
|
||||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
|
||||||
assertThat(strictResults.states).hasSize(1)
|
|
||||||
|
|
||||||
// same query using strict participant matching (unordered list of participants)
|
|
||||||
val strictCriteriaUnordered = VaultQueryCriteria(exactParticipants = listOf(BIG_CORP, MEGA_CORP))
|
|
||||||
val strictResultsUnordered = vaultService.queryBy<ContractState>(strictCriteriaUnordered)
|
|
||||||
assertThat(strictResultsUnordered.states).hasSize(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,19 +813,8 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
|||||||
val criteria = LinearStateQueryCriteria(participants = listOf(BIG_CORP, MINI_CORP))
|
val criteria = LinearStateQueryCriteria(participants = listOf(BIG_CORP, MINI_CORP))
|
||||||
val results = vaultService.queryBy<ContractState>(criteria)
|
val results = vaultService.queryBy<ContractState>(criteria)
|
||||||
// DOCEND VaultQueryExample5
|
// DOCEND VaultQueryExample5
|
||||||
|
|
||||||
assertThat(results.states).hasSize(3)
|
assertThat(results.states).hasSize(3)
|
||||||
|
|
||||||
// same query using strict participant matching
|
|
||||||
// DOCSTART VaultQueryExample51
|
|
||||||
val strictCriteria = LinearStateQueryCriteria(exactParticipants = listOf(MEGA_CORP, BIG_CORP))
|
|
||||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
|
||||||
// DOCEND VaultQueryExample51
|
|
||||||
assertThat(strictResults.states).hasSize(1)
|
|
||||||
|
|
||||||
// same query using strict participant matching (unordered list of participants)
|
|
||||||
val strictCriteriaUnordered = LinearStateQueryCriteria(exactParticipants = listOf(BIG_CORP, MEGA_CORP))
|
|
||||||
val strictResultsUnordered = vaultService.queryBy<ContractState>(strictCriteriaUnordered)
|
|
||||||
assertThat(strictResultsUnordered.states).hasSize(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2018,13 +1959,6 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
|||||||
// DOCEND VaultQueryExample11
|
// DOCEND VaultQueryExample11
|
||||||
|
|
||||||
assertThat(results.states).hasSize(1)
|
assertThat(results.states).hasSize(1)
|
||||||
|
|
||||||
// same query using strict participant matching
|
|
||||||
// DOCSTART VaultQueryExample52
|
|
||||||
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(parties)
|
|
||||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
|
||||||
// DOCEND VaultQueryExample52
|
|
||||||
assertThat(strictResults.states).hasSize(0) // node identity included (MEGA_CORP)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2418,11 +2352,6 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
|||||||
|
|
||||||
assertThat(results.states).hasSize(1)
|
assertThat(results.states).hasSize(1)
|
||||||
assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1")
|
assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1")
|
||||||
|
|
||||||
// same query using strict participant matching
|
|
||||||
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(listOf(ALICE))
|
|
||||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
|
||||||
assertThat(strictResults.states).hasSize(0) // all states include node identity (MEGA_CORP)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2440,11 +2369,6 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
|||||||
|
|
||||||
assertThat(results.states).hasSize(1)
|
assertThat(results.states).hasSize(1)
|
||||||
assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1")
|
assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1")
|
||||||
|
|
||||||
// same query using strict participant matching
|
|
||||||
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(listOf(MEGA_CORP, ALICE, BOB, CHARLIE))
|
|
||||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
|
||||||
assertThat(strictResults.states).hasSize(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2477,7 +2401,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `composite query for fungible, linear and dummy states for multiple participants`() {
|
fun `composite query for fungible and linear states for multiple participants`() {
|
||||||
database.transaction {
|
database.transaction {
|
||||||
identitySvc.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
identitySvc.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
||||||
identitySvc.verifyAndRegisterIdentity(BOB_IDENTITY)
|
identitySvc.verifyAndRegisterIdentity(BOB_IDENTITY)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package net.corda.bank.api
|
package net.corda.bank.api
|
||||||
|
|
||||||
import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
|
import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
|
||||||
import net.corda.client.rpc.CordaRPCClient
|
import net.corda.client.rpc.CordaRPCClientConfiguration
|
||||||
import net.corda.client.rpc.GracefulReconnect
|
import net.corda.client.rpc.internal.ReconnectingCordaRPCOps
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
@ -35,9 +35,7 @@ object BankOfCordaClientApi {
|
|||||||
*
|
*
|
||||||
* @return a payment transaction (following successful issuance of cash to self).
|
* @return a payment transaction (following successful issuance of cash to self).
|
||||||
*/
|
*/
|
||||||
fun requestRPCIssue(rpcAddress: NetworkHostAndPort, params: IssueRequestParams): SignedTransaction {
|
fun requestRPCIssue(rpcAddress: NetworkHostAndPort, params: IssueRequestParams): SignedTransaction = requestRPCIssueHA(listOf(rpcAddress), params)
|
||||||
return requestRPCIssueHA(listOf(rpcAddress), params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RPC API
|
* RPC API
|
||||||
@ -46,28 +44,20 @@ object BankOfCordaClientApi {
|
|||||||
*/
|
*/
|
||||||
fun requestRPCIssueHA(availableRpcServers: List<NetworkHostAndPort>, params: IssueRequestParams): SignedTransaction {
|
fun requestRPCIssueHA(availableRpcServers: List<NetworkHostAndPort>, params: IssueRequestParams): SignedTransaction {
|
||||||
// TODO: privileged security controls required
|
// TODO: privileged security controls required
|
||||||
CordaRPCClient(availableRpcServers)
|
ReconnectingCordaRPCOps(availableRpcServers, BOC_RPC_USER, BOC_RPC_PWD, CordaRPCClientConfiguration.DEFAULT).use { rpc->
|
||||||
.start(BOC_RPC_USER, BOC_RPC_PWD, gracefulReconnect = GracefulReconnect()).use { rpc->
|
rpc.waitUntilNetworkReady().getOrThrow()
|
||||||
rpc.proxy.waitUntilNetworkReady().getOrThrow()
|
|
||||||
|
|
||||||
// Resolve parties via RPC
|
// Resolve parties via RPC
|
||||||
val issueToParty = rpc.proxy.wellKnownPartyFromX500Name(params.issueToPartyName)
|
val issueToParty = rpc.wellKnownPartyFromX500Name(params.issueToPartyName)
|
||||||
?: throw IllegalStateException("Unable to locate ${params.issueToPartyName} in Network Map Service")
|
?: throw IllegalStateException("Unable to locate ${params.issueToPartyName} in Network Map Service")
|
||||||
val notaryLegalIdentity = rpc.proxy.notaryIdentities().firstOrNull { it.name == params.notaryName }
|
val notaryLegalIdentity = rpc.notaryIdentities().firstOrNull { it.name == params.notaryName }
|
||||||
?: throw IllegalStateException("Couldn't locate notary ${params.notaryName} in NetworkMapCache")
|
?: throw IllegalStateException("Couldn't locate notary ${params.notaryName} in NetworkMapCache")
|
||||||
|
|
||||||
val anonymous = true
|
val anonymous = true
|
||||||
val issuerBankPartyRef = OpaqueBytes.of(params.issuerBankPartyRef.toByte())
|
val issuerBankPartyRef = OpaqueBytes.of(params.issuerBankPartyRef.toByte())
|
||||||
|
|
||||||
logger.info("${rpc.proxy.nodeInfo()} issuing ${params.amount} to transfer to $issueToParty ...")
|
logger.info("${rpc.nodeInfo()} issuing ${params.amount} to transfer to $issueToParty ...")
|
||||||
return rpc.proxy.startFlow(
|
return rpc.startFlow(::CashIssueAndPaymentFlow, params.amount, issuerBankPartyRef, issueToParty, anonymous, notaryLegalIdentity)
|
||||||
::CashIssueAndPaymentFlow,
|
|
||||||
params.amount,
|
|
||||||
issuerBankPartyRef,
|
|
||||||
issueToParty,
|
|
||||||
anonymous,
|
|
||||||
notaryLegalIdentity
|
|
||||||
)
|
|
||||||
.returnValue.getOrThrow().stx
|
.returnValue.getOrThrow().stx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,8 @@ package net.corda.webserver.internal
|
|||||||
import com.google.common.html.HtmlEscapers.htmlEscaper
|
import com.google.common.html.HtmlEscapers.htmlEscaper
|
||||||
import io.netty.channel.unix.Errors
|
import io.netty.channel.unix.Errors
|
||||||
import net.corda.client.jackson.JacksonSupport
|
import net.corda.client.jackson.JacksonSupport
|
||||||
import net.corda.client.rpc.CordaRPCClient
|
import net.corda.client.rpc.CordaRPCClientConfiguration
|
||||||
import net.corda.client.rpc.CordaRPCConnection
|
import net.corda.client.rpc.internal.ReconnectingCordaRPCOps
|
||||||
import net.corda.client.rpc.GracefulReconnect
|
|
||||||
import net.corda.core.internal.errors.AddressBindingException
|
import net.corda.core.internal.errors.AddressBindingException
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
@ -47,12 +46,8 @@ class NodeWebServer(val config: WebServerConfig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun run() {
|
fun run() {
|
||||||
try {
|
while (server.isRunning) {
|
||||||
while (server.isRunning) {
|
Thread.sleep(100) // TODO: Redesign
|
||||||
Thread.sleep(100) // TODO: Redesign
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
rpc.close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,11 +75,7 @@ class NodeWebServer(val config: WebServerConfig) {
|
|||||||
sslContextFactory.setIncludeProtocols("TLSv1.2")
|
sslContextFactory.setIncludeProtocols("TLSv1.2")
|
||||||
sslContextFactory.setExcludeCipherSuites(".*NULL.*", ".*RC4.*", ".*MD5.*", ".*DES.*", ".*DSS.*")
|
sslContextFactory.setExcludeCipherSuites(".*NULL.*", ".*RC4.*", ".*MD5.*", ".*DES.*", ".*DSS.*")
|
||||||
sslContextFactory.setIncludeCipherSuites(".*AES.*GCM.*")
|
sslContextFactory.setIncludeCipherSuites(".*AES.*GCM.*")
|
||||||
val sslConnector = ServerConnector(
|
val sslConnector = ServerConnector(server, SslConnectionFactory(sslContextFactory, "http/1.1"), HttpConnectionFactory(httpsConfiguration))
|
||||||
server,
|
|
||||||
SslConnectionFactory(sslContextFactory, "http/1.1"),
|
|
||||||
HttpConnectionFactory(httpsConfiguration)
|
|
||||||
)
|
|
||||||
sslConnector.port = address.port
|
sslConnector.port = address.port
|
||||||
sslConnector
|
sslConnector
|
||||||
} else {
|
} else {
|
||||||
@ -184,21 +175,9 @@ class NodeWebServer(val config: WebServerConfig) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var rpc: CordaRPCConnection
|
private fun reconnectingCordaRPCOps() = ReconnectingCordaRPCOps(config.rpcAddress, config.runAs.username , config.runAs.password, CordaRPCClientConfiguration.DEFAULT, null, javaClass.classLoader)
|
||||||
private fun reconnectingCordaRPCOps(): CordaRPCOps {
|
|
||||||
rpc = CordaRPCClient(config.rpcAddress, null, javaClass.classLoader)
|
|
||||||
.start(
|
|
||||||
config.runAs.username,
|
|
||||||
config.runAs.password,
|
|
||||||
GracefulReconnect()
|
|
||||||
)
|
|
||||||
return rpc.proxy
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Fetch WebServerPluginRegistry classes registered in META-INF/services/net.corda.webserver.services.WebServerPluginRegistry files that exist in the classpath */
|
||||||
* Fetch WebServerPluginRegistry classes registered in META-INF/services/net.corda.webserver.services.WebServerPluginRegistry
|
|
||||||
* files that exist in the classpath
|
|
||||||
*/
|
|
||||||
val pluginRegistries: List<WebServerPluginRegistry> by lazy {
|
val pluginRegistries: List<WebServerPluginRegistry> by lazy {
|
||||||
ServiceLoader.load(WebServerPluginRegistry::class.java).toList()
|
ServiceLoader.load(WebServerPluginRegistry::class.java).toList()
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import net.corda.core.contracts.withoutIssuer
|
|||||||
import net.corda.core.flows.FlowException
|
import net.corda.core.flows.FlowException
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
|
import net.corda.core.messaging.FlowHandle
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
@ -93,14 +94,15 @@ class NewTransaction : Fragment() {
|
|||||||
initOwner(window)
|
initOwner(window)
|
||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
|
val handle: FlowHandle<AbstractCashFlow.Result> = when (request) {
|
||||||
|
is IssueAndPaymentRequest -> rpcProxy.value!!.startFlow(::CashIssueAndPaymentFlow, request)
|
||||||
|
is PaymentRequest -> rpcProxy.value!!.startFlow(::CashPaymentFlow, request)
|
||||||
|
is ExitRequest -> rpcProxy.value!!.startFlow(::CashExitFlow, request)
|
||||||
|
else -> throw IllegalArgumentException("Unexpected request type: $request")
|
||||||
|
}
|
||||||
runAsync {
|
runAsync {
|
||||||
try {
|
try {
|
||||||
when (request) {
|
handle.returnValue.getOrThrow()
|
||||||
is IssueAndPaymentRequest -> rpcProxy.value!!.startFlow(::CashIssueAndPaymentFlow, request)
|
|
||||||
is PaymentRequest -> rpcProxy.value!!.startFlow(::CashPaymentFlow, request)
|
|
||||||
is ExitRequest -> rpcProxy.value!!.startFlow(::CashExitFlow, request)
|
|
||||||
else -> throw IllegalArgumentException("Unexpected request type: $request")
|
|
||||||
}.returnValue.getOrThrow()
|
|
||||||
} finally {
|
} finally {
|
||||||
dialog.dialogPane.isDisable = false
|
dialog.dialogPane.isDisable = false
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ import net.corda.client.jackson.JacksonSupport
|
|||||||
import net.corda.client.jackson.StringToMethodCallParser
|
import net.corda.client.jackson.StringToMethodCallParser
|
||||||
import net.corda.client.rpc.CordaRPCClient
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.client.rpc.CordaRPCClientConfiguration
|
import net.corda.client.rpc.CordaRPCClientConfiguration
|
||||||
import net.corda.client.rpc.GracefulReconnect
|
|
||||||
import net.corda.client.rpc.PermissionException
|
import net.corda.client.rpc.PermissionException
|
||||||
|
import net.corda.client.rpc.internal.ReconnectingCordaRPCOps
|
||||||
import net.corda.core.CordaException
|
import net.corda.core.CordaException
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.contracts.UniqueIdentifier
|
import net.corda.core.contracts.UniqueIdentifier
|
||||||
@ -22,6 +22,7 @@ import net.corda.core.internal.*
|
|||||||
import net.corda.core.internal.concurrent.doneFuture
|
import net.corda.core.internal.concurrent.doneFuture
|
||||||
import net.corda.core.internal.concurrent.openFuture
|
import net.corda.core.internal.concurrent.openFuture
|
||||||
import net.corda.core.internal.messaging.InternalCordaRPCOps
|
import net.corda.core.internal.messaging.InternalCordaRPCOps
|
||||||
|
import net.corda.core.internal.packageName_
|
||||||
import net.corda.core.messaging.*
|
import net.corda.core.messaging.*
|
||||||
import net.corda.tools.shell.utlities.ANSIProgressRenderer
|
import net.corda.tools.shell.utlities.ANSIProgressRenderer
|
||||||
import net.corda.tools.shell.utlities.StdoutANSIProgressRenderer
|
import net.corda.tools.shell.utlities.StdoutANSIProgressRenderer
|
||||||
@ -90,24 +91,21 @@ object InteractiveShell {
|
|||||||
|
|
||||||
fun startShell(configuration: ShellConfiguration, classLoader: ClassLoader? = null, standalone: Boolean = false) {
|
fun startShell(configuration: ShellConfiguration, classLoader: ClassLoader? = null, standalone: Boolean = false) {
|
||||||
rpcOps = { username: String, password: String ->
|
rpcOps = { username: String, password: String ->
|
||||||
val connection = if (standalone) {
|
if (standalone) {
|
||||||
CordaRPCClient(
|
ReconnectingCordaRPCOps(configuration.hostAndPort, username, password, CordaRPCClientConfiguration.DEFAULT, configuration.ssl, classLoader).also {
|
||||||
configuration.hostAndPort,
|
rpcConn = it
|
||||||
configuration.ssl,
|
}
|
||||||
classLoader
|
|
||||||
).start(username, password, gracefulReconnect = GracefulReconnect())
|
|
||||||
} else {
|
} else {
|
||||||
CordaRPCClient(
|
val client = CordaRPCClient(hostAndPort = configuration.hostAndPort,
|
||||||
hostAndPort = configuration.hostAndPort,
|
|
||||||
configuration = CordaRPCClientConfiguration.DEFAULT.copy(
|
configuration = CordaRPCClientConfiguration.DEFAULT.copy(
|
||||||
maxReconnectAttempts = 1
|
maxReconnectAttempts = 1
|
||||||
),
|
),
|
||||||
sslConfiguration = configuration.ssl,
|
sslConfiguration = configuration.ssl,
|
||||||
classLoader = classLoader
|
classLoader = classLoader)
|
||||||
).start(username, password)
|
val connection = client.start(username, password)
|
||||||
|
rpcConn = connection
|
||||||
|
connection.proxy as InternalCordaRPCOps
|
||||||
}
|
}
|
||||||
rpcConn = connection
|
|
||||||
connection.proxy as InternalCordaRPCOps
|
|
||||||
}
|
}
|
||||||
_startShell(configuration, classLoader)
|
_startShell(configuration, classLoader)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user