Merge pull request #1205 from corda/os-merge-244167d

O/S merge from 244167d
This commit is contained in:
Shams Asari 2018-07-05 17:16:52 +01:00 committed by GitHub
commit 300e0573fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
143 changed files with 881 additions and 926 deletions

9
.idea/compiler.xml generated
View File

@ -54,6 +54,12 @@
<module name="contracts-states_test" target="1.8" /> <module name="contracts-states_test" target="1.8" />
<module name="corda-core_integrationTest" target="1.8" /> <module name="corda-core_integrationTest" target="1.8" />
<module name="corda-core_smokeTest" target="1.8" /> <module name="corda-core_smokeTest" target="1.8" />
<module name="corda-enterprise-testing_main" target="1.8" />
<module name="corda-enterprise-testing_test" target="1.8" />
<module name="corda-enterprise-tools_main" target="1.8" />
<module name="corda-enterprise-tools_test" target="1.8" />
<module name="corda-enterprise_main" target="1.8" />
<module name="corda-enterprise_test" target="1.8" />
<module name="corda-finance_integrationTest" target="1.8" /> <module name="corda-finance_integrationTest" target="1.8" />
<module name="corda-project-testing_main" target="1.8" /> <module name="corda-project-testing_main" target="1.8" />
<module name="corda-project-testing_test" target="1.8" /> <module name="corda-project-testing_test" target="1.8" />
@ -93,6 +99,7 @@
<module name="demobench_main" target="1.8" /> <module name="demobench_main" target="1.8" />
<module name="demobench_test" target="1.8" /> <module name="demobench_test" target="1.8" />
<module name="dist_binFiles" target="1.8" /> <module name="dist_binFiles" target="1.8" />
<module name="dist_installerFiles" target="1.8" />
<module name="dist_licenseFiles" target="1.8" /> <module name="dist_licenseFiles" target="1.8" />
<module name="dist_main" target="1.8" /> <module name="dist_main" target="1.8" />
<module name="dist_readmeFiles" target="1.8" /> <module name="dist_readmeFiles" target="1.8" />
@ -170,6 +177,8 @@
<module name="mock_test" target="1.8" /> <module name="mock_test" target="1.8" />
<module name="network-bootstrapper_main" target="1.8" /> <module name="network-bootstrapper_main" target="1.8" />
<module name="network-bootstrapper_test" target="1.8" /> <module name="network-bootstrapper_test" target="1.8" />
<module name="network-verifier_main" target="1.8" />
<module name="network-verifier_test" target="1.8" />
<module name="network-visualiser_main" target="1.8" /> <module name="network-visualiser_main" target="1.8" />
<module name="network-visualiser_test" target="1.8" /> <module name="network-visualiser_test" target="1.8" />
<module name="node-api_main" target="1.8" /> <module name="node-api_main" target="1.8" />

View File

@ -7,12 +7,10 @@ import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.* import net.corda.core.internal.*
import net.corda.core.node.NetworkParameters import net.corda.core.node.NetworkParameters
import net.corda.core.node.NotaryInfo import net.corda.core.node.NotaryInfo
import net.corda.core.node.services.AttachmentId
import net.corda.core.serialization.SerializationDefaults import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
import net.corda.node.services.config.CertChainPolicyConfig
import net.corda.node.services.config.EnterpriseConfiguration import net.corda.node.services.config.EnterpriseConfiguration
import net.corda.node.services.config.MutualExclusionConfiguration import net.corda.node.services.config.MutualExclusionConfiguration
import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfiguration
@ -102,7 +100,7 @@ class BridgeSmokeTest {
bridgeJar.copyToDirectory(testDir) bridgeJar.copyToDirectory(testDir)
} }
fun createNetworkParams(baseDirectory: Path) { private fun createNetworkParams(baseDirectory: Path) {
val dummyNotaryParty = TestIdentity(DUMMY_NOTARY_NAME) val dummyNotaryParty = TestIdentity(DUMMY_NOTARY_NAME)
val notaryInfo = NotaryInfo(dummyNotaryParty.party, false) val notaryInfo = NotaryInfo(dummyNotaryParty.party, false)
val copier = NetworkParametersCopier(NetworkParameters( val copier = NetworkParametersCopier(NetworkParameters(
@ -112,18 +110,18 @@ class BridgeSmokeTest {
maxMessageSize = 10485760, maxMessageSize = 10485760,
maxTransactionSize = 40000, maxTransactionSize = 40000,
epoch = 1, epoch = 1,
whitelistedContractImplementations = emptyMap<String, List<AttachmentId>>() whitelistedContractImplementations = emptyMap()
), overwriteFile = true) ), overwriteFile = true)
copier.install(baseDirectory) copier.install(baseDirectory)
} }
fun SSLConfiguration.createBridgeKeyStores(legalName: CordaX500Name, private fun SSLConfiguration.createBridgeKeyStores(legalName: CordaX500Name,
rootCert: X509Certificate = DEV_ROOT_CA.certificate, rootCert: X509Certificate = DEV_ROOT_CA.certificate,
intermediateCa: CertificateAndKeyPair = DEV_INTERMEDIATE_CA) { intermediateCa: CertificateAndKeyPair = DEV_INTERMEDIATE_CA) {
certificatesDirectory.createDirectories() certificatesDirectory.createDirectories()
if (!trustStoreFile.exists()) { if (!trustStoreFile.exists()) {
loadKeyStore(javaClass.classLoader.getResourceAsStream("certificates/${DEV_CA_TRUST_STORE_FILE}"), DEV_CA_TRUST_STORE_PASS).save(trustStoreFile, trustStorePassword) loadKeyStore(javaClass.classLoader.getResourceAsStream("certificates/$DEV_CA_TRUST_STORE_FILE"), DEV_CA_TRUST_STORE_PASS).save(trustStoreFile, trustStorePassword)
} }
val (nodeCaCert, nodeCaKeyPair) = createDevNodeCa(intermediateCa, legalName) val (nodeCaCert, nodeCaKeyPair) = createDevNodeCa(intermediateCa, legalName)
@ -189,13 +187,13 @@ class BridgeSmokeTest {
} }
} }
fun serverListening(host: String, port: Int): Boolean { private fun serverListening(host: String, port: Int): Boolean {
var s: Socket? = null var s: Socket? = null
try { return try {
s = Socket(host, port) s = Socket(host, port)
return true true
} catch (e: Exception) { } catch (e: Exception) {
return false false
} finally { } finally {
try { try {
s?.close() s?.close()
@ -212,7 +210,6 @@ class BridgeSmokeTest {
doReturn("cordacadevpass").whenever(it).keyStorePassword doReturn("cordacadevpass").whenever(it).keyStorePassword
doReturn(NetworkHostAndPort("localhost", 11005)).whenever(it).p2pAddress doReturn(NetworkHostAndPort("localhost", 11005)).whenever(it).p2pAddress
doReturn(null).whenever(it).jmxMonitoringHttpPort doReturn(null).whenever(it).jmxMonitoringHttpPort
doReturn(emptyList<CertChainPolicyConfig>()).whenever(it).certificateChainCheckPolicies
doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000), externalBridge = true)).whenever(it).enterpriseConfiguration doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000), externalBridge = true)).whenever(it).enterpriseConfiguration
} }
val artemisServer = ArtemisMessagingServer(artemisConfig, NetworkHostAndPort("0.0.0.0", 11005), MAX_MESSAGE_SIZE) val artemisServer = ArtemisMessagingServer(artemisConfig, NetworkHostAndPort("0.0.0.0", 11005), MAX_MESSAGE_SIZE)

View File

@ -17,7 +17,6 @@ import net.corda.bridge.createBridgeKeyStores
import net.corda.bridge.createNetworkParams import net.corda.bridge.createNetworkParams
import net.corda.bridge.services.artemis.BridgeArtemisConnectionServiceImpl import net.corda.bridge.services.artemis.BridgeArtemisConnectionServiceImpl
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.services.config.CertChainPolicyConfig
import net.corda.node.services.config.EnterpriseConfiguration import net.corda.node.services.config.EnterpriseConfiguration
import net.corda.node.services.config.MutualExclusionConfiguration import net.corda.node.services.config.MutualExclusionConfiguration
import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfiguration
@ -102,7 +101,6 @@ class ArtemisConnectionTest {
doReturn("cordacadevpass").whenever(it).keyStorePassword doReturn("cordacadevpass").whenever(it).keyStorePassword
doReturn(NetworkHostAndPort("localhost", 11005)).whenever(it).p2pAddress doReturn(NetworkHostAndPort("localhost", 11005)).whenever(it).p2pAddress
doReturn(null).whenever(it).jmxMonitoringHttpPort doReturn(null).whenever(it).jmxMonitoringHttpPort
doReturn(emptyList<CertChainPolicyConfig>()).whenever(it).certificateChainCheckPolicies
doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000), externalBridge = true)).whenever(it).enterpriseConfiguration doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000), externalBridge = true)).whenever(it).enterpriseConfiguration
} }
val artemisServer = ArtemisMessagingServer(artemisConfig, NetworkHostAndPort("0.0.0.0", 11005), MAX_MESSAGE_SIZE) val artemisServer = ArtemisMessagingServer(artemisConfig, NetworkHostAndPort("0.0.0.0", 11005), MAX_MESSAGE_SIZE)

View File

@ -188,6 +188,7 @@ allprojects {
jvmTarget = "1.8" jvmTarget = "1.8"
javaParameters = true // Useful for reflection. javaParameters = true // Useful for reflection.
freeCompilerArgs = ['-Xjvm-default=compatibility'] freeCompilerArgs = ['-Xjvm-default=compatibility']
allWarningsAsErrors = true
} }
} }

View File

@ -39,7 +39,6 @@ task metadata(type: ProGuardTask) {
keepattributes '*' keepattributes '*'
dontoptimize dontoptimize
printseeds
verbose verbose
dontwarn 'com.sun.jna.**' dontwarn 'com.sun.jna.**'
@ -47,6 +46,7 @@ task metadata(type: ProGuardTask) {
dontwarn 'org.jetbrains.kotlin.com.intellij.**' dontwarn 'org.jetbrains.kotlin.com.intellij.**'
dontwarn 'org.jetbrains.kotlin.com.google.j2objc.annotations.**' dontwarn 'org.jetbrains.kotlin.com.google.j2objc.annotations.**'
dontwarn 'org.jetbrains.kotlin.com.google.errorprone.annotations.**' dontwarn 'org.jetbrains.kotlin.com.google.errorprone.annotations.**'
dontnote
keep 'class org.jetbrains.kotlin.load.java.JvmAnnotationNames { *; }' keep 'class org.jetbrains.kotlin.load.java.JvmAnnotationNames { *; }'
keep 'class org.jetbrains.kotlin.metadata.** { *; }', includedescriptorclasses: true keep 'class org.jetbrains.kotlin.metadata.** { *; }', includedescriptorclasses: true
@ -68,6 +68,7 @@ task validate(type: ProGuardTask) {
verbose verbose
dontwarn 'org.jetbrains.kotlin.com.google.errorprone.annotations.**' dontwarn 'org.jetbrains.kotlin.com.google.errorprone.annotations.**'
dontnote
keep 'class *' keep 'class *'
} }
@ -77,5 +78,4 @@ artifacts {
} }
defaultTasks "metadata" defaultTasks "metadata"
assemble.dependsOn metadata
metadata.finalizedBy validate metadata.finalizedBy validate

View File

@ -401,6 +401,11 @@ class JacksonSupportTest(@Suppress("unused") private val name: String, factory:
testToStringSerialisation(UUID.randomUUID()) testToStringSerialisation(UUID.randomUUID())
} }
@Test
fun Instant() {
testToStringSerialisation(Instant.now())
}
@Test @Test
fun `Date is treated as Instant`() { fun `Date is treated as Instant`() {
val date = Date() val date = Date()

View File

@ -13,7 +13,6 @@ package net.corda.client.jfx
import net.corda.client.jfx.model.NodeMonitorModel import net.corda.client.jfx.model.NodeMonitorModel
import net.corda.client.jfx.model.ProgressTrackingEvent import net.corda.client.jfx.model.ProgressTrackingEvent
import net.corda.core.context.InvocationOrigin import net.corda.core.context.InvocationOrigin
import net.corda.core.contracts.Amount
import net.corda.core.contracts.ContractState import net.corda.core.contracts.ContractState
import net.corda.core.crypto.isFulfilledBy import net.corda.core.crypto.isFulfilledBy
import net.corda.core.crypto.keys import net.corda.core.crypto.keys
@ -32,12 +31,9 @@ import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.finance.DOLLARS import net.corda.finance.DOLLARS
import net.corda.finance.USD
import net.corda.finance.flows.CashExitFlow
import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashIssueFlow
import net.corda.finance.flows.CashPaymentFlow import net.corda.finance.flows.CashPaymentFlow
import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.all
import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.testing.core.* import net.corda.testing.core.*
import net.corda.testing.driver.DriverParameters import net.corda.testing.driver.DriverParameters
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
@ -75,18 +71,7 @@ class NodeMonitorModelTest : IntegrationTest() {
private fun setup(runTest: () -> Unit) { private fun setup(runTest: () -> Unit) {
driver(DriverParameters(extraCordappPackagesToScan = listOf("net.corda.finance"))) { driver(DriverParameters(extraCordappPackagesToScan = listOf("net.corda.finance"))) {
val cashUser = User("user1", "test", permissions = setOf( val cashUser = User("user1", "test", permissions = setOf(all()))
startFlow<CashIssueFlow>(),
startFlow<CashPaymentFlow>(),
startFlow<CashExitFlow>(),
invokeRpc(CordaRPCOps::notaryIdentities),
invokeRpc("vaultTrackBy"),
invokeRpc("vaultQueryBy"),
invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed),
invokeRpc(CordaRPCOps::stateMachineRecordedTransactionMappingFeed),
invokeRpc(CordaRPCOps::stateMachinesFeed),
invokeRpc(CordaRPCOps::networkMapFeed))
)
val aliceNodeHandle = startNode(providedName = ALICE_NAME, rpcUsers = listOf(cashUser)).getOrThrow() val aliceNodeHandle = startNode(providedName = ALICE_NAME, rpcUsers = listOf(cashUser)).getOrThrow()
aliceNode = aliceNodeHandle.nodeInfo aliceNode = aliceNodeHandle.nodeInfo
newNode = { nodeName -> startNode(providedName = nodeName).getOrThrow().nodeInfo } newNode = { nodeName -> startNode(providedName = nodeName).getOrThrow().nodeInfo }
@ -135,11 +120,7 @@ class NodeMonitorModelTest : IntegrationTest() {
@Test @Test
fun `cash issue works end to end`() = setup { fun `cash issue works end to end`() = setup {
rpc.startFlow(::CashIssueFlow, rpc.startFlow(::CashIssueFlow, 100.DOLLARS, OpaqueBytes.of(1), notaryParty)
Amount(100, USD),
OpaqueBytes(ByteArray(1, { 1 })),
notaryParty
)
vaultUpdates.expectEvents(isStrict = false) { vaultUpdates.expectEvents(isStrict = false) {
sequence( sequence(

View File

@ -111,12 +111,12 @@ 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) {
// `retryableStateMachineUpdatesSubject` will change it's upstream subscriber in case of RPC connection failure, this `Observable` should // `retryableStateMachineUpdatesSubject` will change it's upstream subscriber in case of RPC connection failure, this `Observable` should
// never produce an error. // never produce an error.
// `stateMachineUpdatesSubject` will stay firmly subscribed to `retryableStateMachineUpdatesSubject` // `stateMachineUpdatesSubject` will stay firmly subscribed to `retryableStateMachineUpdatesSubject`
retryableStateMachineUpdatesSubject.subscribe(stateMachineUpdatesSubject) retryableStateMachineUpdatesSubject.subscribe(stateMachineUpdatesSubject)
@Suppress("DEPRECATION")
// Proxy may change during re-connect, ensure that subject wiring accurately reacts to this activity. // Proxy may change during re-connect, ensure that subject wiring accurately reacts to this activity.
proxyObservable.addListener { _, _, wrapper -> proxyObservable.addListener { _, _, wrapper ->
if (wrapper != null) { if (wrapper != null) {

View File

@ -57,14 +57,16 @@ class StateMachineDataModel {
private val progressTracking by observable(NodeMonitorModel::progressTracking) private val progressTracking by observable(NodeMonitorModel::progressTracking)
private val progressEvents = progressTracking.recordAsAssociation(ProgressTrackingEvent::stateMachineId) private val progressEvents = progressTracking.recordAsAssociation(ProgressTrackingEvent::stateMachineId)
val counter = Counter() private val counter = Counter()
private val stateMachineIndexMap = HashMap<StateMachineRunId, Int>() private val stateMachineIndexMap = HashMap<StateMachineRunId, Int>()
private val stateMachineStatus = stateMachineUpdates.fold(FXCollections.observableArrayList<SimpleObjectProperty<StateMachineStatus>>()) { list, update -> private val stateMachineStatus = stateMachineUpdates.fold(FXCollections.observableArrayList<SimpleObjectProperty<StateMachineStatus>>()) { list, update ->
when (update) { when (update) {
is StateMachineUpdate.Added -> { is StateMachineUpdate.Added -> {
counter.addSmm() counter.addSmm()
val flowInitiator= update.stateMachineInfo.initiator // TODO Use invocationContext instead
@Suppress("DEPRECATION")
val flowInitiator = update.stateMachineInfo.initiator
val added: SimpleObjectProperty<StateMachineStatus> = val added: SimpleObjectProperty<StateMachineStatus> =
SimpleObjectProperty(StateMachineStatus.Added(update.id, update.stateMachineInfo.flowLogicClassName, flowInitiator)) SimpleObjectProperty(StateMachineStatus.Added(update.id, update.stateMachineInfo.flowLogicClassName, flowInitiator))
list.add(added) list.add(added)
@ -83,7 +85,7 @@ class StateMachineDataModel {
private val stateMachineDataList = stateMachineStatus.map { private val stateMachineDataList = stateMachineStatus.map {
val smStatus = it.value as StateMachineStatus.Added val smStatus = it.value as StateMachineStatus.Added
val id = smStatus.id val id = smStatus.id
val progress = SimpleObjectProperty(progressEvents.get(id)) val progress = SimpleObjectProperty(progressEvents[id])
StateMachineData(id, smStatus.stateMachineName, smStatus.flowInitiator, StateMachineData(id, smStatus.stateMachineName, smStatus.flowInitiator,
Pair(it, EasyBind.map(progress) { ProgressStatus(it?.message) })) Pair(it, EasyBind.map(progress) { ProgressStatus(it?.message) }))
} }

View File

@ -58,7 +58,7 @@ data class PartiallyResolvedTransaction(
return PartiallyResolvedTransaction( return PartiallyResolvedTransaction(
transaction = transaction, transaction = transaction,
inputs = transaction.inputs.map { stateRef -> inputs = transaction.inputs.map { stateRef ->
val tx = inputTransactions.get(stateRef) val tx = inputTransactions[stateRef]
if (tx == null) { if (tx == null) {
InputResolution.Unresolved(stateRef) InputResolution.Unresolved(stateRef)
} else { } else {
@ -74,7 +74,7 @@ data class PartiallyResolvedTransaction(
val outputCount = transaction.coreTransaction.inputs.size val outputCount = transaction.coreTransaction.inputs.size
val stateRefs = (0 until outputCount).map { StateRef(transaction.id, it) } val stateRefs = (0 until outputCount).map { StateRef(transaction.id, it) }
stateRefs.map { stateRef -> stateRefs.map { stateRef ->
val tx = inputTransactions.get(stateRef) val tx = inputTransactions[stateRef]
if (tx == null) { if (tx == null) {
OutputResolution.Unresolved(stateRef) OutputResolution.Unresolved(stateRef)
} else { } else {
@ -94,6 +94,7 @@ class TransactionDataModel {
private val collectedTransactions = transactions.recordInSequence().distinctBy { it.id } private val collectedTransactions = transactions.recordInSequence().distinctBy { it.id }
private val rpcProxy by observableValue(NodeMonitorModel::proxyObservable) private val rpcProxy by observableValue(NodeMonitorModel::proxyObservable)
@Suppress("DEPRECATION")
val partiallyResolvedTransactions = collectedTransactions.map { val partiallyResolvedTransactions = collectedTransactions.map {
PartiallyResolvedTransaction.fromSignedTransaction(it, PartiallyResolvedTransaction.fromSignedTransaction(it,
it.inputs.map { stateRef -> it.inputs.map { stateRef ->

View File

@ -84,14 +84,12 @@ class FlowsExecutionModeTests : NodeBasedTest(listOf("net.corda.finance.contract
@Before @Before
fun setup() { fun setup() {
node = startNode(ALICE_NAME, rpcUsers = listOf(rpcUser)) node = startNode(ALICE_NAME, rpcUsers = listOf(rpcUser))
client = CordaRPCClient(node.internals.configuration.rpcOptions.address!!) client = CordaRPCClient(node.internals.configuration.rpcOptions.address)
} }
@Test @Test
fun `flows draining mode can be enabled and queried`() { fun `flows draining mode can be enabled and queried`() {
asALoggerUser { rpcOps -> asALoggerUser { rpcOps ->
val newValue = true val newValue = true
rpcOps.setFlowsDrainingModeEnabled(true) rpcOps.setFlowsDrainingModeEnabled(true)
@ -104,7 +102,6 @@ class FlowsExecutionModeTests : NodeBasedTest(listOf("net.corda.finance.contract
@Test @Test
fun `flows draining mode can be disabled and queried`() { fun `flows draining mode can be disabled and queried`() {
asALoggerUser { rpcOps -> asALoggerUser { rpcOps ->
rpcOps.setFlowsDrainingModeEnabled(true) rpcOps.setFlowsDrainingModeEnabled(true)
val newValue = false val newValue = false
@ -118,7 +115,6 @@ class FlowsExecutionModeTests : NodeBasedTest(listOf("net.corda.finance.contract
@Test @Test
fun `node starts with flows draining mode disabled`() { fun `node starts with flows draining mode disabled`() {
asALoggerUser { rpcOps -> asALoggerUser { rpcOps ->
val defaultStartingMode = rpcOps.isFlowsDrainingModeEnabled() val defaultStartingMode = rpcOps.isFlowsDrainingModeEnabled()
@ -127,14 +123,12 @@ class FlowsExecutionModeTests : NodeBasedTest(listOf("net.corda.finance.contract
} }
private fun login(username: String, password: String, externalTrace: Trace? = null, impersonatedActor: Actor? = null): CordaRPCConnection { private fun login(username: String, password: String, externalTrace: Trace? = null, impersonatedActor: Actor? = null): CordaRPCConnection {
return client.start(username, password, externalTrace, impersonatedActor) return client.start(username, password, externalTrace, impersonatedActor)
} }
private fun asALoggerUser(action: (CordaRPCOps) -> Unit) { private fun asALoggerUser(action: (CordaRPCOps) -> Unit) {
login(rpcUser.username, rpcUser.password).use { login(rpcUser.username, rpcUser.password).use {
action(it.proxy) action(it.proxy)
} }
} }
} }

View File

@ -90,6 +90,7 @@ task predeterminise(type: ProGuardTask) {
dontpreverify dontpreverify
dontobfuscate dontobfuscate
dontoptimize dontoptimize
dontnote
printseeds printseeds
verbose verbose
@ -133,6 +134,7 @@ task determinise(type: ProGuardTask) {
keepattributes '*' keepattributes '*'
keepdirectories keepdirectories
dontobfuscate dontobfuscate
dontnote
printseeds printseeds
verbose verbose
@ -178,7 +180,6 @@ task checkDeterminism(type: ProGuardTask, dependsOn: jdkTask) {
defaultTasks "determinise" defaultTasks "determinise"
determinise.finalizedBy metafix determinise.finalizedBy metafix
metafix.finalizedBy checkDeterminism metafix.finalizedBy checkDeterminism
assemble.dependsOn checkDeterminism
def deterministicJar = metafix.outputs.files.singleFile def deterministicJar = metafix.outputs.files.singleFile
artifacts { artifacts {

View File

@ -18,10 +18,10 @@ import java.util.*
* A unique identifier for a single state machine run, valid across node restarts. Note that a single run always * A unique identifier for a single state machine run, valid across node restarts. Note that a single run always
* has at least one flow, but that flow may also invoke sub-flows: they all share the same run id. * has at least one flow, but that flow may also invoke sub-flows: they all share the same run id.
*/ */
@DeleteForDJVM
@CordaSerializable @CordaSerializable
data class StateMachineRunId(val uuid: UUID) { data class StateMachineRunId(val uuid: UUID) {
companion object { companion object {
@DeleteForDJVM
fun createRandom(): StateMachineRunId = StateMachineRunId(UUID.randomUUID()) fun createRandom(): StateMachineRunId = StateMachineRunId(UUID.randomUUID())
} }

View File

@ -11,6 +11,7 @@
package net.corda.core.internal package net.corda.core.internal
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import net.corda.core.DeleteForDJVM
import net.corda.core.DoNotImplement import net.corda.core.DoNotImplement
import net.corda.core.concurrent.CordaFuture import net.corda.core.concurrent.CordaFuture
import net.corda.core.context.InvocationContext import net.corda.core.context.InvocationContext
@ -20,6 +21,7 @@ import net.corda.core.node.ServiceHub
import org.slf4j.Logger import org.slf4j.Logger
/** This is an internal interface that is implemented by code in the node module. You should look at [FlowLogic]. */ /** This is an internal interface that is implemented by code in the node module. You should look at [FlowLogic]. */
@DeleteForDJVM
@DoNotImplement @DoNotImplement
interface FlowStateMachine<FLOWRETURN> { interface FlowStateMachine<FLOWRETURN> {
@Suspendable @Suspendable

View File

@ -52,7 +52,7 @@ data class StateMachineInfo @JvmOverloads constructor(
* An object representing information about the initiator of the flow. Note that this field is * An object representing information about the initiator of the flow. Note that this field is
* superceded by the [invocationContext] property, which has more detail. * superceded by the [invocationContext] property, which has more detail.
*/ */
@Deprecated("There is more info available using 'context'") val initiator: FlowInitiator, @Deprecated("There is more info available using 'invocationContext'") val initiator: FlowInitiator,
/** A [DataFeed] of the current progress step as a human readable string, and updates to that string. */ /** A [DataFeed] of the current progress step as a human readable string, and updates to that string. */
val progressTrackerStepAndUpdates: DataFeed<String, String>?, val progressTrackerStepAndUpdates: DataFeed<String, String>?,
/** An [InvocationContext] describing why and by whom the flow was started. */ /** An [InvocationContext] describing why and by whom the flow was started. */

View File

@ -12,11 +12,15 @@ package net.corda.core.node.services
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import net.corda.core.DoNotImplement import net.corda.core.DoNotImplement
import net.corda.core.crypto.CompositeKey
import net.corda.core.crypto.DigitalSignature import net.corda.core.crypto.DigitalSignature
import net.corda.core.crypto.SignableData import net.corda.core.crypto.SignableData
import net.corda.core.crypto.TransactionSignature import net.corda.core.crypto.TransactionSignature
import net.corda.core.identity.PartyAndCertificate import net.corda.core.identity.PartyAndCertificate
import java.security.KeyPair
import java.security.PrivateKey
import java.security.PublicKey import java.security.PublicKey
import java.security.cert.X509Certificate
/** /**
* The KMS is responsible for storing and using private keys to sign things. An implementation of this may, for example, * The KMS is responsible for storing and using private keys to sign things. An implementation of this may, for example,

View File

@ -140,7 +140,7 @@ object MappedSchemaValidator {
fieldsFromOtherMappedSchema(schema) + methodsFromOtherMappedSchema(schema) fieldsFromOtherMappedSchema(schema) + methodsFromOtherMappedSchema(schema)
/** Returns true if [javax.persistence] annotation expect [javax.persistence.Transient] is found. */ /** Returns true if [javax.persistence] annotation expect [javax.persistence.Transient] is found. */
private inline fun hasJpaAnnotation(annotations: Array<Annotation>) = private fun hasJpaAnnotation(annotations: Array<Annotation>) =
annotations.any { annotation -> annotation.toString().startsWith("@javax.persistence.") && annotation !is javax.persistence.Transient } annotations.any { annotation -> annotation.toString().startsWith("@javax.persistence.") && annotation !is javax.persistence.Transient }
class SchemaCrossReferenceReport(private val schema: String, private val entity: String, private val referencedSchema: String, class SchemaCrossReferenceReport(private val schema: String, private val entity: String, private val referencedSchema: String,

View File

@ -58,7 +58,7 @@ class WireTransaction(componentGroups: List<ComponentGroup>, val privacySalt: Pr
@DeleteForDJVM @DeleteForDJVM
constructor(componentGroups: List<ComponentGroup>) : this(componentGroups, PrivacySalt()) constructor(componentGroups: List<ComponentGroup>) : this(componentGroups, PrivacySalt())
@Deprecated("Required only in some unit-tests and for backwards compatibility purposes.", ReplaceWith("WireTransaction(val componentGroups: List<ComponentGroup>, override val privacySalt: PrivacySalt)"), DeprecationLevel.WARNING) @Deprecated("Required only for backwards compatibility purposes.", ReplaceWith("WireTransaction(val componentGroups: List<ComponentGroup>, override val privacySalt: PrivacySalt)"), DeprecationLevel.WARNING)
@DeleteForDJVM @DeleteForDJVM
constructor(inputs: List<StateRef>, constructor(inputs: List<StateRef>,
attachments: List<SecureHash>, attachments: List<SecureHash>,

View File

@ -41,7 +41,8 @@ class ContractsDSLTests {
} }
@RunWith(Parameterized::class) @RunWith(Parameterized::class)
class RequireSingleCommandTests(private val testFunction: (Collection<CommandWithParties<CommandData>>) -> CommandWithParties<CommandData>, description: String) { class RequireSingleCommandTests(private val testFunction: (Collection<CommandWithParties<CommandData>>) -> CommandWithParties<CommandData>,
@Suppress("UNUSED_PARAMETER") description: String) {
companion object { companion object {
@JvmStatic @JvmStatic
@Parameterized.Parameters(name = "{1}") @Parameterized.Parameters(name = "{1}")
@ -74,7 +75,8 @@ class ContractsDSLTests {
} }
@RunWith(Parameterized::class) @RunWith(Parameterized::class)
class SelectWithSingleInputsTests(private val testFunction: (Collection<CommandWithParties<CommandData>>, PublicKey?, AbstractParty?) -> Iterable<CommandWithParties<CommandData>>, description: String) { class SelectWithSingleInputsTests(private val testFunction: (Collection<CommandWithParties<CommandData>>, PublicKey?, AbstractParty?) -> Iterable<CommandWithParties<CommandData>>,
@Suppress("UNUSED_PARAMETER") description: String) {
companion object { companion object {
@JvmStatic @JvmStatic
@Parameterized.Parameters(name = "{1}") @Parameterized.Parameters(name = "{1}")
@ -122,7 +124,8 @@ class ContractsDSLTests {
} }
@RunWith(Parameterized::class) @RunWith(Parameterized::class)
class SelectWithMultipleInputsTests(private val testFunction: (Collection<CommandWithParties<CommandData>>, Collection<PublicKey>?, Collection<Party>?) -> Iterable<CommandWithParties<CommandData>>, description: String) { class SelectWithMultipleInputsTests(private val testFunction: (Collection<CommandWithParties<CommandData>>, Collection<PublicKey>?, Collection<Party>?) -> Iterable<CommandWithParties<CommandData>>,
@Suppress("UNUSED_PARAMETER") description: String) {
companion object { companion object {
@JvmStatic @JvmStatic
@Parameterized.Parameters(name = "{1}") @Parameterized.Parameters(name = "{1}")

View File

@ -30,6 +30,7 @@ import net.corda.testing.dsl.LedgerDSL
import net.corda.testing.dsl.TestLedgerDSLInterpreter import net.corda.testing.dsl.TestLedgerDSLInterpreter
import net.corda.testing.dsl.TestTransactionDSLInterpreter import net.corda.testing.dsl.TestTransactionDSLInterpreter
import net.corda.testing.internal.TEST_TX_TIME import net.corda.testing.internal.TEST_TX_TIME
import net.corda.testing.internal.createWireTransaction
import net.corda.testing.internal.rigorousMock import net.corda.testing.internal.rigorousMock
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import net.corda.testing.node.ledger import net.corda.testing.node.ledger
@ -274,7 +275,7 @@ class PartialMerkleTreeTest {
timeWindow: TimeWindow? = null, timeWindow: TimeWindow? = null,
attachments: List<SecureHash> = emptyList() attachments: List<SecureHash> = emptyList()
): WireTransaction { ): WireTransaction {
return WireTransaction( return createWireTransaction(
inputs = testTx.inputs, inputs = testTx.inputs,
attachments = attachments, attachments = attachments,
outputs = testTx.outputs, outputs = testTx.outputs,

View File

@ -67,7 +67,7 @@ class AttachmentTests {
bobNode.registerInitiatedFlow(FetchAttachmentsResponse::class.java) bobNode.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
// Insert an attachment into node zero's store directly. // Insert an attachment into node zero's store directly.
val id = aliceNode.database.transaction { val id = aliceNode.database.transaction {
aliceNode.attachments.importAttachment(fakeAttachment().inputStream()) aliceNode.attachments.importAttachment(fakeAttachment().inputStream(), "test", null)
} }
// Get node one to run a flow to fetch it and insert it. // Get node one to run a flow to fetch it and insert it.
@ -120,7 +120,7 @@ class AttachmentTests {
val attachment = fakeAttachment() val attachment = fakeAttachment()
// Insert an attachment into node zero's store directly. // Insert an attachment into node zero's store directly.
val id = aliceNode.database.transaction { val id = aliceNode.database.transaction {
aliceNode.attachments.importAttachment(attachment.inputStream()) aliceNode.attachments.importAttachment(attachment.inputStream(), "test", null)
} }
// Corrupt its store. // Corrupt its store.

View File

@ -156,7 +156,7 @@ class ResolveTransactionsFlowTest {
} }
// TODO: this operation should not require an explicit transaction // TODO: this operation should not require an explicit transaction
val id = megaCorpNode.transaction { val id = megaCorpNode.transaction {
megaCorpNode.services.attachments.importAttachment(makeJar()) megaCorpNode.services.attachments.importAttachment(makeJar(), "test", null)
} }
val stx2 = makeTransactions(withAttachment = id).second val stx2 = makeTransactions(withAttachment = id).second
val p = TestFlow(stx2, megaCorp) val p = TestFlow(stx2, megaCorp)
@ -211,6 +211,7 @@ class ResolveTransactionsFlowTest {
} }
} }
@Suppress("unused")
@InitiatedBy(TestFlow::class) @InitiatedBy(TestFlow::class)
private class TestResponseFlow(val otherSideSession: FlowSession) : FlowLogic<Void?>() { private class TestResponseFlow(val otherSideSession: FlowSession) : FlowLogic<Void?>() {
@Suspendable @Suspendable

View File

@ -21,10 +21,10 @@ import rx.Observable
import java.util.* import java.util.*
class TopologicalSortTest { class TopologicalSortTest {
class DummyTransaction( class DummyTransaction constructor(
override val id: SecureHash, override val id: SecureHash,
override val inputs: List<StateRef>, override val inputs: List<StateRef>,
val numberOfOutputs: Int, @Suppress("CanBeParameter") private val numberOfOutputs: Int,
override val notary: Party override val notary: Party
) : CoreTransaction() { ) : CoreTransaction() {
override val outputs: List<TransactionState<ContractState>> = (1..numberOfOutputs).map { override val outputs: List<TransactionState<ContractState>> = (1..numberOfOutputs).map {
@ -78,7 +78,7 @@ class TopologicalSortTest {
} }
// Swap two random items // Swap two random items
transactions.combine(Generator.intRange(0, N - 1), Generator.intRange(0, N - 2)) { txs, i, j -> transactions.combine(Generator.intRange(0, N - 1), Generator.intRange(0, N - 2)) { txs, i, _ ->
val k = 0 // if (i == j) i + 1 else j val k = 0 // if (i == j) i + 1 else j
val tmp = txs[i] val tmp = txs[i]
txs[i] = txs[k] txs[i] = txs[k]
@ -94,7 +94,7 @@ class TopologicalSortTest {
} }
} }
fun checkTopologicallyOrdered(txs: List<SignedTransaction>) { private fun checkTopologicallyOrdered(txs: List<SignedTransaction>) {
val outputs = HashSet<StateRef>() val outputs = HashSet<StateRef>()
for (tx in txs) { for (tx in txs) {
if (!outputs.containsAll(tx.inputs)) { if (!outputs.containsAll(tx.inputs)) {

View File

@ -18,6 +18,7 @@ import net.corda.core.crypto.CompositeKey
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.core.* import net.corda.testing.core.*
import net.corda.testing.internal.createWireTransaction
import net.corda.testing.internal.rigorousMock import net.corda.testing.internal.rigorousMock
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -63,7 +64,7 @@ class TransactionTests {
val cpub = ck.public val cpub = ck.public
val c1 = CompositeKey.Builder().addKeys(apub, bpub).build(2) val c1 = CompositeKey.Builder().addKeys(apub, bpub).build(2)
val compKey = CompositeKey.Builder().addKeys(c1, cpub).build(1) val compKey = CompositeKey.Builder().addKeys(c1, cpub).build(1)
val wtx = WireTransaction( val wtx = createWireTransaction(
inputs = listOf(StateRef(SecureHash.randomSHA256(), 0)), inputs = listOf(StateRef(SecureHash.randomSHA256(), 0)),
attachments = emptyList(), attachments = emptyList(),
outputs = emptyList(), outputs = emptyList(),
@ -89,7 +90,7 @@ class TransactionTests {
@Test @Test
fun `signed transaction missing signatures`() { fun `signed transaction missing signatures`() {
val wtx = WireTransaction( val wtx = createWireTransaction(
inputs = listOf(StateRef(SecureHash.randomSHA256(), 0)), inputs = listOf(StateRef(SecureHash.randomSHA256(), 0)),
attachments = emptyList(), attachments = emptyList(),
outputs = emptyList(), outputs = emptyList(),
@ -129,8 +130,8 @@ class TransactionTests {
}, DummyContract.PROGRAM_ID)) }, DummyContract.PROGRAM_ID))
val id = SecureHash.randomSHA256() val id = SecureHash.randomSHA256()
val timeWindow: TimeWindow? = null val timeWindow: TimeWindow? = null
val privacySalt: PrivacySalt = PrivacySalt() val privacySalt = PrivacySalt()
val transaction: LedgerTransaction = LedgerTransaction( val transaction = LedgerTransaction(
inputs, inputs,
outputs, outputs,
commands, commands,
@ -147,7 +148,7 @@ class TransactionTests {
@Test @Test
fun `transaction cannot have duplicate inputs`() { fun `transaction cannot have duplicate inputs`() {
val stateRef = StateRef(SecureHash.randomSHA256(), 0) val stateRef = StateRef(SecureHash.randomSHA256(), 0)
fun buildTransaction() = WireTransaction( fun buildTransaction() = createWireTransaction(
inputs = listOf(stateRef, stateRef), inputs = listOf(stateRef, stateRef),
attachments = emptyList(), attachments = emptyList(),
outputs = emptyList(), outputs = emptyList(),
@ -170,7 +171,7 @@ class TransactionTests {
val attachments = emptyList<Attachment>() val attachments = emptyList<Attachment>()
val id = SecureHash.randomSHA256() val id = SecureHash.randomSHA256()
val timeWindow: TimeWindow? = null val timeWindow: TimeWindow? = null
val privacySalt: PrivacySalt = PrivacySalt() val privacySalt = PrivacySalt()
fun buildTransaction() = LedgerTransaction( fun buildTransaction() = LedgerTransaction(
inputs, inputs,
outputs, outputs,
@ -188,7 +189,7 @@ class TransactionTests {
@Test @Test
fun `transactions with identical contents must have different ids`() { fun `transactions with identical contents must have different ids`() {
val outputState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DummyContract.PROGRAM_ID, DUMMY_NOTARY) val outputState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DummyContract.PROGRAM_ID, DUMMY_NOTARY)
fun buildTransaction() = WireTransaction( fun buildTransaction() = createWireTransaction(
inputs = emptyList(), inputs = emptyList(),
attachments = emptyList(), attachments = emptyList(),
outputs = listOf(outputState), outputs = listOf(outputState),

View File

@ -136,7 +136,7 @@ class IntegrationTestingTutorial : IntegrationTest() {
// move to Bob // move to Bob
parallel( parallel(
(1..numberOfStates).map { i -> (1..numberOfStates).map { i ->
expect(match = { it.moved() == i * 100 }) { update: Vault.Update<Cash.State> -> expect(match = { it.moved() == i * 100 }) { _: Vault.Update<Cash.State> ->
} }
} }
), ),
@ -154,7 +154,7 @@ class IntegrationTestingTutorial : IntegrationTest() {
} }
} }
fun Vault.Update<Cash.State>.moved(): Int { private fun Vault.Update<Cash.State>.moved(): Int {
val consumedSum = consumed.sumBy { it.state.data.amount.quantity.toInt() } val consumedSum = consumed.sumBy { it.state.data.amount.quantity.toInt() }
val producedSum = produced.sumBy { it.state.data.amount.quantity.toInt() } val producedSum = produced.sumBy { it.state.data.amount.quantity.toInt() }
return consumedSum - producedSum return consumedSum - producedSum

View File

@ -40,6 +40,7 @@ import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
@ -134,7 +135,7 @@ public class FlowCookbookJava {
// We retrieve a notary from the network map. // We retrieve a notary from the network map.
// DOCSTART 01 // DOCSTART 01
CordaX500Name notaryName = new CordaX500Name("Notary Service", "London", "GB"); CordaX500Name notaryName = new CordaX500Name("Notary Service", "London", "GB");
Party specificNotary = getServiceHub().getNetworkMapCache().getNotary(notaryName); Party specificNotary = Objects.requireNonNull(getServiceHub().getNetworkMapCache().getNotary(notaryName));
// Alternatively, we can pick an arbitrary notary from the notary // Alternatively, we can pick an arbitrary notary from the notary
// list. However, it is always preferable to specify the notary // list. However, it is always preferable to specify the notary
// explicitly, as the notary list might change when new notaries are // explicitly, as the notary list might change when new notaries are
@ -378,7 +379,7 @@ public class FlowCookbookJava {
// Or we can add the output state as a ``TransactionState``, which already specifies // Or we can add the output state as a ``TransactionState``, which already specifies
// the output's contract and notary. // the output's contract and notary.
// DOCSTART 51 // DOCSTART 51
TransactionState txState = new TransactionState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary); TransactionState txState = new TransactionState<>(ourOutputState, DummyContract.PROGRAM_ID, specificNotary);
// DOCEND 51 // DOCEND 51
// Commands can be added as ``Command``s. // Commands can be added as ``Command``s.
@ -662,7 +663,7 @@ public class FlowCookbookJava {
} }
@Override @Override
protected void checkTransaction(SignedTransaction stx) { protected void checkTransaction(@NotNull SignedTransaction stx) {
requireThat(require -> { requireThat(require -> {
// Any additional checking we see fit... // Any additional checking we see fit...
DummyState outputState = (DummyState) stx.getTx().getOutputs().get(0).getData(); DummyState outputState = (DummyState) stx.getTx().getOutputs().get(0).getData();

View File

@ -13,6 +13,7 @@ package net.corda.docs.java.tutorial.contract;
import net.corda.core.contracts.*; import net.corda.core.contracts.*;
import net.corda.core.transactions.LedgerTransaction; import net.corda.core.transactions.LedgerTransaction;
import net.corda.core.transactions.LedgerTransaction.InOutGroup; import net.corda.core.transactions.LedgerTransaction.InOutGroup;
import org.jetbrains.annotations.NotNull;
import java.time.Instant; import java.time.Instant;
import java.util.Currency; import java.util.Currency;
@ -22,6 +23,7 @@ import static net.corda.core.contracts.ContractsDSL.requireSingleCommand;
import static net.corda.core.contracts.ContractsDSL.requireThat; import static net.corda.core.contracts.ContractsDSL.requireThat;
import static net.corda.finance.utils.StateSumming.sumCashBy; import static net.corda.finance.utils.StateSumming.sumCashBy;
@SuppressWarnings("unused")
public class CommercialPaper implements Contract { public class CommercialPaper implements Contract {
// DOCSTART 1 // DOCSTART 1
public static final String IOU_CONTRACT_ID = "com.example.contract.IOUContract"; public static final String IOU_CONTRACT_ID = "com.example.contract.IOUContract";
@ -29,7 +31,7 @@ public class CommercialPaper implements Contract {
// DOCSTART 3 // DOCSTART 3
@Override @Override
public void verify(LedgerTransaction tx) { public void verify(@NotNull LedgerTransaction tx) {
List<InOutGroup<State, State>> groups = tx.groupStates(State.class, State::withoutOwner); List<InOutGroup<State, State>> groups = tx.groupStates(State.class, State::withoutOwner);
CommandWithParties<Commands> cmd = requireSingleCommand(tx.getCommands(), Commands.class); CommandWithParties<Commands> cmd = requireSingleCommand(tx.getCommands(), Commands.class);
// DOCEND 3 // DOCEND 3
@ -37,7 +39,7 @@ public class CommercialPaper implements Contract {
// DOCSTART 4 // DOCSTART 4
TimeWindow timeWindow = tx.getTimeWindow(); TimeWindow timeWindow = tx.getTimeWindow();
for (InOutGroup group : groups) { for (InOutGroup<State, State> group : groups) {
List<State> inputs = group.getInputs(); List<State> inputs = group.getInputs();
List<State> outputs = group.getOutputs(); List<State> outputs = group.getOutputs();
@ -57,6 +59,7 @@ public class CommercialPaper implements Contract {
Amount<Issued<Currency>> received = sumCashBy(tx.getOutputStates(), input.getOwner()); Amount<Issued<Currency>> received = sumCashBy(tx.getOutputStates(), input.getOwner());
if (timeWindow == null) throw new IllegalArgumentException("Redemptions must be timestamped"); if (timeWindow == null) throw new IllegalArgumentException("Redemptions must be timestamped");
Instant time = timeWindow.getFromTime(); Instant time = timeWindow.getFromTime();
if (time == null) throw new IllegalArgumentException("Redemptions must have a from time");
requireThat(require -> { requireThat(require -> {
require.using("the paper must have matured", time.isAfter(input.getMaturityDate())); require.using("the paper must have matured", time.isAfter(input.getMaturityDate()));
require.using("the received amount equals the face value", received == input.getFaceValue()); require.using("the received amount equals the face value", received == input.getFaceValue());
@ -68,6 +71,7 @@ public class CommercialPaper implements Contract {
State output = outputs.get(0); State output = outputs.get(0);
if (timeWindow == null) throw new IllegalArgumentException("Issuances must have a time-window"); if (timeWindow == null) throw new IllegalArgumentException("Issuances must have a time-window");
Instant time = timeWindow.getUntilTime(); Instant time = timeWindow.getUntilTime();
if (time == null) throw new IllegalArgumentException("Issuances must have an until time");
requireThat(require -> { requireThat(require -> {
// Don't allow people to issue commercial paper under other entities identities. // Don't allow people to issue commercial paper under other entities identities.
require.using("output states are issued by a command signer", cmd.getSigners().contains(output.getIssuance().getParty().getOwningKey())); require.using("output states are issued by a command signer", cmd.getSigners().contains(output.getIssuance().getParty().getOwningKey()));

View File

@ -50,6 +50,7 @@ enum class PrintOrVisualise {
Visualise Visualise
} }
@Suppress("DEPRECATION")
fun main(args: Array<String>) { fun main(args: Array<String>) {
require(args.isNotEmpty()) { "Usage: <binary> [Print|Visualise]" } require(args.isNotEmpty()) { "Usage: <binary> [Print|Visualise]" }
val printOrVisualise = PrintOrVisualise.valueOf(args[0]) val printOrVisualise = PrintOrVisualise.valueOf(args[0])
@ -109,6 +110,7 @@ fun main(args: Array<String>) {
} }
} }
// END 5 // END 5
Unit
} }
} }

View File

@ -8,7 +8,7 @@
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
@file:Suppress("UNUSED_VARIABLE", "unused") @file:Suppress("UNUSED_VARIABLE", "unused", "DEPRECATION")
package net.corda.docs package net.corda.docs

View File

@ -8,6 +8,8 @@
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
@file:Suppress("UNUSED_VARIABLE")
package net.corda.docs.tutorial.tearoffs package net.corda.docs.tutorial.tearoffs
import net.corda.core.contracts.Command import net.corda.core.contracts.Command
@ -52,4 +54,4 @@ fun main(args: Array<String>) {
} catch (e: FilteredTransactionVerificationException) { } catch (e: FilteredTransactionVerificationException) {
throw MerkleTreeException("Rate Fix Oracle: Couldn't verify partial Merkle tree.") throw MerkleTreeException("Rate Fix Oracle: Couldn't verify partial Merkle tree.")
} }
} }

View File

@ -43,6 +43,27 @@ Optionally run the node's webserver as well by opening a terminal window in the
.. warning:: The node webserver is for testing purposes only and will be removed soon. .. warning:: The node webserver is for testing purposes only and will be removed soon.
Command-line options
~~~~~~~~~~~~~~~~~~~~
The node can optionally be started with the following command-line options:
* ``--base-directory``: The node working directory where all the files are kept (default: ``.``)
* ``--bootstrap-raft-cluster``: Bootstraps Raft cluster. The node forms a single node cluster (ignoring otherwise configured peer
addresses), acting as a seed for other nodes to join the cluster
* ``--config-file``: The path to the config file (default: ``node.conf``)
* ``--help``
* ``--initial-registration``: Start initial node registration with Corda network to obtain certificate from the permissioning
server
* ``--just-generate-node-info``: Perform the node start-up task necessary to generate its nodeInfo, save it to disk, then
quit
* ``--log-to-console``: If set, prints logging to the console as well as to a file
* ``--logging-level <[ERROR,WARN,INFO, DEBUG,TRACE]>``: Enable logging at this level and higher (default: INFO)
* ``--network-root-truststore``: Network root trust store obtained from network operator
* ``--network-root-truststore-password``: Network root trust store password obtained from network operator
* ``--no-local-shell``: Do not start the embedded shell locally
* ``--sshd``: Enables SSHD server for node administration
* ``--version``: Print the version and exit
Enabling remote debugging Enabling remote debugging
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
To enable remote debugging of the node, run the following from the terminal window: To enable remote debugging of the node, run the following from the terminal window:
@ -61,8 +82,11 @@ This command line will start the node with JMX metrics accessible via HTTP on po
See :ref:`Monitoring your node <jolokia_ref>` for further details. See :ref:`Monitoring your node <jolokia_ref>` for further details.
Starting all nodes at once from the command line (native) Starting all nodes at once from the command line
--------------------------------------------------------- ------------------------------------------------
Native
~~~~~~
If you created your nodes using ``deployNodes``, a ``runnodes`` shell script (or batch file on Windows) will have been If you created your nodes using ``deployNodes``, a ``runnodes`` shell script (or batch file on Windows) will have been
generated to allow you to quickly start up all nodes and their webservers. ``runnodes`` should only be used for testing generated to allow you to quickly start up all nodes and their webservers. ``runnodes`` should only be used for testing
purposes. purposes.
@ -79,8 +103,8 @@ If you receive an ``OutOfMemoryError`` exception when interacting with the nodes
Java heap memory available to them, which you can do when running them individually. See Java heap memory available to them, which you can do when running them individually. See
:ref:`starting-an-individual-corda-node`. :ref:`starting-an-individual-corda-node`.
Starting all nodes at once from the command line (docker-compose) docker-compose
----------------------------------------------------------------- ~~~~~~~~~~~~~~
If you created your nodes using ``Dockerform``, the ``docker-compose.yml`` file and corresponding ``Dockerfile`` for If you created your nodes using ``Dockerform``, the ``docker-compose.yml`` file and corresponding ``Dockerfile`` for
nodes has been created and configured appropriately. Navigate to ``build/nodes`` directory and run ``docker-compose up`` nodes has been created and configured appropriately. Navigate to ``build/nodes`` directory and run ``docker-compose up``
command. This will startup nodes inside new, internal network. command. This will startup nodes inside new, internal network.

View File

@ -411,32 +411,38 @@ For more information on the client RPC interface and how to build an RPC client
Running nodes across machines Running nodes across machines
----------------------------- -----------------------------
The nodes can be split across different machines and configured to communicate across the network. The nodes can be configured to communicate as a network even when distributed across several machines:
After deploying the nodes, navigate to the build folder (``kotlin-source/build/nodes``) and for each node that needs to * Deploy the nodes as usual:
be moved to another machine open its config file and change the Artemis messaging address to the IP address of the machine
where the node will run (e.g. ``p2pAddress="10.18.0.166:10007"``).
These changes require new node-info files to be distributed amongst the nodes. Use the network bootstrapper tool * Unix/Mac OSX: ``./gradlew deployNodes``
(see :doc:`network-bootstrapper` for more information on this and how to built it) to update the files and have * Windows: ``gradlew.bat deployNodes``
them distributed locally.
``java -jar network-bootstrapper.jar kotlin-source/build/nodes`` * Navigate to the build folder (``kotlin-source/build/nodes``)
* For each node, open its ``node.conf`` file and change ``localhost`` in its ``p2pAddress`` to the IP address of the machine
where the node will be run (e.g. ``p2pAddress="10.18.0.166:10007"``)
* These changes require new node-info files to be distributed amongst the nodes. Use the network bootstrapper tool
(see :doc:`network-bootstrapper`) to update the files and have them distributed locally:
Once that's done move the node folders to their designated machines (e.g. using a USB key). It is important that none of the ``java -jar network-bootstrapper.jar kotlin-source/build/nodes``
nodes - including the notary - end up on more than one machine. Each computer should also have a copy of ``runnodes``
and ``runnodes.bat``.
For example, you may end up with the following layout: * Move the node folders to their individual machines (e.g. using a USB key). It is important that none of the
nodes - including the notary - end up on more than one machine. Each computer should also have a copy of ``runnodes``
and ``runnodes.bat``.
* Machine 1: ``Notary``, ``PartyA``, ``runnodes``, ``runnodes.bat`` For example, you may end up with the following layout:
* Machine 2: ``PartyB``, ``PartyC``, ``runnodes``, ``runnodes.bat``
After starting each node, the nodes will be able to see one another and agree IOUs among themselves. * Machine 1: ``Notary``, ``PartyA``, ``runnodes``, ``runnodes.bat``
* Machine 2: ``PartyB``, ``PartyC``, ``runnodes``, ``runnodes.bat``
.. note:: If you are using H2 and wish to use the same ``h2port`` value for all the nodes, then only assign them that * After starting each node, the nodes will be able to see one another and agree IOUs among themselves
value after the nodes have been moved to their machines. The initial bootstrapping process requires access to the nodes'
databases and if they share the same H2 port then the process will fail. .. warning:: The bootstrapper must be run **after** the ``node.conf`` files have been modified, but **before** the nodes
are distributed across machines. Otherwise, the nodes will not be able to communicate.
.. note:: If you are using H2 and wish to use the same ``h2port`` value for two or more nodes, you must only assign them that
value after the nodes have been moved to their individual machines. The initial bootstrapping process requires access to the
nodes' databases and if two nodes share the same H2 port, the process will fail.
Testing and debugging Testing and debugging
--------------------- ---------------------

View File

@ -1,41 +1,23 @@
buildscript { buildscript {
ext.kotlin_version = '1.2.40'
repositories { repositories {
mavenCentral()
jcenter() jcenter()
} }
dependencies { dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "com.github.jengelman.gradle.plugins:shadow:$shadow_version"
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.3'
} }
} }
plugins { apply plugin: 'kotlin'
id "org.jetbrains.kotlin.jvm" apply plugin: 'application'
id 'com.github.johnrengelman.shadow' version '2.0.3' apply plugin: 'com.github.johnrengelman.shadow'
id 'java'
id 'application'
}
repositories {
mavenCentral()
}
dependencies { dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
compile group: 'info.picocli', name: 'picocli', version: '3.0.1' compile "info.picocli:picocli:3.0.1"
testCompile group: 'junit', name: 'junit', version: '4.12' testCompile "junit:junit:$junit_version"
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
} }
mainClassName = "net.corda.avalanche.MainKt" mainClassName = "net.corda.avalanche.MainKt"
shadowJar { shadowJar {
baseName = "avalanche" baseName = "avalanche"

View File

@ -8,37 +8,18 @@
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
buildscript { ext {
ext.commonsio_version = '2.6' commonsio_version = '2.6'
ext.commonslogging_version = '1.2' cucumber_version = '1.2.5'
ext.cucumber_version = '1.2.5' crash_version = 'cce5a00f114343c1145c1d7756e1dd6df3ea984e'
ext.crash_version = 'cce5a00f114343c1145c1d7756e1dd6df3ea984e' docker_client_version = '8.11.0'
ext.docker_client_version = '8.11.0'
repositories {
maven {
jcenter()
url 'https://jitpack.io'
}
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
} }
group 'net.corda.behave' group 'net.corda.behave'
apply plugin: 'java'
apply plugin: 'kotlin' apply plugin: 'kotlin'
apply plugin: 'net.corda.plugins.publish-utils' apply plugin: 'net.corda.plugins.publish-utils'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
sourceSets { sourceSets {
behave { behave {
kotlin { kotlin {
@ -89,6 +70,7 @@ dependencies {
compile "org.slf4j:log4j-over-slf4j:$slf4j_version" compile "org.slf4j:log4j-over-slf4j:$slf4j_version"
compile "org.slf4j:jul-to-slf4j:$slf4j_version" compile "org.slf4j:jul-to-slf4j:$slf4j_version"
compile "org.slf4j:jcl-over-slf4j:$slf4j_version"
compile "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version" compile "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
compile "org.apache.logging.log4j:log4j-core:$log4j_version" compile "org.apache.logging.log4j:log4j-core:$log4j_version"
@ -96,10 +78,9 @@ dependencies {
compile "net.sf.jopt-simple:jopt-simple:$jopt_simple_version" compile "net.sf.jopt-simple:jopt-simple:$jopt_simple_version"
// FastClasspathScanner: classpath scanning // FastClasspathScanner: classpath scanning
compile 'io.github.lukehutch:fast-classpath-scanner:2.12.3' compile "io.github.lukehutch:fast-classpath-scanner:$fast_classpath_scanner_version"
compile "commons-io:commons-io:$commonsio_version" compile "commons-io:commons-io:$commonsio_version"
compile "commons-logging:commons-logging:$commonslogging_version"
compile "com.spotify:docker-client:$docker_client_version" compile "com.spotify:docker-client:$docker_client_version"
compile "io.reactivex:rxjava:$rxjava_version" compile "io.reactivex:rxjava:$rxjava_version"
@ -122,14 +103,6 @@ dependencies {
behaveCompile "info.cukes:cucumber-picocontainer:$cucumber_version" behaveCompile "info.cukes:cucumber-picocontainer:$cucumber_version"
} }
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
test { test {
testLogging.showStandardStreams = true testLogging.showStandardStreams = true
} }

View File

@ -11,19 +11,19 @@
package net.corda.behave.network package net.corda.behave.network
import net.corda.behave.database.DatabaseType import net.corda.behave.database.DatabaseType
import net.corda.behave.file.* import net.corda.behave.file.LogSource
import net.corda.behave.monitoring.PatternWatch import net.corda.behave.file.currentDirectory
import net.corda.behave.file.stagingRoot
import net.corda.behave.file.tmpDirectory
import net.corda.behave.node.Distribution import net.corda.behave.node.Distribution
import net.corda.behave.node.Node import net.corda.behave.node.Node
import net.corda.behave.node.configuration.NotaryType import net.corda.behave.node.configuration.NotaryType
import net.corda.behave.process.Command import net.corda.behave.process.Command
import net.corda.behave.process.JarCommand import net.corda.behave.process.JarCommand
import net.corda.core.CordaException import net.corda.core.CordaException
import net.corda.core.CordaRuntimeException
import net.corda.core.internal.* import net.corda.core.internal.*
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.minutes import net.corda.core.utilities.minutes
import net.corda.core.utilities.seconds
import java.io.Closeable import java.io.Closeable
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
@ -147,116 +147,8 @@ class Network private constructor(
* using Local signing and "Auto Approval" mode * using Local signing and "Auto Approval" mode
*/ */
private fun bootstrapDoorman() { private fun bootstrapDoorman() {
// TODO: rework how we use the Doorman/NMS (now these are a separate product / distribution) // TODO: rework how we use the Doorman/NMS (now these are a separate product / distribution)
signalFailure("Bootstrapping a Corda Enterprise network using the Doorman is no longer supported; exiting ...") signalFailure("Bootstrapping a Corda Enterprise network using the Doorman is no longer supported; exiting ...")
return
// WARNING!! Need to use the correct bootstrapper
// only if using OS nodes (need to choose the latest version)
val r3node = nodes.values
.find { it.config.distribution.type == Distribution.Type.CORDA_ENTERPRISE } ?: throw CordaRuntimeException("Missing R3 distribution node")
val distribution = r3node.config.distribution
// Copy over reference configuration files used in bootstrapping
val source = doormanConfigDirectory
val doormanTargetDirectory = targetDirectory / "doorman"
source.toFile().copyRecursively(doormanTargetDirectory.toFile(), true)
// Use master version of Bootstrapper
val doormanJar = Distribution.R3_MASTER.doormanJar
log.info("DoormanJar URL: $doormanJar\n")
// 1. Create key stores for local signer
// java -jar doorman-<version>.jar --mode ROOT_KEYGEN
log.info("Doorman target directory: $doormanTargetDirectory")
runCommand(JarCommand(doormanJar,
arrayOf("--config-file", "$doormanConfigDirectory/node-init.conf", "--mode", "ROOT_KEYGEN", "--trust-store-password", "password"),
doormanTargetDirectory, timeout))
// java -jar doorman-<version>.jar --mode CA_KEYGEN
runCommand(JarCommand(doormanJar,
arrayOf("--config-file", "$doormanConfigDirectory/node-init.conf", "--mode", "CA_KEYGEN"),
doormanTargetDirectory, timeout))
// 2. Start the doorman service for notary registration
doormanNMS = JarCommand(doormanJar,
arrayOf("--config-file", "$doormanConfigDirectory/node-init.conf"),
doormanTargetDirectory, timeout)
val doormanCommand = runCommand(doormanNMS, noWait = true)
log.info("Waiting for DoormanNMS to be alive")
PatternWatch(doormanCommand.output, "Network management web services started on").await(30.seconds)
log.info("DoormanNMS up and running")
// Notary Nodes
val notaryNodes = nodes.values.filter { it.config.notary.notaryType != NotaryType.NONE }
notaryNodes.forEach { notaryNode ->
val notaryTargetDirectory = targetDirectory / notaryNode.config.name
log.info("Notary target directory: $notaryTargetDirectory")
// 3. Create notary node and register with the doorman
runCommand(JarCommand(distribution.cordaJar,
arrayOf("--initial-registration",
"--base-directory", "$notaryTargetDirectory",
"--network-root-truststore", "../doorman/certificates/distribute-nodes/network-root-truststore.jks",
"--network-root-truststore-password", "password"),
notaryTargetDirectory, timeout))
// 4. Generate node info files for notary nodes
runCommand(JarCommand(distribution.cordaJar,
arrayOf("--just-generate-node-info",
"--base-directory", "$notaryTargetDirectory"),
notaryTargetDirectory, timeout))
// cp (or ln -s) nodeInfo* notary-node-info
val nodeInfoFile = notaryTargetDirectory.toFile().listFiles { _, filename -> filename.matches("nodeInfo-.+".toRegex()) }.firstOrNull() ?: throw CordaRuntimeException("Missing notary nodeInfo file")
Files.copy(nodeInfoFile.toPath(), (notaryTargetDirectory / "notary-node-info"), StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING)
}
// exit Doorman process
doormanCommand.interrupt()
doormanCommand.waitFor()
// 5. Add notary identities to the network parameters
// 6. Load initial network parameters file for network map service
val networkParamsConfig = if (notaryNodes.isEmpty()) "network-parameters-without-notary.conf" else "network-parameters.conf"
val updateNetworkParams = JarCommand(doormanJar,
arrayOf("--config-file", "$doormanTargetDirectory/node.conf", "--set-network-parameters", "$doormanTargetDirectory/$networkParamsConfig"),
doormanTargetDirectory, timeout)
runCommand(updateNetworkParams)
// 7. Start a fully configured Doorman / NMS
doormanNMS = JarCommand(doormanJar,
arrayOf("--config-file", "$doormanConfigDirectory/node.conf"),
doormanTargetDirectory, timeout)
val doormanNMSCommand = runCommand(doormanNMS, noWait = true)
log.info("Waiting for DoormanNMS to be alive")
PatternWatch(doormanNMSCommand.output, "Network management web services started on").await(30.seconds)
log.info("DoormanNMS up and running")
// 8. Register other participant nodes
val partyNodes = nodes.values.filter { it.config.notary.notaryType == NotaryType.NONE }
partyNodes.forEach { partyNode ->
val partyTargetDirectory = targetDirectory / partyNode.config.name
log.info("Party target directory: $partyTargetDirectory")
// 3. Create notary node and register with the doorman
runCommand(JarCommand(distribution.cordaJar,
arrayOf("--initial-registration",
"--network-root-truststore", "../doorman/certificates/distribute-nodes/network-root-truststore.jks",
"--network-root-truststore-password", "password",
"--base-directory", "$partyTargetDirectory"),
partyTargetDirectory, timeout))
}
isDoormanNMSRunning = true
} }
private fun runCommand(command: Command, noWait: Boolean = false): Command { private fun runCommand(command: Command, noWait: Boolean = false): Command {
@ -446,7 +338,7 @@ class Network private constructor(
val rpcProxyPortNo = node.config.nodeInterface.rpcProxy val rpcProxyPortNo = node.config.nodeInterface.rpcProxy
val pid = Files.lines(tmpDirectory / "rpcProxy-pid-$rpcProxyPortNo").findFirst().get() val pid = Files.lines(tmpDirectory / "rpcProxy-pid-$rpcProxyPortNo").findFirst().get()
// TODO: consider generic implementation to support non *nix platforms // TODO: consider generic implementation to support non *nix platforms
Command(listOf("kill", "-9", "$pid")).run() Command(listOf("kill", "-9", pid)).run()
(tmpDirectory / "rpcProxy-pid-$rpcProxyPortNo").deleteIfExists() (tmpDirectory / "rpcProxy-pid-$rpcProxyPortNo").deleteIfExists()
} }
catch (e: Exception) { catch (e: Exception) {

View File

@ -14,7 +14,6 @@ import net.corda.behave.database.DatabaseConnection
import net.corda.behave.database.DatabaseType import net.corda.behave.database.DatabaseType
import net.corda.behave.file.LogSource import net.corda.behave.file.LogSource
import net.corda.behave.file.currentDirectory import net.corda.behave.file.currentDirectory
import net.corda.behave.file.stagingRoot
import net.corda.behave.monitoring.PatternWatch import net.corda.behave.monitoring.PatternWatch
import net.corda.behave.node.configuration.* import net.corda.behave.node.configuration.*
import net.corda.behave.process.JarCommand import net.corda.behave.process.JarCommand
@ -31,8 +30,8 @@ import net.corda.core.internal.div
import net.corda.core.internal.exists import net.corda.core.internal.exists
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.minutes
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.minutes
import net.corda.core.utilities.seconds import net.corda.core.utilities.seconds
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import java.net.InetAddress import java.net.InetAddress
@ -45,7 +44,7 @@ import java.util.concurrent.CountDownLatch
*/ */
class Node( class Node(
val config: Configuration, val config: Configuration,
val rootDirectory: Path = currentDirectory, private val rootDirectory: Path = currentDirectory,
private val settings: ServiceSettings = ServiceSettings(), private val settings: ServiceSettings = ServiceSettings(),
val rpcProxy: Boolean = false, val rpcProxy: Boolean = false,
val networkType: Distribution.Type val networkType: Distribution.Type
@ -77,18 +76,6 @@ class Node(
private var haveDependenciesStopped = false private var haveDependenciesStopped = false
fun describe(): String {
val network = config.nodeInterface
val database = config.database
return """
|Node Information: ${config.name}
| - P2P: ${network.host}:${network.p2pPort}
| - RPC: ${network.host}:${network.rpcPort}
| - SSH: ${network.host}:${network.sshPort}
| - DB: ${network.host}:${database.port} (${database.type})
|""".trimMargin()
}
fun configure() { fun configure() {
if (isConfigured) { return } if (isConfigured) { return }
isConfigured = true isConfigured = true
@ -164,10 +151,6 @@ class Node(
} }
} }
val nodeInfoGenerationOutput: LogSource by lazy {
LogSource(logDirectory, "node-info-gen.log")
}
val logOutput: LogSource by lazy { val logOutput: LogSource by lazy {
val hostname = InetAddress.getLocalHost().hostName val hostname = InetAddress.getLocalHost().hostName
LogSource(logDirectory, "node-$hostname.*.log") LogSource(logDirectory, "node-$hostname.*.log")
@ -387,10 +370,11 @@ class Node(
val name = name ?: error("Node name not set") val name = name ?: error("Node name not set")
val directory = directory ?: error("Runtime directory not set") val directory = directory ?: error("Runtime directory not set")
// TODO: rework how we use the Doorman/NMS (now these are a separate product / distribution) // TODO: rework how we use the Doorman/NMS (now these are a separate product / distribution)
val compatibilityZoneURL = null val compatibilityZoneURL = if (networkType == Distribution.Type.CORDA_ENTERPRISE && System.getProperty("USE_NETWORK_SERVICES") != null) {
if (networkType == Distribution.Type.CORDA_ENTERPRISE && System.getProperty("USE_NETWORK_SERVICES") != null) "http://localhost:1300" // TODO: add additional USE_NETWORK_SERVICES_URL to specify location of existing operational environment to use.
"http://localhost:1300" // TODO: add additional USE_NETWORK_SERVICES_URL to specify location of existing operational environment to use. } else {
else null null
}
return Node( return Node(
Configuration( Configuration(
name, name,

View File

@ -72,7 +72,7 @@ class ScenarioState {
inline fun <T> withNetwork(action: ScenarioState.() -> T): T { inline fun <T> withNetwork(action: ScenarioState.() -> T): T {
ensureNetworkIsRunning() ensureNetworkIsRunning()
return action() return this.action()
} }
inline fun <T> withClient(nodeName: String, crossinline action: (CordaRPCOps) -> T): T { inline fun <T> withClient(nodeName: String, crossinline action: (CordaRPCOps) -> T): T {

View File

@ -10,34 +10,33 @@
package net.corda.behave.scenarios.helpers package net.corda.behave.scenarios.helpers
import net.corda.behave.logging.getLogger
import net.corda.behave.scenarios.ScenarioState import net.corda.behave.scenarios.ScenarioState
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import org.slf4j.Logger
import org.slf4j.LoggerFactory
abstract class Substeps(protected val state: ScenarioState) { abstract class Substeps(protected val state: ScenarioState) {
protected val log: Logger = LoggerFactory.getLogger(javaClass)
protected val log = getLogger<Substeps>() protected fun withNetwork(action: ScenarioState.() -> Unit) = state.withNetwork(action)
protected fun withNetwork(action: ScenarioState.() -> Unit) =
state.withNetwork(action)
protected fun <T> withClient(nodeName: String, action: ScenarioState.(CordaRPCOps) -> T): T { protected fun <T> withClient(nodeName: String, action: ScenarioState.(CordaRPCOps) -> T): T {
return state.withClient(nodeName, { return state.withClient(nodeName) {
return@withClient try { try {
action(state, it) action(state, it)
} catch (ex: Exception) { } catch (ex: Exception) {
state.error<T>(ex.message ?: "Failed to execute RPC call") state.error(ex.message ?: "Failed to execute RPC call")
} }
}) }
} }
protected fun <T> withClientProxy(nodeName: String, action: ScenarioState.(CordaRPCOps) -> T): T { protected fun <T> withClientProxy(nodeName: String, action: ScenarioState.(CordaRPCOps) -> T): T {
return state.withClientProxy(nodeName, { return state.withClientProxy(nodeName) {
return@withClientProxy try { try {
action(state, it) action(state, it)
} catch (ex: Exception) { } catch (ex: Exception) {
state.error<T>(ex.message ?: "Failed to execute HTTP call") state.error(ex.message ?: "Failed to execute HTTP call")
} }
}) }
} }
} }

View File

@ -15,7 +15,6 @@ import org.junit.Test
import rx.observers.TestSubscriber import rx.observers.TestSubscriber
class CommandTests { class CommandTests {
@Test @Test
fun `successful command returns zero`() { fun `successful command returns zero`() {
val exitCode = Command(listOf("ls", "/")).run() val exitCode = Command(listOf("ls", "/")).run()

View File

@ -34,7 +34,7 @@ dependencies {
compile project(':finance') compile project(':finance')
// ObjectWeb Asm: a library for synthesising and working with JVM bytecode. // ObjectWeb Asm: a library for synthesising and working with JVM bytecode.
compile "org.ow2.asm:asm:5.0.4" compile "org.ow2.asm:asm:$asm_version"
compile "com.google.guava:guava:$guava_version" compile "com.google.guava:guava:$guava_version"

View File

@ -34,7 +34,6 @@ repositories {
} }
apply plugin: 'kotlin' apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'
apply plugin: 'idea' apply plugin: 'idea'
description 'A javaagent to allow hooking into Kryo' description 'A javaagent to allow hooking into Kryo'

View File

@ -114,7 +114,6 @@ object FiberMonitor {
thread { thread {
while (true) { while (true) {
Thread.sleep(1000) Thread.sleep(1000)
this
} }
} }
} }

View File

@ -12,7 +12,7 @@ package net.corda.flowhook
import java.lang.instrument.Instrumentation import java.lang.instrument.Instrumentation
@Suppress("UNUSED") @Suppress("UNUSED", "UNUSED_PARAMETER")
class FlowHookAgent { class FlowHookAgent {
companion object { companion object {
@JvmStatic @JvmStatic
@ -22,4 +22,3 @@ class FlowHookAgent {
} }
} }
} }

View File

@ -21,7 +21,7 @@ import org.apache.activemq.artemis.core.io.buffer.TimedBuffer
import java.sql.Connection import java.sql.Connection
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@Suppress("UNUSED") @Suppress("UNUSED", "UNUSED_PARAMETER")
object FlowHookContainer { object FlowHookContainer {
@JvmStatic @JvmStatic

View File

@ -34,7 +34,6 @@ repositories {
} }
apply plugin: 'kotlin' apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'
apply plugin: 'idea' apply plugin: 'idea'
apply plugin: 'net.corda.plugins.cordapp' apply plugin: 'net.corda.plugins.cordapp'

View File

@ -11,13 +11,11 @@ import java.util.concurrent.Callable
// Responsible for executing test scenario for a single node executing `LinearStateBatchNotariseFlow` and verifying the results // Responsible for executing test scenario for a single node executing `LinearStateBatchNotariseFlow` and verifying the results
class LinearStateScenarioRunner(options: OptionSet) : AbstractScenarioRunner(options), Callable<Boolean> { class LinearStateScenarioRunner(options: OptionSet) : AbstractScenarioRunner(options), Callable<Boolean> {
companion object { companion object {
private val logger = contextLogger() private val logger = contextLogger()
} }
override fun call(): Boolean { override fun call(): Boolean {
scenarioInitialized() scenarioInitialized()
try { try {
@ -42,6 +40,7 @@ class LinearStateScenarioRunner(options: OptionSet) : AbstractScenarioRunner(opt
} }
} }
@Suppress("UNUSED_PARAMETER")
private fun verifyResultsAndStatesTally(results: MutableList<LinearStateBatchNotariseFlow.Result>, states: Vault.Page<LinearStateBatchNotariseContract.State>): Boolean { private fun verifyResultsAndStatesTally(results: MutableList<LinearStateBatchNotariseFlow.Result>, states: Vault.Page<LinearStateBatchNotariseContract.State>): Boolean {
// Unfortunately, there is absolutely nothing in `LinearStateBatchNotariseFlow.Result` which can link it to the original transaction // Unfortunately, there is absolutely nothing in `LinearStateBatchNotariseFlow.Result` which can link it to the original transaction
return true return true

View File

@ -8,33 +8,11 @@
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
buildscript { ext {
// For sharing constants between builds javaassist_version = "3.12.1.GA"
Properties constants = new Properties()
file("$projectDir/../../constants.properties").withInputStream { constants.load(it) }
ext.kotlin_version = constants.getProperty("kotlinVersion")
ext.javaassist_version = "3.12.1.GA"
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
} }
apply plugin: 'kotlin' apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'
apply plugin: 'idea' apply plugin: 'idea'
description 'A javaagent to allow hooking into Kryo' description 'A javaagent to allow hooking into Kryo'

View File

@ -8,33 +8,11 @@
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited. * Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/ */
buildscript { ext {
// For sharing constants between builds javaassist_version = "3.12.1.GA"
Properties constants = new Properties()
file("$projectDir/../../constants.properties").withInputStream { constants.load(it) }
ext.kotlin_version = constants.getProperty("kotlinVersion")
ext.javaassist_version = "3.12.1.GA"
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
} }
apply plugin: 'kotlin' apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'
apply plugin: 'idea' apply plugin: 'idea'
description 'A javaagent to allow hooking into the instrumentation by Quasar' description 'A javaagent to allow hooking into the instrumentation by Quasar'

View File

@ -12,12 +12,12 @@ package net.corda.finance.contracts.universal
import net.corda.core.crypto.toStringShort import net.corda.core.crypto.toStringShort
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.uncheckedCast
import java.math.BigDecimal import java.math.BigDecimal
import java.security.PublicKey import java.security.PublicKey
import java.time.Instant import java.time.Instant
private class PrettyPrint(arr : Arrangement) { private class PrettyPrint(arr : Arrangement) {
val parties = involvedParties(arr) val parties = involvedParties(arr)
private val sb = StringBuilder() private val sb = StringBuilder()
@ -26,21 +26,21 @@ private class PrettyPrint(arr : Arrangement) {
private var atStart = true private var atStart = true
private fun print(msg: String) { private fun print(msg: String) {
if (atStart) if (atStart)
repeat(indentLevel, { sb.append(' ') }) repeat(indentLevel) { sb.append(' ') }
sb.append(msg) sb.append(msg)
atStart = false atStart = false
} }
private fun println(message: Any?) { private fun println(message: Any?) {
if (atStart) if (atStart)
repeat(indentLevel, { sb.append(' ') }) repeat(indentLevel) { sb.append(' ') }
sb.appendln(message) sb.appendln(message)
atStart = true atStart = true
} }
private fun print(msg: Any?) { private fun print(msg: Any?) {
if (atStart) if (atStart)
repeat(indentLevel, { sb.append(' ') }) repeat(indentLevel) { sb.append(' ') }
sb.append(msg) sb.append(msg)
atStart = false atStart = false
} }
@ -55,8 +55,7 @@ private class PrettyPrint(arr : Arrangement) {
val partyMap = mutableMapOf<PublicKey, String>() val partyMap = mutableMapOf<PublicKey, String>()
val usedPartyNames = mutableSetOf<String>() val usedPartyNames = mutableSetOf<String>()
fun createPartyName(party : Party) : String fun createPartyName(party : Party): String {
{
val parts = party.name.organisation.toLowerCase().split(' ') val parts = party.name.organisation.toLowerCase().split(' ')
var camelName = parts.drop(1).fold(parts.first()) { var camelName = parts.drop(1).fold(parts.first()) {
@ -79,38 +78,38 @@ private class PrettyPrint(arr : Arrangement) {
} }
} }
fun prettyPrint(per: Perceivable<Boolean>, x: Boolean? = null) { fun prettyPrintBoolean(per: Perceivable<Boolean>) {
when (per) { when (per) {
is Const -> print("\"${per.value}\"") is Const -> print("\"${per.value}\"")
is PerceivableOr -> { is PerceivableOr -> {
prettyPrint(per.left) prettyPrintBoolean(per.left)
print(" or ") print(" or ")
prettyPrint(per.right) prettyPrintBoolean(per.right)
} }
is PerceivableAnd -> { is PerceivableAnd -> {
prettyPrint(per.left) prettyPrintBoolean(per.left)
print(" and ") print(" and ")
prettyPrint(per.right) prettyPrintBoolean(per.right)
} }
is TimePerceivable -> { is TimePerceivable -> {
when (per.cmp) { when (per.cmp) {
Comparison.GT, Comparison.GTE -> { Comparison.GT, Comparison.GTE -> {
print("after(") print("after(")
prettyPrint(per.instant) prettyPrintInstant(per.instant)
print(")") print(")")
} }
Comparison.LT, Comparison.LTE -> { Comparison.LT, Comparison.LTE -> {
print("before(") print("before(")
prettyPrint(per.instant) prettyPrintInstant(per.instant)
print(")") print(")")
} }
} }
} }
is PerceivableComparison<*> -> { is PerceivableComparison<*> -> {
when (per.type) { when (per.type) {
BigDecimal::class.java -> prettyPrint(per.left as Perceivable<BigDecimal>) BigDecimal::class.java -> prettyPrintBigDecimal(uncheckedCast(per.left))
Instant::class.java -> prettyPrint(per.left as Perceivable<Instant>) Instant::class.java -> prettyPrintInstant(uncheckedCast(per.left))
Boolean::class.java -> prettyPrint(per.left as Perceivable<Boolean>) Boolean::class.java -> prettyPrintBoolean(uncheckedCast(per.left))
} }
when (per.cmp) { when (per.cmp) {
Comparison.GT -> print(" > ") Comparison.GT -> print(" > ")
@ -119,9 +118,9 @@ private class PrettyPrint(arr : Arrangement) {
Comparison.LTE -> print(" <= ") Comparison.LTE -> print(" <= ")
} }
when (per.type) { when (per.type) {
BigDecimal::class.java -> prettyPrint(per.right as Perceivable<BigDecimal>) BigDecimal::class.java -> prettyPrintBigDecimal(uncheckedCast(per.right))
Instant::class.java -> prettyPrint(per.right as Perceivable<Instant>) Instant::class.java -> prettyPrintInstant(uncheckedCast(per.right))
Boolean::class.java -> prettyPrint(per.right as Perceivable<Boolean>) Boolean::class.java -> prettyPrintBoolean(uncheckedCast(per.right))
} }
} }
is TerminalEvent -> print("TerminalEvent(${partyMap[per.reference.owningKey]}, \"${per.source}\")") is TerminalEvent -> print("TerminalEvent(${partyMap[per.reference.owningKey]}, \"${per.source}\")")
@ -130,7 +129,7 @@ private class PrettyPrint(arr : Arrangement) {
} }
} }
fun prettyPrint(per: Perceivable<Instant>, x: Instant? = null) { fun prettyPrintInstant(per: Perceivable<Instant>) {
when (per) { when (per) {
is Const -> print("\"${per.value}\"") is Const -> print("\"${per.value}\"")
is StartDate -> print("startDate") is StartDate -> print("startDate")
@ -139,34 +138,33 @@ private class PrettyPrint(arr : Arrangement) {
} }
} }
fun prettyPrint(per: Perceivable<BigDecimal>, x: BigDecimal? = null) { fun prettyPrintBigDecimal(per: Perceivable<BigDecimal>) {
when (per) { when (per) {
is PerceivableOperation<BigDecimal> -> { is PerceivableOperation<BigDecimal> -> {
prettyPrint(per.left) prettyPrintBigDecimal(per.left)
when (per.op) { when (per.op) {
Operation.PLUS -> print(" + ") Operation.PLUS -> print(" + ")
Operation.MINUS -> print(" - ") Operation.MINUS -> print(" - ")
Operation.DIV -> print(" / ") Operation.DIV -> print(" / ")
Operation.TIMES -> print(" * ") Operation.TIMES -> print(" * ")
else -> print(per.op)
} }
prettyPrint(per.right) prettyPrintBigDecimal(per.right)
} }
is UnaryPlus -> { is UnaryPlus -> {
print("(") print("(")
prettyPrint(per.arg) prettyPrintBigDecimal(per.arg)
print(".).plus()") print(".).plus()")
} }
is Const -> print(per.value) is Const -> print(per.value)
is Interest -> { is Interest -> {
print("Interest(") print("Interest(")
prettyPrint(per.amount) prettyPrintBigDecimal(per.amount)
print(", \"${per.dayCountConvention}\", ") print(", \"${per.dayCountConvention}\", ")
prettyPrint(per.amount) prettyPrintBigDecimal(per.amount)
print(", ") print(", ")
prettyPrint(per.start) prettyPrintInstant(per.start)
print(", ") print(", ")
prettyPrint(per.end) prettyPrintInstant(per.end)
print(")") print(")")
} }
is CurrencyCross -> print("${per.foreign}/${per.domestic}") is CurrencyCross -> print("${per.foreign}/${per.domestic}")
@ -175,7 +173,6 @@ private class PrettyPrint(arr : Arrangement) {
} }
fun prettyPrint(arr: Arrangement) { fun prettyPrint(arr: Arrangement) {
when (arr) { when (arr) {
is Zero -> println("zero") is Zero -> println("zero")
is RollOut -> { is RollOut -> {
@ -193,7 +190,7 @@ private class PrettyPrint(arr : Arrangement) {
is Continuation -> println("next()") is Continuation -> println("next()")
is Obligation -> { is Obligation -> {
print("${partyMap[arr.from.owningKey]}.gives( ${partyMap[arr.to.owningKey]}, ") print("${partyMap[arr.from.owningKey]}.gives( ${partyMap[arr.to.owningKey]}, ")
prettyPrint(arr.amount) prettyPrintBigDecimal(arr.amount)
println(", ${arr.currency})") println(", ${arr.currency})")
} }
is Actions -> { is Actions -> {
@ -201,7 +198,7 @@ private class PrettyPrint(arr : Arrangement) {
indent { indent {
for ((name, condition, arrangement) in arr.actions) { for ((name, condition, arrangement) in arr.actions) {
print("\"$name\".givenThat(") print("\"$name\".givenThat(")
prettyPrint(condition) prettyPrintBoolean(condition)
println(") {") println(") {")
indent { indent {
prettyPrint(arrangement) prettyPrint(arrangement)

View File

@ -46,46 +46,45 @@ class UniversalContract : Contract {
class Split(val ratio: BigDecimal) : Commands class Split(val ratio: BigDecimal) : Commands
} }
fun eval(@Suppress("UNUSED_PARAMETER") tx: LedgerTransaction, expr: Perceivable<Instant>): Instant? = when (expr) { fun evalInstant(expr: Perceivable<Instant>): Instant? = when (expr) {
is Const -> expr.value is Const -> expr.value
is StartDate -> null is StartDate -> null
is EndDate -> null is EndDate -> null
else -> throw Error("Unable to evaluate") else -> throw Error("Unable to evaluate")
} }
fun eval(tx: LedgerTransaction, expr: Perceivable<Boolean>): Boolean = when (expr) { fun evalBoolean(tx: LedgerTransaction, expr: Perceivable<Boolean>): Boolean = when (expr) {
is PerceivableAnd -> eval(tx, expr.left) && eval(tx, expr.right) is PerceivableAnd -> evalBoolean(tx, expr.left) && evalBoolean(tx, expr.right)
is PerceivableOr -> eval(tx, expr.left) || eval(tx, expr.right) is PerceivableOr -> evalBoolean(tx, expr.left) || evalBoolean(tx, expr.right)
is Const<Boolean> -> expr.value is Const<Boolean> -> expr.value
is TimePerceivable -> when (expr.cmp) { is TimePerceivable -> when (expr.cmp) {
Comparison.LTE -> tx.timeWindow!!.fromTime!! <= eval(tx, expr.instant) Comparison.LTE -> tx.timeWindow!!.fromTime!! <= evalInstant(expr.instant)
Comparison.GTE -> tx.timeWindow!!.untilTime!! >= eval(tx, expr.instant) Comparison.GTE -> tx.timeWindow!!.untilTime!! >= evalInstant(expr.instant)
else -> throw NotImplementedError("eval special") else -> throw NotImplementedError("eval special")
} }
is ActorPerceivable -> tx.commands.single().signers.contains(expr.actor.owningKey) is ActorPerceivable -> tx.commands.single().signers.contains(expr.actor.owningKey)
else -> throw NotImplementedError("eval - Boolean - " + expr.javaClass.name) else -> throw NotImplementedError("eval - Boolean - " + expr.javaClass.name)
} }
fun eval(tx: LedgerTransaction, expr: Perceivable<BigDecimal>): BigDecimal = fun evalBigDecimal(tx: LedgerTransaction, expr: Perceivable<BigDecimal>): BigDecimal =
when (expr) { when (expr) {
is Const<BigDecimal> -> expr.value is Const<BigDecimal> -> expr.value
is UnaryPlus -> { is UnaryPlus -> {
val x = eval(tx, expr.arg) val x = evalBigDecimal(tx, expr.arg)
if (x > BigDecimal.ZERO) if (x > BigDecimal.ZERO)
x x
else else
BigDecimal.ZERO BigDecimal.ZERO
} }
is PerceivableOperation -> { is PerceivableOperation -> {
val l = eval(tx, expr.left) val l = evalBigDecimal(tx, expr.left)
val r = eval(tx, expr.right) val r = evalBigDecimal(tx, expr.right)
when (expr.op) { when (expr.op) {
Operation.DIV -> l / r Operation.DIV -> l / r
Operation.MINUS -> l - r Operation.MINUS -> l - r
Operation.PLUS -> l + r Operation.PLUS -> l + r
Operation.TIMES -> l * r Operation.TIMES -> l * r
else -> throw NotImplementedError("eval - amount - operation " + expr.op)
} }
} }
is Fixing -> { is Fixing -> {
@ -93,8 +92,8 @@ class UniversalContract : Contract {
0.0.bd 0.0.bd
} }
is Interest -> { is Interest -> {
val a = eval(tx, expr.amount) val a = evalBigDecimal(tx, expr.amount)
val i = eval(tx, expr.interest) val i = evalBigDecimal(tx, expr.interest)
//TODO //TODO
@ -105,7 +104,7 @@ class UniversalContract : Contract {
fun validateImmediateTransfers(tx: LedgerTransaction, arrangement: Arrangement): Arrangement = when (arrangement) { fun validateImmediateTransfers(tx: LedgerTransaction, arrangement: Arrangement): Arrangement = when (arrangement) {
is Obligation -> { is Obligation -> {
val amount = eval(tx, arrangement.amount) val amount = evalBigDecimal(tx, arrangement.amount)
requireThat { "transferred quantity is non-negative" using (amount >= BigDecimal.ZERO) } requireThat { "transferred quantity is non-negative" using (amount >= BigDecimal.ZERO) }
Obligation(const(amount), arrangement.currency, arrangement.from, arrangement.to) Obligation(const(amount), arrangement.currency, arrangement.from, arrangement.to)
} }
@ -220,7 +219,7 @@ class UniversalContract : Contract {
"action must have a time-window" using (tx.timeWindow != null) "action must have a time-window" using (tx.timeWindow != null)
// "action must be authorized" by (cmd.signers.any { action.actors.any { party -> party.owningKey == it } }) // "action must be authorized" by (cmd.signers.any { action.actors.any { party -> party.owningKey == it } })
// todo perhaps merge these two requirements? // todo perhaps merge these two requirements?
"condition must be met" using (eval(tx, action.condition)) "condition must be met" using evalBoolean(tx, action.condition)
} }
// verify that any resulting transfers can be resolved // verify that any resulting transfers can be resolved
@ -297,7 +296,7 @@ class UniversalContract : Contract {
perceivable.dayCountConvention, replaceFixing(tx, perceivable.interest, fixings, unusedFixings), perceivable.dayCountConvention, replaceFixing(tx, perceivable.interest, fixings, unusedFixings),
perceivable.start, perceivable.end)) perceivable.start, perceivable.end))
is Fixing -> { is Fixing -> {
val dt = eval(tx, perceivable.date) val dt = evalInstant(perceivable.date)
if (dt != null && fixings.containsKey(FixOf(perceivable.source, dt.toLocalDate(), perceivable.tenor))) { if (dt != null && fixings.containsKey(FixOf(perceivable.source, dt.toLocalDate(), perceivable.tenor))) {
unusedFixings.remove(FixOf(perceivable.source, dt.toLocalDate(), perceivable.tenor)) unusedFixings.remove(FixOf(perceivable.source, dt.toLocalDate(), perceivable.tenor))
uncheckedCast(Const(fixings[FixOf(perceivable.source, dt.toLocalDate(), perceivable.tenor)]!!)) uncheckedCast(Const(fixings[FixOf(perceivable.source, dt.toLocalDate(), perceivable.tenor)]!!))

View File

@ -24,13 +24,12 @@ class IRS {
@Rule @Rule
@JvmField @JvmField
val testSerialization = SerializationEnvironmentRule() val testSerialization = SerializationEnvironmentRule()
val TEST_TX_TIME_1: Instant get() = Instant.parse("2017-09-02T12:00:00.00Z")
val notional = 50.M private val testTxTime1: Instant = Instant.parse("2017-09-02T12:00:00.00Z")
val currency = EUR private val notional = 50.M
private val currency = EUR
val tradeDate: LocalDate = LocalDate.of(2016, 9, 1)
private val tradeDate: LocalDate = LocalDate.of(2016, 9, 1)
/* /*
@ -43,7 +42,7 @@ class IRS {
*/ */
val contractInitial = arrange { private val contractInitial = arrange {
rollOut("2016-09-01".ld, "2018-09-01".ld, Frequency.Quarterly) { rollOut("2016-09-01".ld, "2018-09-01".ld, Frequency.Quarterly) {
actions { actions {
(acmeCorp or highStreetBank) may { (acmeCorp or highStreetBank) may {
@ -62,7 +61,8 @@ class IRS {
} }
} }
} }
val contractAfterFixingFirst = arrange {
private val contractAfterFixingFirst = arrange {
actions { actions {
(acmeCorp or highStreetBank) may { (acmeCorp or highStreetBank) may {
val floating = interest(notional, "act/365", 1.0.bd, "2016-09-01", "2016-12-01") val floating = interest(notional, "act/365", 1.0.bd, "2016-09-01", "2016-12-01")
@ -93,15 +93,15 @@ class IRS {
rollOut("2016-12-01".ld, "2018-09-01".ld, Frequency.Quarterly) { rollOut("2016-12-01".ld, "2018-09-01".ld, Frequency.Quarterly) {
actions { actions {
(acmeCorp or highStreetBank) may { (acmeCorp or highStreetBank) may {
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("3M")), start, end) val nextFloating = interest(notional, "act/365", fix("LIBOR", start, Tenor("3M")), start, end)
val fixed = interest(notional, "act/365", 0.5.bd, start, end) val nextFixed = interest(notional, "act/365", 0.5.bd, start, end)
"pay floating" anytime { "pay floating" anytime {
highStreetBank.owes(acmeCorp, floating - fixed, currency) highStreetBank.owes(acmeCorp, nextFloating - nextFixed, currency)
next() next()
} }
"pay fixed" anytime { "pay fixed" anytime {
highStreetBank.owes(acmeCorp, fixed - floating, currency) highStreetBank.owes(acmeCorp, nextFixed - nextFloating, currency)
next() next()
} }
} }
@ -112,7 +112,7 @@ class IRS {
} }
} }
val contractAfterExecutionFirst = arrange { private val contractAfterExecutionFirst = arrange {
rollOut("2016-12-01".ld, "2018-09-01".ld, Frequency.Quarterly) { rollOut("2016-12-01".ld, "2018-09-01".ld, Frequency.Quarterly) {
actions { actions {
(acmeCorp or highStreetBank) may { (acmeCorp or highStreetBank) may {
@ -132,19 +132,20 @@ class IRS {
} }
} }
val paymentFirst = arrange { highStreetBank.owes(acmeCorp, 250.K, EUR) } private val paymentFirst = arrange { highStreetBank.owes(acmeCorp, 250.K, EUR) }
val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY), contractInitial) private val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY), contractInitial)
val stateAfterFixingFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterFixingFirst) private val stateAfterFixingFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterFixingFirst)
val stateAfterExecutionFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterExecutionFirst) private val stateAfterExecutionFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterExecutionFirst)
private val statePaymentFirst = UniversalContract.State(listOf(DUMMY_NOTARY), paymentFirst)
val statePaymentFirst = UniversalContract.State(listOf(DUMMY_NOTARY), paymentFirst)
@Test @Test
fun issue() { fun issue() {
transaction { transaction {
output(UNIVERSAL_PROGRAM_ID, stateInitial) output(UNIVERSAL_PROGRAM_ID, stateInitial)
timeWindow(TEST_TX_TIME_1) timeWindow(testTxTime1)
tweak { tweak {
command(acmeCorp.owningKey, UniversalContract.Commands.Issue()) command(acmeCorp.owningKey, UniversalContract.Commands.Issue())
@ -160,7 +161,7 @@ class IRS {
transaction { transaction {
input(UNIVERSAL_PROGRAM_ID, stateInitial) input(UNIVERSAL_PROGRAM_ID, stateInitial)
output(UNIVERSAL_PROGRAM_ID, stateAfterFixingFirst) output(UNIVERSAL_PROGRAM_ID, stateAfterFixingFirst)
timeWindow(TEST_TX_TIME_1) timeWindow(testTxTime1)
tweak { tweak {
command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name"))
@ -200,7 +201,7 @@ class IRS {
input(UNIVERSAL_PROGRAM_ID, stateAfterFixingFirst) input(UNIVERSAL_PROGRAM_ID, stateAfterFixingFirst)
output(UNIVERSAL_PROGRAM_ID, stateAfterExecutionFirst) output(UNIVERSAL_PROGRAM_ID, stateAfterExecutionFirst)
output(UNIVERSAL_PROGRAM_ID, statePaymentFirst) output(UNIVERSAL_PROGRAM_ID, statePaymentFirst)
timeWindow(TEST_TX_TIME_1) timeWindow(testTxTime1)
tweak { tweak {
command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name"))

View File

@ -27,8 +27,8 @@ class CashSelectionOracleImpl : AbstractCashSelection(maxRetries = 16, retrySlee
private val log = contextLogger() private val log = contextLogger()
} }
override fun isCompatible(metaData: DatabaseMetaData): Boolean { override fun isCompatible(metadata: DatabaseMetaData): Boolean {
return metaData.driverName.startsWith(JDBC_DRIVER_NAME, ignoreCase = true) return metadata.driverName.startsWith(JDBC_DRIVER_NAME, ignoreCase = true)
} }
override fun toString() = "${this::class.qualifiedName} for '$JDBC_DRIVER_NAME'" override fun toString() = "${this::class.qualifiedName} for '$JDBC_DRIVER_NAME'"

View File

@ -16,7 +16,6 @@ import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.toBase58String
import java.sql.Connection import java.sql.Connection
import java.sql.DatabaseMetaData import java.sql.DatabaseMetaData
import java.sql.ResultSet import java.sql.ResultSet
@ -32,8 +31,8 @@ class CashSelectionSQLServerImpl : AbstractCashSelection(maxRetries = 16, retryS
private val log = contextLogger() private val log = contextLogger()
} }
override fun isCompatible(metaData: DatabaseMetaData): Boolean { override fun isCompatible(metadata: DatabaseMetaData): Boolean {
return metaData.driverName.startsWith(JDBC_DRIVER_NAME, ignoreCase = true) return metadata.driverName.startsWith(JDBC_DRIVER_NAME, ignoreCase = true)
} }
override fun toString() = "${this::class.qualifiedName} for '$JDBC_DRIVER_NAME'" override fun toString() = "${this::class.qualifiedName} for '$JDBC_DRIVER_NAME'"

View File

@ -8,7 +8,6 @@ import java.nio.file.Paths
import kotlin.system.exitProcess import kotlin.system.exitProcess
fun main(args: Array<String>) { fun main(args: Array<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
println("Usage: launcher <main-class-name> [args]") println("Usage: launcher <main-class-name> [args]")
exitProcess(0) exitProcess(0)
@ -54,15 +53,14 @@ fun main(args: Array<String>) {
@Suppress("unchecked") @Suppress("unchecked")
private fun fixBaseDirArg(args: Array<String>, nodeBaseDirFromArgs: Path): Array<String> { private fun fixBaseDirArg(args: Array<String>, nodeBaseDirFromArgs: Path): Array<String> {
val baseDirIdx = args.indexOf("--base-directory") val baseDirIdx = args.indexOf("--base-directory")
if (baseDirIdx != -1){ return if (baseDirIdx != -1) {
args[baseDirIdx+1] = nodeBaseDirFromArgs.toString() // Replace the arg that follows, i.e. --base-directory X
return args // TODO This will not work for --base-directory=X
args[baseDirIdx + 1] = nodeBaseDirFromArgs.toString()
args
} else {
args + listOf("--base-directory", nodeBaseDirFromArgs.toString())
} }
val argsWithBaseDir = args.copyOf(args.size + 2)
argsWithBaseDir[argsWithBaseDir.lastIndex - 1] = "--base-directory"
argsWithBaseDir[argsWithBaseDir.lastIndex] = nodeBaseDirFromArgs.toString()
return argsWithBaseDir as Array<String>
} }
private fun setupClassLoader(nodeBaseDir: Path): ClassLoader { private fun setupClassLoader(nodeBaseDir: Path): ClassLoader {

View File

@ -35,6 +35,8 @@ import java.util.*
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
import kotlin.reflect.KType import kotlin.reflect.KType
import kotlin.reflect.full.createInstance
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.memberProperties import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.primaryConstructor import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.jvmErasure import kotlin.reflect.jvm.jvmErasure
@ -42,6 +44,17 @@ import kotlin.reflect.jvm.jvmErasure
@Target(AnnotationTarget.PROPERTY) @Target(AnnotationTarget.PROPERTY)
annotation class OldConfig(val value: String) annotation class OldConfig(val value: String)
/**
* This annotation can be used to provide ConfigParser for the class,
* the [parseAs] method will use the provided parser instead of data class constructs to parse the object.
*/
@Target(AnnotationTarget.CLASS)
annotation class CustomConfigParser(val parser: KClass<out ConfigParser<*>>)
interface ConfigParser<T> {
fun parse(config: Config): T
}
const val CUSTOM_NODE_PROPERTIES_ROOT = "custom" const val CUSTOM_NODE_PROPERTIES_ROOT = "custom"
// TODO Move other config parsing to use parseAs and remove this // TODO Move other config parsing to use parseAs and remove this
@ -50,7 +63,10 @@ operator fun <T : Any> Config.getValue(receiver: Any, metadata: KProperty<*>): T
} }
fun <T : Any> Config.parseAs(clazz: KClass<T>, onUnknownKeys: ((Set<String>, logger: Logger) -> Unit) = UnknownConfigKeysPolicy.FAIL::handle, nestedPath: String? = null): T { fun <T : Any> Config.parseAs(clazz: KClass<T>, onUnknownKeys: ((Set<String>, logger: Logger) -> Unit) = UnknownConfigKeysPolicy.FAIL::handle, nestedPath: String? = null): T {
require(clazz.isData) { "Only Kotlin data classes can be parsed. Offending: ${clazz.qualifiedName}" } // Use custom parser if provided, instead of treating the object as data class.
clazz.findAnnotation<CustomConfigParser>()?.let { return uncheckedCast(it.parser.createInstance().parse(this)) }
require(clazz.isData) { "Only Kotlin data classes or class annotated with CustomConfigParser can be parsed. Offending: ${clazz.qualifiedName}" }
val constructor = clazz.primaryConstructor!! val constructor = clazz.primaryConstructor!!
val parameters = constructor.parameters val parameters = constructor.parameters
val parameterNames = parameters.flatMap { param -> val parameterNames = parameters.flatMap { param ->

View File

@ -237,6 +237,36 @@ class ConfigParsingTest {
} }
} }
@Test
fun `parse with provided parser`() {
val type1Config = mapOf("type" to "1", "value" to "type 1 value")
val type2Config = mapOf("type" to "2", "value" to "type 2 value")
val configuration = config("values" to listOf(type1Config, type2Config))
val objects = configuration.parseAs<TestObjects>()
assertThat(objects.values).containsExactly(TestObject.Type1("type 1 value"), TestObject.Type2("type 2 value"))
}
class TestParser : ConfigParser<TestObject> {
override fun parse(config: Config): TestObject {
val type = config.getInt("type")
return when (type) {
1 -> config.parseAs<TestObject.Type1>(onUnknownKeys = UnknownConfigKeysPolicy.IGNORE::handle)
2 -> config.parseAs<TestObject.Type2>(onUnknownKeys = UnknownConfigKeysPolicy.IGNORE::handle)
else -> throw IllegalArgumentException("Unsupported Object type : '$type'")
}
}
}
data class TestObjects(val values: List<TestObject>)
@CustomConfigParser(TestParser::class)
sealed class TestObject {
data class Type1(val value: String) : TestObject()
data class Type2(val value: String) : TestObject()
}
private inline fun <reified S : SingleData<V>, reified L : ListData<V>, V : Any> testPropertyType( private inline fun <reified S : SingleData<V>, reified L : ListData<V>, V : Any> testPropertyType(
value1: V, value1: V,
value2: V, value2: V,
@ -320,6 +350,7 @@ class ConfigParsingTest {
require(positive > 0) { "$positive is not positive" } require(positive > 0) { "$positive is not positive" }
} }
} }
data class OldData( data class OldData(
@OldConfig("oldValue") @OldConfig("oldValue")
val newValue: String) val newValue: String)

View File

@ -63,6 +63,7 @@ class AuthDBTests : NodeBasedTest() {
private lateinit var client: CordaRPCClient private lateinit var client: CordaRPCClient
private lateinit var db: UsersDB private lateinit var db: UsersDB
@Suppress("MemberVisibilityCanBePrivate")
@Parameterized.Parameter @Parameterized.Parameter
lateinit var passwordEncryption: PasswordEncryption lateinit var passwordEncryption: PasswordEncryption
@ -110,7 +111,7 @@ class AuthDBTests : NodeBasedTest() {
) )
node = startNode(ALICE_NAME, rpcUsers = emptyList(), configOverrides = securityConfig) node = startNode(ALICE_NAME, rpcUsers = emptyList(), configOverrides = securityConfig)
client = CordaRPCClient(node.internals.configuration.rpcOptions.address!!) client = CordaRPCClient(node.internals.configuration.rpcOptions.address)
} }
@Test @Test
@ -243,9 +244,8 @@ private data class RoleAndPermissions(val role: String, val permissions: List<St
/* /*
* Manage in-memory DB mocking a users database with the schema expected by Node's security manager * Manage in-memory DB mocking a users database with the schema expected by Node's security manager
*/ */
private class UsersDB : AutoCloseable { private class UsersDB(name: String, users: List<UserAndRoles> = emptyList(), roleAndPermissions: List<RoleAndPermissions> = emptyList()) : AutoCloseable {
val jdbcUrl = "jdbc:h2:mem:$name;DB_CLOSE_DELAY=-1"
val jdbcUrl: String
companion object { companion object {
const val DB_CREATE_SCHEMA = """ const val DB_CREATE_SCHEMA = """
@ -295,11 +295,7 @@ private class UsersDB : AutoCloseable {
} }
} }
constructor(name: String, init {
users: List<UserAndRoles> = emptyList(),
roleAndPermissions: List<RoleAndPermissions> = emptyList()) {
jdbcUrl = "jdbc:h2:mem:$name;DB_CLOSE_DELAY=-1"
dataSource = DataSourceFactory.createDataSource(Properties().apply { dataSource = DataSourceFactory.createDataSource(Properties().apply {
put("dataSourceClassName", "org.h2.jdbcx.JdbcDataSource") put("dataSourceClassName", "org.h2.jdbcx.JdbcDataSource")
put("dataSource.url", jdbcUrl) put("dataSource.url", jdbcUrl)
@ -307,11 +303,9 @@ private class UsersDB : AutoCloseable {
session { session {
it.execute(DB_CREATE_SCHEMA) it.execute(DB_CREATE_SCHEMA)
} }
require(users.map { it.username }.toSet().size == users.size) { require(users.map { it.username }.toSet().size == users.size) {
"Duplicate username in input" "Duplicate username in input"
} }
users.forEach { insert(it) } users.forEach { insert(it) }
roleAndPermissions.forEach { insert(it) } roleAndPermissions.forEach { insert(it) }
} }

View File

@ -257,7 +257,7 @@ class MySQLNotaryServiceTests : IntegrationTest() {
} }
private fun createNotaryNode(): InternalMockNetwork.MockNode { private fun createNotaryNode(): InternalMockNetwork.MockNode {
val dataStoreProperties = makeTestDataSourceProperties(configSupplier = { _, _ -> ConfigFactory.empty() }, fallBackConfigSupplier = ::inMemoryH2DataSourceConfig).apply { val dataStoreProperties = makeInternalTestDataSourceProperties(configSupplier = { ConfigFactory.empty() }).apply {
setProperty("autoCommit", "false") setProperty("autoCommit", "false")
} }
return mockNet.createUnstartedNode( return mockNet.createUnstartedNode(

View File

@ -32,7 +32,6 @@ import net.corda.testing.internal.DEV_ROOT_CA
import net.corda.testing.internal.IntegrationTest import net.corda.testing.internal.IntegrationTest
import net.corda.testing.internal.IntegrationTestSchemas import net.corda.testing.internal.IntegrationTestSchemas
import net.corda.testing.node.NotarySpec import net.corda.testing.node.NotarySpec
import net.corda.testing.node.internal.CompatibilityZoneParams
import net.corda.testing.node.internal.SharedCompatibilityZoneParams import net.corda.testing.node.internal.SharedCompatibilityZoneParams
import net.corda.testing.node.internal.internalDriver import net.corda.testing.node.internal.internalDriver
import net.corda.testing.node.internal.network.NetworkMapServer import net.corda.testing.node.internal.network.NetworkMapServer
@ -64,7 +63,6 @@ class NodeRegistrationTest : IntegrationTest() {
private val notaryName = CordaX500Name("NotaryService", "Zurich", "CH") private val notaryName = CordaX500Name("NotaryService", "Zurich", "CH")
private val aliceName = CordaX500Name("Alice", "London", "GB") private val aliceName = CordaX500Name("Alice", "London", "GB")
private val genevieveName = CordaX500Name("Genevieve", "London", "GB") private val genevieveName = CordaX500Name("Genevieve", "London", "GB")
private val log = contextLogger()
} }
@Rule @Rule
@ -82,7 +80,7 @@ class NodeRegistrationTest : IntegrationTest() {
pollInterval = 1.seconds, pollInterval = 1.seconds,
hostAndPort = portAllocation.nextHostAndPort(), hostAndPort = portAllocation.nextHostAndPort(),
myHostNameValue = "localhost", myHostNameValue = "localhost",
additionalServices = registrationHandler) additionalServices = *arrayOf(registrationHandler))
serverHostAndPort = server.start() serverHostAndPort = server.start()
} }

View File

@ -78,7 +78,7 @@ class MQSecurityAsNodeTest : P2PMQSecurityTest() {
@Test @Test
fun `login to a non ssl port as a node user`() { fun `login to a non ssl port as a node user`() {
val attacker = clientTo(alice.internals.configuration.rpcOptions.address!!, sslConfiguration = null) val attacker = clientTo(alice.internals.configuration.rpcOptions.address, sslConfiguration = null)
assertThatExceptionOfType(ActiveMQSecurityException::class.java).isThrownBy { assertThatExceptionOfType(ActiveMQSecurityException::class.java).isThrownBy {
attacker.start(NODE_P2P_USER, NODE_P2P_USER, enableSSL = false) attacker.start(NODE_P2P_USER, NODE_P2P_USER, enableSSL = false)
} }
@ -86,7 +86,7 @@ class MQSecurityAsNodeTest : P2PMQSecurityTest() {
@Test @Test
fun `login to a non ssl port as a peer user`() { fun `login to a non ssl port as a peer user`() {
val attacker = clientTo(alice.internals.configuration.rpcOptions.address!!, sslConfiguration = null) val attacker = clientTo(alice.internals.configuration.rpcOptions.address, sslConfiguration = null)
assertThatExceptionOfType(ActiveMQSecurityException::class.java).isThrownBy { assertThatExceptionOfType(ActiveMQSecurityException::class.java).isThrownBy {
attacker.start(PEER_USER, PEER_USER, enableSSL = false) // Login as a peer attacker.start(PEER_USER, PEER_USER, enableSSL = false) // Login as a peer
} }

View File

@ -18,7 +18,7 @@ import org.junit.Test
*/ */
class MQSecurityAsRPCTest : RPCMQSecurityTest() { class MQSecurityAsRPCTest : RPCMQSecurityTest() {
override fun createAttacker(): SimpleMQClient { override fun createAttacker(): SimpleMQClient {
return clientTo(alice.internals.configuration.rpcOptions.address!!) return clientTo(alice.internals.configuration.rpcOptions.address)
} }
@Test @Test

View File

@ -41,6 +41,7 @@ import net.corda.testing.node.internal.NodeBasedTest
import net.corda.testing.node.internal.startFlow import net.corda.testing.node.internal.startFlow
import org.apache.activemq.artemis.api.core.ActiveMQNonExistentQueueException import org.apache.activemq.artemis.api.core.ActiveMQNonExistentQueueException
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException import org.apache.activemq.artemis.api.core.ActiveMQSecurityException
import org.apache.activemq.artemis.api.core.RoutingType
import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.SimpleString
import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.junit.ClassRule import org.junit.ClassRule
@ -125,9 +126,9 @@ abstract class MQSecurityTest : NodeBasedTest() {
} }
fun loginToRPCAndGetClientQueue(): String { fun loginToRPCAndGetClientQueue(): String {
loginToRPC(alice.internals.configuration.rpcOptions.address!!, rpcUser) loginToRPC(alice.internals.configuration.rpcOptions.address, rpcUser)
val clientQueueQuery = SimpleString("${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.${rpcUser.username}.*") val clientQueueQuery = SimpleString("${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.${rpcUser.username}.*")
val client = clientTo(alice.internals.configuration.rpcOptions.address!!) val client = clientTo(alice.internals.configuration.rpcOptions.address)
client.start(rpcUser.username, rpcUser.password, false) client.start(rpcUser.username, rpcUser.password, false)
return client.session.addressQuery(clientQueueQuery).queueNames.single().toString() return client.session.addressQuery(clientQueueQuery).queueNames.single().toString()
} }
@ -140,7 +141,7 @@ abstract class MQSecurityTest : NodeBasedTest() {
fun assertTempQueueCreationAttackFails(queue: String) { fun assertTempQueueCreationAttackFails(queue: String) {
assertAttackFails(queue, "CREATE_NON_DURABLE_QUEUE") { assertAttackFails(queue, "CREATE_NON_DURABLE_QUEUE") {
attacker.session.createTemporaryQueue(queue, queue) attacker.session.createTemporaryQueue(queue, RoutingType.MULTICAST, queue)
} }
// Double-check // Double-check
assertThatExceptionOfType(ActiveMQNonExistentQueueException::class.java).isThrownBy { assertThatExceptionOfType(ActiveMQNonExistentQueueException::class.java).isThrownBy {
@ -157,7 +158,7 @@ abstract class MQSecurityTest : NodeBasedTest() {
fun assertNonTempQueueCreationAttackFails(queue: String, durable: Boolean) { fun assertNonTempQueueCreationAttackFails(queue: String, durable: Boolean) {
val permission = if (durable) "CREATE_DURABLE_QUEUE" else "CREATE_NON_DURABLE_QUEUE" val permission = if (durable) "CREATE_DURABLE_QUEUE" else "CREATE_NON_DURABLE_QUEUE"
assertAttackFails(queue, permission) { assertAttackFails(queue, permission) {
attacker.session.createQueue(queue, queue, durable) attacker.session.createQueue(queue, RoutingType.MULTICAST, queue, durable)
} }
// Double-check // Double-check
assertThatExceptionOfType(ActiveMQNonExistentQueueException::class.java).isThrownBy { assertThatExceptionOfType(ActiveMQNonExistentQueueException::class.java).isThrownBy {

View File

@ -14,11 +14,10 @@ import com.typesafe.config.Config
import com.typesafe.config.ConfigException import com.typesafe.config.ConfigException
import net.corda.core.context.AuthServiceId import net.corda.core.context.AuthServiceId
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.div import net.corda.core.internal.TimedFlow
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.seconds import net.corda.core.utilities.seconds
import net.corda.node.internal.artemis.CertificateChainCheckPolicy
import net.corda.node.services.config.rpc.NodeRpcOptions import net.corda.node.services.config.rpc.NodeRpcOptions
import net.corda.nodeapi.BrokerRpcSslOptions import net.corda.nodeapi.BrokerRpcSslOptions
import net.corda.nodeapi.internal.config.NodeSSLConfiguration import net.corda.nodeapi.internal.config.NodeSSLConfiguration
@ -51,6 +50,7 @@ interface NodeConfiguration : NodeSSLConfiguration {
val devModeOptions: DevModeOptions? val devModeOptions: DevModeOptions?
val compatibilityZoneURL: URL? val compatibilityZoneURL: URL?
val networkServices: NetworkServicesConfig? val networkServices: NetworkServicesConfig?
@Suppress("DEPRECATION")
val certificateChainCheckPolicies: List<CertChainPolicyConfig> val certificateChainCheckPolicies: List<CertChainPolicyConfig>
val verifierType: VerifierType val verifierType: VerifierType
val flowTimeout: FlowTimeoutConfiguration val flowTimeout: FlowTimeoutConfiguration
@ -237,6 +237,7 @@ data class NodeConfigurationImpl(
override val messagingServerExternal: Boolean = (messagingServerAddress != null), override val messagingServerExternal: Boolean = (messagingServerAddress != null),
override val enterpriseConfiguration: EnterpriseConfiguration, override val enterpriseConfiguration: EnterpriseConfiguration,
override val notary: NotaryConfig?, override val notary: NotaryConfig?,
@Suppress("DEPRECATION")
@Deprecated("Do not configure") @Deprecated("Do not configure")
override val certificateChainCheckPolicies: List<CertChainPolicyConfig> = emptyList(), override val certificateChainCheckPolicies: List<CertChainPolicyConfig> = emptyList(),
override val devMode: Boolean = false, override val devMode: Boolean = false,
@ -413,6 +414,7 @@ data class NodeConfigurationImpl(
} }
// Check for usage of deprecated config // Check for usage of deprecated config
@Suppress("DEPRECATION")
if(certificateChainCheckPolicies.isNotEmpty()) { if(certificateChainCheckPolicies.isNotEmpty()) {
logger.warn("""You are configuring certificateChainCheckPolicies. This is a setting that is not used, and will be removed in a future version. logger.warn("""You are configuring certificateChainCheckPolicies. This is a setting that is not used, and will be removed in a future version.
|Please contact the R3 team on the public slack to discuss your use case. |Please contact the R3 team on the public slack to discuss your use case.
@ -467,18 +469,7 @@ enum class CertChainPolicyType {
} }
@Deprecated("Do not use") @Deprecated("Do not use")
data class CertChainPolicyConfig(val role: String, private val policy: CertChainPolicyType, private val trustedAliases: Set<String>) { data class CertChainPolicyConfig(val role: String, private val policy: CertChainPolicyType, private val trustedAliases: Set<String>)
val certificateChainCheckPolicy: CertificateChainCheckPolicy
get() {
return when (policy) {
CertChainPolicyType.Any -> CertificateChainCheckPolicy.Any
CertChainPolicyType.RootMustMatch -> CertificateChainCheckPolicy.RootMustMatch
CertChainPolicyType.LeafMustMatch -> CertificateChainCheckPolicy.LeafMustMatch
CertChainPolicyType.MustContainOneOf -> CertificateChainCheckPolicy.MustContainOneOf(trustedAliases)
CertChainPolicyType.UsernameMustMatch -> CertificateChainCheckPolicy.UsernameMustMatchCommonName
}
}
}
// Supported types of authentication/authorization data providers // Supported types of authentication/authorization data providers
enum class AuthDataSourceType { enum class AuthDataSourceType {
@ -515,8 +506,6 @@ data class SecurityConfiguration(val authService: SecurityConfiguration.AuthServ
} }
} }
fun copyWithAdditionalUser(user: User) = AuthService(dataSource.copyWithAdditionalUser(user), id, options)
// Optional components: cache // Optional components: cache
data class Options(val cache: Options.Cache?) { data class Options(val cache: Options.Cache?) {
@ -544,12 +533,6 @@ data class SecurityConfiguration(val authService: SecurityConfiguration.AuthServ
AuthDataSourceType.DB -> require(users == null && connection != null) AuthDataSourceType.DB -> require(users == null && connection != null)
} }
} }
fun copyWithAdditionalUser(user: User): DataSource {
val extendedList = this.users?.toMutableList() ?: mutableListOf()
extendedList.add(user)
return DataSource(this.type, this.passwordEncryption, this.connection, listOf(*extendedList.toTypedArray()))
}
} }
companion object { companion object {

View File

@ -34,7 +34,7 @@ import javax.annotation.concurrent.ThreadSafe
*/ */
// TODO There is duplicated logic between this and PersistentIdentityService // TODO There is duplicated logic between this and PersistentIdentityService
@ThreadSafe @ThreadSafe
class InMemoryIdentityService(identities: List<out PartyAndCertificate> = emptyList(), class InMemoryIdentityService(identities: List<PartyAndCertificate> = emptyList(),
override val trustRoot: X509Certificate) : SingletonSerializeAsToken(), IdentityService { override val trustRoot: X509Certificate) : SingletonSerializeAsToken(), IdentityService {
companion object { companion object {
private val log = contextLogger() private val log = contextLogger()

View File

@ -63,7 +63,7 @@ class E2ETestKeyManagementService(val identityService: IdentityService,
} }
override fun freshKeyAndCert(identity: PartyAndCertificate, revocationEnabled: Boolean): PartyAndCertificate { override fun freshKeyAndCert(identity: PartyAndCertificate, revocationEnabled: Boolean): PartyAndCertificate {
return freshCertificate(identityService, freshKey(), identity, getSigner(identity.owningKey), revocationEnabled) return freshCertificate(identityService, freshKey(), identity, getSigner(identity.owningKey))
} }
private fun getSigner(publicKey: PublicKey): ContentSigner = getSigner(getSigningKeyPair(publicKey)) private fun getSigner(publicKey: PublicKey): ContentSigner = getSigner(getSigningKeyPair(publicKey))

View File

@ -40,8 +40,7 @@ import java.time.Duration
fun freshCertificate(identityService: IdentityService, fun freshCertificate(identityService: IdentityService,
subjectPublicKey: PublicKey, subjectPublicKey: PublicKey,
issuer: PartyAndCertificate, issuer: PartyAndCertificate,
issuerSigner: ContentSigner, issuerSigner: ContentSigner): PartyAndCertificate {
revocationEnabled: Boolean = false): PartyAndCertificate {
val issuerRole = CertRole.extract(issuer.certificate) val issuerRole = CertRole.extract(issuer.certificate)
require(issuerRole == CertRole.LEGAL_IDENTITY) { "Confidential identities can only be issued from well known identities, provided issuer ${issuer.name} has role $issuerRole" } require(issuerRole == CertRole.LEGAL_IDENTITY) { "Confidential identities can only be issued from well known identities, provided issuer ${issuer.name} has role $issuerRole" }
val issuerCert = issuer.certificate val issuerCert = issuer.certificate

View File

@ -98,8 +98,9 @@ class PersistentKeyManagementService(val identityService: IdentityService,
return keyPair.public return keyPair.public
} }
override fun freshKeyAndCert(identity: PartyAndCertificate, revocationEnabled: Boolean): PartyAndCertificate = override fun freshKeyAndCert(identity: PartyAndCertificate, revocationEnabled: Boolean): PartyAndCertificate {
freshCertificate(identityService, freshKey(), identity, getSigner(identity.owningKey), revocationEnabled) return freshCertificate(identityService, freshKey(), identity, getSigner(identity.owningKey))
}
private fun getSigner(publicKey: PublicKey): ContentSigner = getSigner(getSigningKeyPair(publicKey)) private fun getSigner(publicKey: PublicKey): ContentSigner = getSigner(getSigningKeyPair(publicKey))

View File

@ -16,6 +16,7 @@ import net.corda.node.utilities.AffinityExecutor
import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
import org.hibernate.Session import org.hibernate.Session
import org.hibernate.query.NativeQuery
import java.io.Serializable import java.io.Serializable
import java.sql.SQLTransientConnectionException import java.sql.SQLTransientConnectionException
import java.time.Duration import java.time.Duration
@ -132,7 +133,7 @@ class RunOnceService(private val database: CordaPersistence, private val machine
private fun insertMutualExclusion(session: Session) { private fun insertMutualExclusion(session: Session) {
val query = session.createNativeQuery("INSERT INTO $TABLE VALUES ('X', :machineName, :pid, CURRENT_TIMESTAMP, :version)", MutualExclusion::class.java) val query = session.createNativeQuery("INSERT INTO $TABLE VALUES ('X', :machineName, :pid, CURRENT_TIMESTAMP, :version)", MutualExclusion::class.java)
query.unwrap(org.hibernate.SQLQuery::class.java).addSynchronizedEntityClass(MutualExclusion::class.java) query.unwrap(NativeQuery::class.java).addSynchronizedEntityClass(MutualExclusion::class.java)
query.setParameter("pid", pid) query.setParameter("pid", pid)
query.setParameter("machineName", machineName) query.setParameter("machineName", machineName)
query.setParameter("version", 0) query.setParameter("version", 0)

View File

@ -70,7 +70,7 @@ class MultiThreadedStateMachineManager(
val checkpointStorage: CheckpointStorage, val checkpointStorage: CheckpointStorage,
val executor: ExecutorService, val executor: ExecutorService,
val database: CordaPersistence, val database: CordaPersistence,
val secureRandom: SecureRandom, private val secureRandom: SecureRandom,
private val unfinishedFibers: ReusableLatch = ReusableLatch(), private val unfinishedFibers: ReusableLatch = ReusableLatch(),
private val classloader: ClassLoader = MultiThreadedStateMachineManager::class.java.classLoader private val classloader: ClassLoader = MultiThreadedStateMachineManager::class.java.classLoader
) : StateMachineManager, StateMachineManagerInternal { ) : StateMachineManager, StateMachineManagerInternal {
@ -158,7 +158,7 @@ class MultiThreadedStateMachineManager(
} }
serviceHub.networkMapCache.nodeReady.then { serviceHub.networkMapCache.nodeReady.then {
resumeRestoredFlows(fibers) resumeRestoredFlows(fibers)
flowMessaging.start { receivedMessage, deduplicationHandler -> flowMessaging.start { _, deduplicationHandler ->
lifeCycle.requireState(State.STARTED, StateMachineStoppedException("Flow cannot be started. State machine is stopped.")) { lifeCycle.requireState(State.STARTED, StateMachineStoppedException("Flow cannot be started. State machine is stopped.")) {
deliverExternalEvent(deduplicationHandler.externalCause) deliverExternalEvent(deduplicationHandler.externalCause)
} }
@ -306,10 +306,10 @@ class MultiThreadedStateMachineManager(
} }
private fun checkQuasarJavaAgentPresence() { private fun checkQuasarJavaAgentPresence() {
check(SuspendableHelper.isJavaAgentActive(), { check(SuspendableHelper.isJavaAgentActive()) {
"""Missing the '-javaagent' JVM argument. Make sure you run the tests with the Quasar java agent attached to your JVM. """Missing the '-javaagent' JVM argument. Make sure you run the tests with the Quasar java agent attached to your JVM.
#See https://docs.corda.net/troubleshooting.html - 'Fiber classes not instrumented' for more details.""".trimMargin("#") #See https://docs.corda.net/troubleshooting.html - 'Fiber classes not instrumented' for more details.""".trimMargin("#")
}) }
} }
private fun decrementLiveFibers() { private fun decrementLiveFibers() {
@ -324,8 +324,7 @@ class MultiThreadedStateMachineManager(
return checkpointStorage.getAllCheckpoints().map { (id, serializedCheckpoint) -> return checkpointStorage.getAllCheckpoints().map { (id, serializedCheckpoint) ->
// If a flow is added before start() then don't attempt to restore it // If a flow is added before start() then don't attempt to restore it
if (concurrentBox.content.flows.containsKey(id)) return@map null if (concurrentBox.content.flows.containsKey(id)) return@map null
val checkpoint = deserializeCheckpoint(serializedCheckpoint) val checkpoint = deserializeCheckpoint(serializedCheckpoint) ?: return@map null
if (checkpoint == null) return@map null
createFlowFromCheckpoint( createFlowFromCheckpoint(
id = id, id = id,
checkpoint = checkpoint, checkpoint = checkpoint,
@ -440,7 +439,7 @@ class MultiThreadedStateMachineManager(
val flowId = sessionToFlow[recipientId] val flowId = sessionToFlow[recipientId]
if (flowId == null) { if (flowId == null) {
deduplicationHandler.afterDatabaseTransaction() deduplicationHandler.afterDatabaseTransaction()
if (sessionMessage.payload is EndSessionMessage) { if (sessionMessage.payload === EndSessionMessage) {
logger.debug { logger.debug {
"Got ${EndSessionMessage::class.java.simpleName} for " + "Got ${EndSessionMessage::class.java.simpleName} for " +
"unknown session $recipientId, discarding..." "unknown session $recipientId, discarding..."
@ -537,12 +536,6 @@ class MultiThreadedStateMachineManager(
isStartIdempotent: Boolean isStartIdempotent: Boolean
): CordaFuture<FlowStateMachine<A>> { ): CordaFuture<FlowStateMachine<A>> {
val flowId = StateMachineRunId.createRandom() val flowId = StateMachineRunId.createRandom()
val deduplicationSeed = when (flowStart) {
FlowStart.Explicit -> flowId.uuid.toString()
is FlowStart.Initiated ->
"${flowStart.initiatingMessage.initiatorSessionId.toLong}-" +
"${flowStart.initiatingMessage.initiationEntropy}"
}
// Before we construct the state machine state by freezing the FlowLogic we need to make sure that lazy properties // Before we construct the state machine state by freezing the FlowLogic we need to make sure that lazy properties
// have access to the fiber (and thereby the service hub) // have access to the fiber (and thereby the service hub)
@ -553,7 +546,7 @@ class MultiThreadedStateMachineManager(
val frozenFlowLogic = (flowLogic as FlowLogic<*>).serialize(context = checkpointSerializationContext!!) val frozenFlowLogic = (flowLogic as FlowLogic<*>).serialize(context = checkpointSerializationContext!!)
val flowCorDappVersion = FlowStateMachineImpl.createSubFlowVersion(serviceHub.cordappProvider.getCordappForFlow(flowLogic), serviceHub.myInfo.platformVersion) val flowCorDappVersion = FlowStateMachineImpl.createSubFlowVersion(serviceHub.cordappProvider.getCordappForFlow(flowLogic), serviceHub.myInfo.platformVersion)
val initialCheckpoint = Checkpoint.create(invocationContext, flowStart, flowLogic.javaClass, frozenFlowLogic, ourIdentity, deduplicationSeed, flowCorDappVersion).getOrThrow() val initialCheckpoint = Checkpoint.create(invocationContext, flowStart, flowLogic.javaClass, frozenFlowLogic, ourIdentity, flowCorDappVersion).getOrThrow()
val startedFuture = openFuture<Unit>() val startedFuture = openFuture<Unit>()
val initialState = StateMachineState( val initialState = StateMachineState(
checkpoint = initialCheckpoint, checkpoint = initialCheckpoint,
@ -721,7 +714,7 @@ class MultiThreadedStateMachineManager(
private fun addAndStartFlow(id: StateMachineRunId, flow: Flow) { private fun addAndStartFlow(id: StateMachineRunId, flow: Flow) {
val checkpoint = flow.fiber.snapshot().checkpoint val checkpoint = flow.fiber.snapshot().checkpoint
for (sessionId in getFlowSessionIds(checkpoint)) { for (sessionId in getFlowSessionIds(checkpoint)) {
sessionToFlow.put(sessionId, id) sessionToFlow[sessionId] = id
} }
concurrentBox.concurrent { concurrentBox.concurrent {
val oldFlow = flows.put(id, flow) val oldFlow = flows.put(id, flow)

View File

@ -66,10 +66,10 @@ import kotlin.streams.toList
@ThreadSafe @ThreadSafe
class SingleThreadedStateMachineManager( class SingleThreadedStateMachineManager(
val serviceHub: ServiceHubInternal, val serviceHub: ServiceHubInternal,
val checkpointStorage: CheckpointStorage, private val checkpointStorage: CheckpointStorage,
val executor: ExecutorService, val executor: ExecutorService,
val database: CordaPersistence, val database: CordaPersistence,
val secureRandom: SecureRandom, private val secureRandom: SecureRandom,
private val unfinishedFibers: ReusableLatch = ReusableLatch(), private val unfinishedFibers: ReusableLatch = ReusableLatch(),
private val classloader: ClassLoader = SingleThreadedStateMachineManager::class.java.classLoader private val classloader: ClassLoader = SingleThreadedStateMachineManager::class.java.classLoader
) : StateMachineManager, StateMachineManagerInternal { ) : StateMachineManager, StateMachineManagerInternal {
@ -145,7 +145,7 @@ class SingleThreadedStateMachineManager(
} }
serviceHub.networkMapCache.nodeReady.then { serviceHub.networkMapCache.nodeReady.then {
resumeRestoredFlows(fibers) resumeRestoredFlows(fibers)
flowMessaging.start { receivedMessage, deduplicationHandler -> flowMessaging.start { _, deduplicationHandler ->
executor.execute { executor.execute {
deliverExternalEvent(deduplicationHandler.externalCause) deliverExternalEvent(deduplicationHandler.externalCause)
} }
@ -296,10 +296,10 @@ class SingleThreadedStateMachineManager(
} }
private fun checkQuasarJavaAgentPresence() { private fun checkQuasarJavaAgentPresence() {
check(SuspendableHelper.isJavaAgentActive(), { check(SuspendableHelper.isJavaAgentActive()) {
"""Missing the '-javaagent' JVM argument. Make sure you run the tests with the Quasar java agent attached to your JVM. """Missing the '-javaagent' JVM argument. Make sure you run the tests with the Quasar java agent attached to your JVM.
#See https://docs.corda.net/troubleshooting.html - 'Fiber classes not instrumented' for more details.""".trimMargin("#") #See https://docs.corda.net/troubleshooting.html - 'Fiber classes not instrumented' for more details.""".trimMargin("#")
}) }
} }
private fun decrementLiveFibers() { private fun decrementLiveFibers() {
@ -314,8 +314,7 @@ class SingleThreadedStateMachineManager(
return checkpointStorage.getAllCheckpoints().map { (id, serializedCheckpoint) -> return checkpointStorage.getAllCheckpoints().map { (id, serializedCheckpoint) ->
// If a flow is added before start() then don't attempt to restore it // If a flow is added before start() then don't attempt to restore it
mutex.locked { if (flows.containsKey(id)) return@map null } mutex.locked { if (flows.containsKey(id)) return@map null }
val checkpoint = deserializeCheckpoint(serializedCheckpoint) val checkpoint = deserializeCheckpoint(serializedCheckpoint) ?: return@map null
if (checkpoint == null) return@map null
logger.debug { "Restored $checkpoint" } logger.debug { "Restored $checkpoint" }
createFlowFromCheckpoint( createFlowFromCheckpoint(
id = id, id = id,
@ -534,12 +533,6 @@ class SingleThreadedStateMachineManager(
isStartIdempotent: Boolean isStartIdempotent: Boolean
): CordaFuture<FlowStateMachine<A>> { ): CordaFuture<FlowStateMachine<A>> {
val flowId = StateMachineRunId.createRandom() val flowId = StateMachineRunId.createRandom()
val deduplicationSeed = when (flowStart) {
FlowStart.Explicit -> flowId.uuid.toString()
is FlowStart.Initiated ->
"${flowStart.initiatingMessage.initiatorSessionId.toLong}-" +
"${flowStart.initiatingMessage.initiationEntropy}"
}
// Before we construct the state machine state by freezing the FlowLogic we need to make sure that lazy properties // Before we construct the state machine state by freezing the FlowLogic we need to make sure that lazy properties
// have access to the fiber (and thereby the service hub) // have access to the fiber (and thereby the service hub)
@ -551,7 +544,7 @@ class SingleThreadedStateMachineManager(
val flowCorDappVersion = createSubFlowVersion(serviceHub.cordappProvider.getCordappForFlow(flowLogic), serviceHub.myInfo.platformVersion) val flowCorDappVersion = createSubFlowVersion(serviceHub.cordappProvider.getCordappForFlow(flowLogic), serviceHub.myInfo.platformVersion)
val initialCheckpoint = Checkpoint.create(invocationContext, flowStart, flowLogic.javaClass, frozenFlowLogic, ourIdentity, deduplicationSeed, flowCorDappVersion).getOrThrow() val initialCheckpoint = Checkpoint.create(invocationContext, flowStart, flowLogic.javaClass, frozenFlowLogic, ourIdentity, flowCorDappVersion).getOrThrow()
val startedFuture = openFuture<Unit>() val startedFuture = openFuture<Unit>()
val initialState = StateMachineState( val initialState = StateMachineState(
checkpoint = initialCheckpoint, checkpoint = initialCheckpoint,

View File

@ -2,6 +2,7 @@ package net.corda.node.services.statemachine
import net.corda.core.flows.StateMachineRunId import net.corda.core.flows.StateMachineRunId
import net.corda.core.internal.ThreadBox import net.corda.core.internal.ThreadBox
import net.corda.core.internal.TimedFlow
import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
@ -100,12 +101,6 @@ class StaffedFlowHospital {
private data class ConsultationReport(val error: Throwable, val diagnosis: Diagnosis, val by: List<Staff>) private data class ConsultationReport(val error: Throwable, val diagnosis: Diagnosis, val by: List<Staff>)
/**
* The flow running in [flowFiber] has cleaned, possibly as a result of a flow hospital resume.
*/
// It's okay for flows to be cleaned... we fix them now!
fun flowCleaned(flowFiber: FlowFiber) = Unit
/** /**
* The flow has been removed from the state machine. * The flow has been removed from the state machine.
*/ */

View File

@ -79,7 +79,6 @@ data class Checkpoint(
flowLogicClass: Class<FlowLogic<*>>, flowLogicClass: Class<FlowLogic<*>>,
frozenFlowLogic: SerializedBytes<FlowLogic<*>>, frozenFlowLogic: SerializedBytes<FlowLogic<*>>,
ourIdentity: Party, ourIdentity: Party,
deduplicationSeed: String,
subFlowVersion: SubFlowVersion subFlowVersion: SubFlowVersion
): Try<Checkpoint> { ): Try<Checkpoint> {
return SubFlow.create(flowLogicClass, subFlowVersion).map { topLevelSubFlow -> return SubFlow.create(flowLogicClass, subFlowVersion).map { topLevelSubFlow ->

View File

@ -55,9 +55,7 @@ class HospitalisingInterceptor(
when (nextState.checkpoint.errorState) { when (nextState.checkpoint.errorState) {
is ErrorState.Clean -> { is ErrorState.Clean -> {
if (hospitalisedFlows.remove(fiber.id) != null) { hospitalisedFlows.remove(fiber.id)
flowHospital.flowCleaned(fiber)
}
} }
is ErrorState.Errored -> { is ErrorState.Errored -> {
val exceptionsToHandle = nextState.checkpoint.errorState.errors.map { it.exception } val exceptionsToHandle = nextState.checkpoint.errorState.errors.map { it.exception }

View File

@ -86,7 +86,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
Transactional.Committed(value) Transactional.Committed(value)
} else { } else {
// Some database transactions, including us, writing, with readers seeing whatever is in the database and writers seeing the (in memory) value. // Some database transactions, including us, writing, with readers seeing whatever is in the database and writers seeing the (in memory) value.
Transactional.InFlight(this, key, { loadValue(key) }).apply { alsoWrite(value) } Transactional.InFlight(this, key, _readerValueLoader = { loadValue(key) }).apply { alsoWrite(value) }
} }
} }
@ -156,13 +156,13 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
} }
// Helpers to know if transaction(s) are currently writing the given key. // Helpers to know if transaction(s) are currently writing the given key.
protected fun weAreWriting(key: K): Boolean = pendingKeys.get(key)?.contains(contextTransaction) ?: false protected fun weAreWriting(key: K): Boolean = pendingKeys[key]?.contains(contextTransaction) ?: false
protected fun anyoneWriting(key: K): Boolean = pendingKeys.get(key)?.isNotEmpty() ?: false protected fun anyoneWriting(key: K): Boolean = pendingKeys[key]?.isNotEmpty() ?: false
// Indicate this database transaction is a writer of this key. // Indicate this database transaction is a writer of this key.
private fun addPendingKey(key: K, databaseTransaction: DatabaseTransaction): Boolean { private fun addPendingKey(key: K, databaseTransaction: DatabaseTransaction): Boolean {
var added = true var added = true
pendingKeys.compute(key) { k, oldSet -> pendingKeys.compute(key) { _, oldSet ->
if (oldSet == null) { if (oldSet == null) {
val newSet = HashSet<DatabaseTransaction>(0) val newSet = HashSet<DatabaseTransaction>(0)
newSet += databaseTransaction newSet += databaseTransaction
@ -177,7 +177,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
// Remove this database transaction as a writer of this key, because the transaction committed or rolled back. // Remove this database transaction as a writer of this key, because the transaction committed or rolled back.
private fun removePendingKey(key: K, databaseTransaction: DatabaseTransaction) { private fun removePendingKey(key: K, databaseTransaction: DatabaseTransaction) {
pendingKeys.compute(key) { k, oldSet -> pendingKeys.compute(key) { _, oldSet ->
if (oldSet == null) { if (oldSet == null) {
oldSet oldSet
} else { } else {
@ -209,7 +209,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
} }
// No one can see it. // No one can see it.
class Missing<T>() : Transactional<T>() { class Missing<T> : Transactional<T>() {
override val value: T override val value: T
get() = throw NoSuchElementException("Not present") get() = throw NoSuchElementException("Not present")
override val isPresent: Boolean override val isPresent: Boolean
@ -238,7 +238,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
fun alsoWrite(_value: T) { fun alsoWrite(_value: T) {
// Make the lazy loader the writers see actually just return the value that has been set. // Make the lazy loader the writers see actually just return the value that has been set.
writerValueLoader.set({ _value }) writerValueLoader.set { _value }
// We make all these vals so that the lambdas do not need a reference to this, and so the onCommit only has a weak ref to the value. // We make all these vals so that the lambdas do not need a reference to this, and so the onCommit only has a weak ref to the value.
// We want this so that the cache could evict the value (due to memory constraints etc) without the onCommit callback // We want this so that the cache could evict the value (due to memory constraints etc) without the onCommit callback
// retaining what could be a large memory footprint object. // retaining what could be a large memory footprint object.
@ -252,10 +252,9 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
// and then stop saying the transaction is writing the key. // and then stop saying the transaction is writing the key.
tx.onCommit { tx.onCommit {
if (strongComitted.compareAndSet(false, true)) { if (strongComitted.compareAndSet(false, true)) {
val dereferencedKey = strongKey
val dereferencedValue = weakValue.get() val dereferencedValue = weakValue.get()
if (dereferencedValue != null) { if (dereferencedValue != null) {
strongMap.cache.put(dereferencedKey, Committed(dereferencedValue)) strongMap.cache.put(strongKey, Committed(dereferencedValue))
} }
} }
strongMap.removePendingKey(strongKey, tx) strongMap.removePendingKey(strongKey, tx)
@ -272,7 +271,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
private fun loadAsWriter(): T { private fun loadAsWriter(): T {
val _value = writerValueLoader.get()() val _value = writerValueLoader.get()()
if (writerValueLoader.get() == _writerValueLoader) { if (writerValueLoader.get() == _writerValueLoader) {
writerValueLoader.set({ _value }) writerValueLoader.set { _value }
} }
return _value return _value
} }
@ -282,7 +281,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
private fun loadAsReader(): T? { private fun loadAsReader(): T? {
val _value = readerValueLoader.get()() val _value = readerValueLoader.get()()
if (readerValueLoader.get() == _readerValueLoader) { if (readerValueLoader.get() == _readerValueLoader) {
readerValueLoader.set({ _value }) readerValueLoader.set { _value }
} }
return _value return _value
} }
@ -320,7 +319,7 @@ open class AppendOnlyPersistentMap<K, V, E, out EK>(
toPersistentEntity, toPersistentEntity,
persistentEntityClass) { persistentEntityClass) {
//TODO determine cacheBound based on entity class later or with node config allowing tuning, or using some heuristic based on heap size //TODO determine cacheBound based on entity class later or with node config allowing tuning, or using some heuristic based on heap size
override val cache = NonInvalidatingCache<K, Transactional<V>>( override val cache = NonInvalidatingCache(
bound = cacheBound, bound = cacheBound,
loadFunction = { key: K -> loadFunction = { key: K ->
// This gets called if a value is read and the cache has no Transactional for this key yet. // This gets called if a value is read and the cache has no Transactional for this key yet.
@ -331,10 +330,10 @@ open class AppendOnlyPersistentMap<K, V, E, out EK>(
// If someone is writing (but not us) // If someone is writing (but not us)
// For those not writing, the value cannot be seen. // For those not writing, the value cannot be seen.
// For those writing, they need to re-load the value from the database (which their database transaction CAN see). // For those writing, they need to re-load the value from the database (which their database transaction CAN see).
Transactional.InFlight<K, V>(this, key, { null }, { loadValue(key)!! }) Transactional.InFlight(this, key, { null }, { loadValue(key)!! })
} else { } else {
// If no one is writing, then the value does not exist. // If no one is writing, then the value does not exist.
Transactional.Missing<V>() Transactional.Missing()
} }
} else { } else {
// A value was found // A value was found
@ -342,10 +341,10 @@ open class AppendOnlyPersistentMap<K, V, E, out EK>(
// If we are writing, it might not be globally visible, and was evicted from the cache. // If we are writing, it might not be globally visible, and was evicted from the cache.
// For those not writing, they need to check the database again. // For those not writing, they need to check the database again.
// For those writing, they can see the value found. // For those writing, they can see the value found.
Transactional.InFlight<K, V>(this, key, { loadValue(key) }, { value }) Transactional.InFlight(this, key, { loadValue(key) }, { value })
} else { } else {
// If no one is writing, then make it globally visible. // If no one is writing, then make it globally visible.
Transactional.Committed<V>(value) Transactional.Committed(value)
} }
} }
}) })
@ -364,26 +363,22 @@ class WeightBasedAppendOnlyPersistentMap<K, V, E, out EK>(
fromPersistentEntity, fromPersistentEntity,
toPersistentEntity, toPersistentEntity,
persistentEntityClass) { persistentEntityClass) {
override val cache = NonInvalidatingWeightBasedCache<K, Transactional<V>>( override val cache = NonInvalidatingWeightBasedCache(
maxWeight = maxWeight, maxWeight = maxWeight,
weigher = object : Weigher<K, Transactional<V>> { weigher = Weigher { key, value -> weighingFunc(key, value) },
override fun weigh(key: K, value: Transactional<V>): Int {
return weighingFunc(key, value)
}
},
loadFunction = { key: K -> loadFunction = { key: K ->
val value: V? = loadValue(key) val value: V? = loadValue(key)
if (value == null) { if (value == null) {
if (anyoneWriting(key)) { if (anyoneWriting(key)) {
Transactional.InFlight<K, V>(this, key, { null }, { loadValue(key)!! }) Transactional.InFlight(this, key, { null }, { loadValue(key)!! })
} else { } else {
Transactional.Missing<V>() Transactional.Missing()
} }
} else { } else {
if (weAreWriting(key)) { if (weAreWriting(key)) {
Transactional.InFlight<K, V>(this, key, { loadValue(key) }, { value }) Transactional.InFlight(this, key, { loadValue(key) }, { value })
} else { } else {
Transactional.Committed<V>(value) Transactional.Committed(value)
} }
} }
}) })

View File

@ -46,9 +46,6 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import rx.Observable; import rx.Observable;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.cert.CertificateException;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -80,7 +77,7 @@ public class VaultQueryJavaTests {
private CordaPersistence database; private CordaPersistence database;
@Before @Before
public void setUp() throws CertificateException, InvalidAlgorithmParameterException { public void setUp() {
List<String> cordappPackages = asList( List<String> cordappPackages = asList(
"net.corda.testing.internal.vault", "net.corda.testing.internal.vault",
"net.corda.finance.contracts.asset", "net.corda.finance.contracts.asset",
@ -101,14 +98,10 @@ public class VaultQueryJavaTests {
} }
@After @After
public void cleanUp() throws IOException { public void cleanUp() {
database.close(); database.close();
} }
/**
* Sample Vault Query API tests
*/
/** /**
* Static queryBy() tests * Static queryBy() tests
*/ */
@ -119,6 +112,7 @@ public class VaultQueryJavaTests {
FieldInfo currency = getField("currency", SampleCashSchemaV2.PersistentCashState.class); FieldInfo currency = getField("currency", SampleCashSchemaV2.PersistentCashState.class);
CriteriaExpression.AggregateFunctionExpression<Object, Boolean> expression = sum(quantity, singletonList(currency), Sort.Direction.ASC); CriteriaExpression.AggregateFunctionExpression<Object, Boolean> expression = sum(quantity, singletonList(currency), Sort.Direction.ASC);
@SuppressWarnings("unchecked")
VaultCustomQueryCriteria<SampleCashSchemaV2.PersistentCashState> criteria = new VaultCustomQueryCriteria(expression, Vault.StateStatus.UNCONSUMED, null); VaultCustomQueryCriteria<SampleCashSchemaV2.PersistentCashState> criteria = new VaultCustomQueryCriteria(expression, Vault.StateStatus.UNCONSUMED, null);
database.transaction(tx -> vaultService.queryBy(FungibleAsset.class, criteria)); database.transaction(tx -> vaultService.queryBy(FungibleAsset.class, criteria));
@ -131,13 +125,14 @@ public class VaultQueryJavaTests {
FieldInfo stateRef = getField("stateRef", SampleCashSchemaV2.PersistentCashState.class); FieldInfo stateRef = getField("stateRef", SampleCashSchemaV2.PersistentCashState.class);
CriteriaExpression.AggregateFunctionExpression<Object, Boolean> expression = sum(quantity, asList(currency, stateRef), Sort.Direction.ASC); CriteriaExpression.AggregateFunctionExpression<Object, Boolean> expression = sum(quantity, asList(currency, stateRef), Sort.Direction.ASC);
@SuppressWarnings("unchecked")
VaultCustomQueryCriteria<SampleCashSchemaV2.PersistentCashState> criteria = new VaultCustomQueryCriteria(expression, Vault.StateStatus.UNCONSUMED, null); VaultCustomQueryCriteria<SampleCashSchemaV2.PersistentCashState> criteria = new VaultCustomQueryCriteria(expression, Vault.StateStatus.UNCONSUMED, null);
database.transaction(tx -> vaultService.queryBy(FungibleAsset.class, criteria)); database.transaction(tx -> vaultService.queryBy(FungibleAsset.class, criteria));
} }
@Test @Test
public void unconsumedLinearStates() throws VaultQueryException { public void unconsumedLinearStates() {
database.transaction(tx -> { database.transaction(tx -> {
vaultFiller.fillWithSomeTestLinearStates(3); vaultFiller.fillWithSomeTestLinearStates(3);
return tx; return tx;
@ -209,7 +204,7 @@ public class VaultQueryJavaTests {
} }
@Test @Test
public void consumedDealStatesPagedSorted() throws VaultQueryException { public void consumedDealStatesPagedSorted() {
List<String> dealIds = asList("123", "456", "789"); List<String> dealIds = asList("123", "456", "789");
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Triple<StateAndRef<LinearState>, UniqueIdentifier, Vault<DealState>> ids = Triple<StateAndRef<LinearState>, UniqueIdentifier, Vault<DealState>> ids =
@ -320,7 +315,6 @@ public class VaultQueryJavaTests {
DataFeed<Vault.Page<ContractState>, Vault.Update<ContractState>> results = vaultService.trackBy(ContractState.class, criteria); DataFeed<Vault.Page<ContractState>, Vault.Update<ContractState>> results = vaultService.trackBy(ContractState.class, criteria);
Vault.Page<ContractState> snapshot = results.getSnapshot(); Vault.Page<ContractState> snapshot = results.getSnapshot();
Observable<Vault.Update<ContractState>> updates = results.getUpdates();
// DOCEND VaultJavaQueryExample4 // DOCEND VaultJavaQueryExample4
assertThat(snapshot.getStates()).hasSize(3); assertThat(snapshot.getStates()).hasSize(3);
@ -374,7 +368,6 @@ public class VaultQueryJavaTests {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void aggregateFunctionsWithoutGroupClause() { public void aggregateFunctionsWithoutGroupClause() {
database.transaction(tx -> { database.transaction(tx -> {
Amount<Currency> dollars100 = new Amount<>(100, Currency.getInstance("USD")); Amount<Currency> dollars100 = new Amount<>(100, Currency.getInstance("USD"));
Amount<Currency> dollars200 = new Amount<>(200, Currency.getInstance("USD")); Amount<Currency> dollars200 = new Amount<>(200, Currency.getInstance("USD"));
Amount<Currency> dollars300 = new Amount<>(300, Currency.getInstance("USD")); Amount<Currency> dollars300 = new Amount<>(300, Currency.getInstance("USD"));
@ -420,7 +413,6 @@ public class VaultQueryJavaTests {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void aggregateFunctionsWithSingleGroupClause() { public void aggregateFunctionsWithSingleGroupClause() {
database.transaction(tx -> { database.transaction(tx -> {
Amount<Currency> dollars100 = new Amount<>(100, Currency.getInstance("USD")); Amount<Currency> dollars100 = new Amount<>(100, Currency.getInstance("USD"));
Amount<Currency> dollars200 = new Amount<>(200, Currency.getInstance("USD")); Amount<Currency> dollars200 = new Amount<>(200, Currency.getInstance("USD"));
Amount<Currency> dollars300 = new Amount<>(300, Currency.getInstance("USD")); Amount<Currency> dollars300 = new Amount<>(300, Currency.getInstance("USD"));

View File

@ -34,7 +34,6 @@ import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.unwrap import net.corda.core.utilities.unwrap
import net.corda.finance.DOLLARS import net.corda.finance.DOLLARS
import net.corda.finance.GBP import net.corda.finance.GBP
import net.corda.finance.USD
import net.corda.finance.contracts.asset.Cash import net.corda.finance.contracts.asset.Cash
import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashIssueFlow
import net.corda.finance.flows.CashPaymentFlow import net.corda.finance.flows.CashPaymentFlow
@ -167,6 +166,7 @@ class CordaRPCOpsImplTest {
@Test @Test
fun `issue and move`() { fun `issue and move`() {
@Suppress("DEPRECATION")
withPermissions(invokeRpc(CordaRPCOps::stateMachinesFeed), withPermissions(invokeRpc(CordaRPCOps::stateMachinesFeed),
invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed), invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed),
invokeRpc("vaultTrackBy"), invokeRpc("vaultTrackBy"),
@ -178,11 +178,7 @@ class CordaRPCOpsImplTest {
vaultTrackCash = rpc.vaultTrackBy<Cash.State>().updates vaultTrackCash = rpc.vaultTrackBy<Cash.State>().updates
} }
val result = rpc.startFlow(::CashIssueFlow, val result = rpc.startFlow(::CashIssueFlow, 100.DOLLARS, OpaqueBytes.of(1), notary)
100.DOLLARS,
OpaqueBytes(ByteArray(1, { 1 })),
notary
)
mockNet.runNetwork() mockNet.runNetwork()
@ -257,7 +253,7 @@ class CordaRPCOpsImplTest {
fun `cash command by user not permissioned for cash`() { fun `cash command by user not permissioned for cash`() {
withoutAnyPermissions { withoutAnyPermissions {
assertThatExceptionOfType(PermissionException::class.java).isThrownBy { assertThatExceptionOfType(PermissionException::class.java).isThrownBy {
rpc.startFlow(::CashIssueFlow, Amount(100, USD), OpaqueBytes(ByteArray(1, { 1 })), notary) rpc.startFlow(::CashIssueFlow, 100.DOLLARS, OpaqueBytes.of(1), notary)
} }
} }
} }

View File

@ -70,7 +70,7 @@ class NodeTest {
fun `generateAndSaveNodeInfo works`() { fun `generateAndSaveNodeInfo works`() {
val configuration = createConfig(ALICE_NAME) val configuration = createConfig(ALICE_NAME)
val info = VersionInfo(789, "3.0", "SNAPSHOT", "R3") val info = VersionInfo(789, "3.0", "SNAPSHOT", "R3")
configureDatabase(configuration.dataSourceProperties, configuration.database, { null }, { null }).use { database -> configureDatabase(configuration.dataSourceProperties, configuration.database, { null }, { null }).use {
val node = Node(configuration, info, initialiseSerialization = false) val node = Node(configuration, info, initialiseSerialization = false)
assertEquals(node.generateNodeInfo(), node.generateNodeInfo()) // Node info doesn't change (including the serial) assertEquals(node.generateNodeInfo(), node.generateNodeInfo()) // Node info doesn't change (including the serial)
} }

View File

@ -19,7 +19,6 @@ import org.apache.activemq.artemis.api.core.SimpleString
import org.junit.Test import org.junit.Test
import rx.Notification import rx.Notification
import rx.Observable import rx.Observable
import rx.Subscription
import rx.subjects.UnicastSubject import rx.subjects.UnicastSubject
import java.time.Instant import java.time.Instant
import java.util.* import java.util.*
@ -38,7 +37,7 @@ class RoundTripObservableSerializerTests {
.maximumSize(100) .maximumSize(100)
.build() .build()
subMap.put(id, ObservableSubscription(mock<Subscription>())) subMap.put(id, ObservableSubscription(mock()))
return subMap return subMap
} }
@ -48,7 +47,7 @@ class RoundTripObservableSerializerTests {
}) })
private fun createRpcObservableMap(): Cache<Trace.InvocationId, UnicastSubject<Notification<*>>> { private fun createRpcObservableMap(): Cache<Trace.InvocationId, UnicastSubject<Notification<*>>> {
val onObservableRemove = RemovalListener<Trace.InvocationId, UnicastSubject<Notification<*>>> { key, value, cause -> val onObservableRemove = RemovalListener<Trace.InvocationId, UnicastSubject<Notification<*>>> { key, _, _ ->
val observableId = key!! val observableId = key!!
observablesToReap.locked { observables.add(observableId) } observablesToReap.locked { observables.add(observableId) }
@ -85,7 +84,7 @@ class RoundTripObservableSerializerTests {
// What we're actually going to serialize then deserialize // What we're actually going to serialize then deserialize
val obs = Observable.create<Int>({ 12 }) val obs = Observable.create<Int> { Math.random() }
val serverSerializationContext = RpcServerObservableSerializer.createContext( val serverSerializationContext = RpcServerObservableSerializer.createContext(
serializationContext, serverObservableContext) serializationContext, serverObservableContext)
@ -95,6 +94,6 @@ class RoundTripObservableSerializerTests {
val blob = SerializationOutput(serverSerializer).serialize(obs, serverSerializationContext) val blob = SerializationOutput(serverSerializer).serialize(obs, serverSerializationContext)
val obs2 = DeserializationInput(clientSerializer).deserialize(blob, clientSerializationContext) DeserializationInput(clientSerializer).deserialize(blob, clientSerializationContext)
} }
} }

View File

@ -8,13 +8,12 @@ import net.corda.node.internal.serialization.testutils.TestObservableContext
import net.corda.node.internal.serialization.testutils.serializationContext import net.corda.node.internal.serialization.testutils.serializationContext
import net.corda.node.serialization.amqp.RpcServerObservableSerializer import net.corda.node.serialization.amqp.RpcServerObservableSerializer
import net.corda.node.services.messaging.ObservableSubscription import net.corda.node.services.messaging.ObservableSubscription
import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.amqp.SerializationOutput import net.corda.serialization.internal.amqp.SerializationOutput
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactory
import net.corda.serialization.internal.AllWhitelist
import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.SimpleString
import org.junit.Test import org.junit.Test
import rx.Observable import rx.Observable
import rx.Subscription
import java.time.Instant import java.time.Instant
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -28,7 +27,7 @@ class RpcServerObservableSerializerTests {
.maximumSize(100) .maximumSize(100)
.build() .build()
subMap.put(Trace.InvocationId("test1", Instant.now()), ObservableSubscription(mock<Subscription>())) subMap.put(Trace.InvocationId("test1", Instant.now()), ObservableSubscription(mock()))
return subMap return subMap
} }
@ -72,7 +71,7 @@ class RpcServerObservableSerializerTests {
register(RpcServerObservableSerializer()) register(RpcServerObservableSerializer())
} }
val obs = Observable.create<Int>({ 12 }) val obs = Observable.create<Int> { Math.random() }
val newContext = RpcServerObservableSerializer.createContext(serializationContext, observable) val newContext = RpcServerObservableSerializer.createContext(serializationContext, observable)
try { try {

View File

@ -10,22 +10,8 @@
package net.corda.node.services.events package net.corda.node.services.events
import com.nhaarman.mockito_kotlin.any import com.nhaarman.mockito_kotlin.*
import com.nhaarman.mockito_kotlin.argForWhich import net.corda.core.contracts.*
import com.nhaarman.mockito_kotlin.doAnswer
import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.eq
import com.nhaarman.mockito_kotlin.same
import com.nhaarman.mockito_kotlin.timeout
import com.nhaarman.mockito_kotlin.verify
import com.nhaarman.mockito_kotlin.verifyNoMoreInteractions
import com.nhaarman.mockito_kotlin.whenever
import junit.framework.Assert.fail
import net.corda.core.contracts.SchedulableState
import net.corda.core.contracts.ScheduledActivity
import net.corda.core.contracts.ScheduledStateRef
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionState
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowLogicRef import net.corda.core.flows.FlowLogicRef
@ -46,11 +32,7 @@ import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.spectator import net.corda.testing.internal.spectator
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import net.corda.testing.node.TestClock import net.corda.testing.node.TestClock
import org.junit.After import org.junit.*
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestWatcher import org.junit.rules.TestWatcher
import org.junit.runner.Description import org.junit.runner.Description
import org.slf4j.Logger import org.slf4j.Logger
@ -61,6 +43,7 @@ import java.util.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.fail
open class NodeSchedulerServiceTestBase { open class NodeSchedulerServiceTestBase {
protected class Event(time: Instant) { protected class Event(time: Instant) {
@ -97,7 +80,7 @@ open class NodeSchedulerServiceTestBase {
doLookup(transactionStates).whenever(it).loadState(any()) doLookup(transactionStates).whenever(it).loadState(any())
} }
protected val traces = Collections.synchronizedList(mutableListOf<ScheduledStateRef>()) private val traces = Collections.synchronizedList(mutableListOf<ScheduledStateRef>())
@Before @Before
fun resetTraces() { fun resetTraces() {
@ -108,7 +91,7 @@ open class NodeSchedulerServiceTestBase {
doReturn(false).whenever(it).isTraceEnabled doReturn(false).whenever(it).isTraceEnabled
doAnswer { doAnswer {
traces += it.getArgument<ScheduledStateRef>(1) traces += it.getArgument<ScheduledStateRef>(1)
}.whenever(it).trace(eq(NodeSchedulerService.schedulingAsNextFormat), any<Object>()) }.whenever(it).trace(eq(NodeSchedulerService.schedulingAsNextFormat), any<Any>())
} }
protected fun assertWaitingFor(ssr: ScheduledStateRef) { protected fun assertWaitingFor(ssr: ScheduledStateRef) {
@ -283,7 +266,7 @@ class NodeSchedulerServiceTest : NodeSchedulerServiceTestBase() {
class NodeSchedulerPersistenceTest : NodeSchedulerServiceTestBase() { class NodeSchedulerPersistenceTest : NodeSchedulerServiceTestBase() {
private val databaseConfig: DatabaseConfig = DatabaseConfig() private val databaseConfig: DatabaseConfig = DatabaseConfig()
fun createScheduler(db: CordaPersistence): NodeSchedulerService { private fun createScheduler(db: CordaPersistence): NodeSchedulerService {
return NodeSchedulerService( return NodeSchedulerService(
testClock, testClock,
db, db,
@ -295,7 +278,7 @@ class NodeSchedulerPersistenceTest : NodeSchedulerServiceTestBase() {
log = log).apply { start() } log = log).apply { start() }
} }
fun transactionStateMock(logicRef: FlowLogicRef, time: Instant): TransactionState<*> { private fun transactionStateMock(logicRef: FlowLogicRef, time: Instant): TransactionState<*> {
return rigorousMock<TransactionState<SchedulableState>>().also { return rigorousMock<TransactionState<SchedulableState>>().also {
doReturn(rigorousMock<SchedulableState>().also { doReturn(rigorousMock<SchedulableState>().also {
doReturn(ScheduledActivity(logicRef, time)).whenever(it).nextScheduledActivity(any(), any()) doReturn(ScheduledActivity(logicRef, time)).whenever(it).nextScheduledActivity(any(), any())

View File

@ -81,7 +81,6 @@ class ArtemisMessagingTest {
doReturn("cordacadevpass").whenever(it).keyStorePassword doReturn("cordacadevpass").whenever(it).keyStorePassword
doReturn(NetworkHostAndPort("0.0.0.0", serverPort)).whenever(it).p2pAddress doReturn(NetworkHostAndPort("0.0.0.0", serverPort)).whenever(it).p2pAddress
doReturn(null).whenever(it).jmxMonitoringHttpPort doReturn(null).whenever(it).jmxMonitoringHttpPort
doReturn(emptyList<CertChainPolicyConfig>()).whenever(it).certificateChainCheckPolicies
doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000))).whenever(it).enterpriseConfiguration doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000))).whenever(it).enterpriseConfiguration
doReturn(FlowTimeoutConfiguration(5.seconds, 3, backoffBase = 1.0)).whenever(it).flowTimeout doReturn(FlowTimeoutConfiguration(5.seconds, 3, backoffBase = 1.0)).whenever(it).flowTimeout
} }

View File

@ -200,7 +200,7 @@ class DBCheckpointStorageTests {
override fun call() {} override fun call() {}
} }
val frozenLogic = logic.serialize(context = SerializationDefaults.CHECKPOINT_CONTEXT) val frozenLogic = logic.serialize(context = SerializationDefaults.CHECKPOINT_CONTEXT)
val checkpoint = Checkpoint.create(InvocationContext.shell(), FlowStart.Explicit, logic.javaClass, frozenLogic, ALICE, "", SubFlowVersion.CoreFlow(version)).getOrThrow() val checkpoint = Checkpoint.create(InvocationContext.shell(), FlowStart.Explicit, logic.javaClass, frozenLogic, ALICE, SubFlowVersion.CoreFlow(version)).getOrThrow()
return id to checkpoint.serialize(context = SerializationDefaults.CHECKPOINT_CONTEXT) return id to checkpoint.serialize(context = SerializationDefaults.CHECKPOINT_CONTEXT)
} }

View File

@ -17,18 +17,14 @@ import net.corda.core.crypto.SignatureMetadata
import net.corda.core.crypto.TransactionSignature import net.corda.core.crypto.TransactionSignature
import net.corda.core.toFuture import net.corda.core.toFuture
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.WireTransaction
import net.corda.node.internal.configureDatabase import net.corda.node.internal.configureDatabase
import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.transactions.PersistentUniquenessProvider import net.corda.node.services.transactions.PersistentUniquenessProvider
import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.core.ALICE_NAME import net.corda.testing.core.*
import net.corda.testing.core.DUMMY_NOTARY_NAME
import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.core.TestIdentity
import net.corda.testing.core.dummyCommand
import net.corda.testing.internal.LogHelper import net.corda.testing.internal.LogHelper
import net.corda.testing.internal.createWireTransaction
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
@ -176,7 +172,7 @@ class DBTransactionStorageTests {
} }
private fun newTransaction(): SignedTransaction { private fun newTransaction(): SignedTransaction {
val wtx = WireTransaction( val wtx = createWireTransaction(
inputs = listOf(StateRef(SecureHash.randomSHA256(), 0)), inputs = listOf(StateRef(SecureHash.randomSHA256(), 0)),
attachments = emptyList(), attachments = emptyList(),
outputs = emptyList(), outputs = emptyList(),
@ -184,6 +180,9 @@ class DBTransactionStorageTests {
notary = DUMMY_NOTARY, notary = DUMMY_NOTARY,
timeWindow = null timeWindow = null
) )
return SignedTransaction(wtx, listOf(TransactionSignature(ByteArray(1), ALICE_PUBKEY, SignatureMetadata(1, Crypto.findSignatureScheme(ALICE_PUBKEY).schemeNumberID)))) return SignedTransaction(
wtx,
listOf(TransactionSignature(ByteArray(1), ALICE_PUBKEY, SignatureMetadata(1, Crypto.findSignatureScheme(ALICE_PUBKEY).schemeNumberID)))
)
} }
} }

View File

@ -14,7 +14,6 @@ import com.nhaarman.mockito_kotlin.*
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.StateRef import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionState
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.generateKeyPair import net.corda.core.crypto.generateKeyPair
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
@ -39,13 +38,13 @@ import net.corda.finance.schemas.SampleCashSchemaV3
import net.corda.finance.schemas.CashSchemaV1 import net.corda.finance.schemas.CashSchemaV1
import net.corda.finance.utils.sumCash import net.corda.finance.utils.sumCash
import net.corda.node.internal.configureDatabase import net.corda.node.internal.configureDatabase
import net.corda.node.services.api.IdentityServiceInternal
import net.corda.node.services.api.WritableTransactionStorage
import net.corda.node.services.schema.ContractStateAndRef import net.corda.node.services.schema.ContractStateAndRef
import net.corda.node.services.schema.HibernateObserver import net.corda.node.services.schema.HibernateObserver
import net.corda.node.services.schema.NodeSchemaService import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.services.vault.VaultSchemaV1
import net.corda.node.services.api.IdentityServiceInternal
import net.corda.node.services.api.WritableTransactionStorage
import net.corda.node.services.vault.NodeVaultService import net.corda.node.services.vault.NodeVaultService
import net.corda.node.services.vault.VaultSchemaV1
import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.nodeapi.internal.persistence.HibernateConfiguration import net.corda.nodeapi.internal.persistence.HibernateConfiguration
@ -85,18 +84,18 @@ class HibernateConfigurationTest {
val testSerialization = SerializationEnvironmentRule() val testSerialization = SerializationEnvironmentRule()
lateinit var services: MockServices lateinit var services: MockServices
private lateinit var vaultFiller: VaultFiller private lateinit var vaultFiller: VaultFiller
lateinit var bankServices: MockServices private lateinit var bankServices: MockServices
lateinit var issuerServices: MockServices private lateinit var issuerServices: MockServices
lateinit var notaryServices: MockServices private lateinit var notaryServices: MockServices
lateinit var database: CordaPersistence lateinit var database: CordaPersistence
val vault: VaultService get() = services.vaultService val vault: VaultService get() = services.vaultService
// Hibernate configuration objects // Hibernate configuration objects
lateinit var hibernateConfig: HibernateConfiguration lateinit var hibernateConfig: HibernateConfiguration
lateinit var hibernatePersister: HibernateObserver private lateinit var hibernatePersister: HibernateObserver
lateinit var sessionFactory: SessionFactory private lateinit var sessionFactory: SessionFactory
lateinit var entityManager: EntityManager private lateinit var entityManager: EntityManager
lateinit var criteriaBuilder: CriteriaBuilder private lateinit var criteriaBuilder: CriteriaBuilder
// Identities used // Identities used
private lateinit var identity: Party private lateinit var identity: Party
@ -104,7 +103,7 @@ class HibernateConfigurationTest {
private lateinit var notary: Party private lateinit var notary: Party
// test States // test States
lateinit var cashStates: List<StateAndRef<Cash.State>> private lateinit var cashStates: List<StateAndRef<Cash.State>>
@Before @Before
fun setUp() { fun setUp() {
@ -701,7 +700,7 @@ class HibernateConfigurationTest {
val queryResults = entityManager.createQuery(criteriaQuery).resultList val queryResults = entityManager.createQuery(criteriaQuery).resultList
queryResults.forEach { queryResults.forEach {
val cashState = (services.loadState(toStateRef(it.stateRef!!)) as TransactionState<Cash.State>).data val cashState = services.loadState(toStateRef(it.stateRef!!)).data as Cash.State
println("${it.stateRef} with owner: ${cashState.owner.owningKey.toBase58String()}") println("${it.stateRef} with owner: ${cashState.owner.owningKey.toBase58String()}")
} }
@ -785,7 +784,7 @@ class HibernateConfigurationTest {
// execute query // execute query
val queryResults = entityManager.createQuery(criteriaQuery).resultList val queryResults = entityManager.createQuery(criteriaQuery).resultList
queryResults.forEach { queryResults.forEach {
val cashState = (services.loadState(toStateRef(it.stateRef!!)) as TransactionState<Cash.State>).data val cashState = services.loadState(toStateRef(it.stateRef!!)).data as Cash.State
println("${it.stateRef} with owner ${cashState.owner.owningKey.toBase58String()} and participants ${cashState.participants.map { it.owningKey.toBase58String() }}") println("${it.stateRef} with owner ${cashState.owner.owningKey.toBase58String()} and participants ${cashState.participants.map { it.owningKey.toBase58String() }}")
} }
@ -924,6 +923,6 @@ class HibernateConfigurationTest {
} }
private fun toStateRef(pStateRef: PersistentStateRef): StateRef { private fun toStateRef(pStateRef: PersistentStateRef): StateRef {
return StateRef(SecureHash.parse(pStateRef.txId!!), pStateRef.index!!) return StateRef(SecureHash.parse(pStateRef.txId), pStateRef.index)
} }
} }

View File

@ -15,11 +15,7 @@ import com.google.common.jimfs.Configuration
import com.google.common.jimfs.Jimfs import com.google.common.jimfs.Jimfs
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256 import net.corda.core.crypto.sha256
import net.corda.core.internal.read import net.corda.core.internal.*
import net.corda.core.internal.readAll
import net.corda.core.internal.readFully
import net.corda.core.internal.write
import net.corda.core.internal.writeLines
import net.corda.core.node.services.vault.AttachmentQueryCriteria import net.corda.core.node.services.vault.AttachmentQueryCriteria
import net.corda.core.node.services.vault.AttachmentSort import net.corda.core.node.services.vault.AttachmentSort
import net.corda.core.node.services.vault.Builder import net.corda.core.node.services.vault.Builder
@ -69,7 +65,7 @@ class NodeAttachmentStorageTest {
fun `insert and retrieve`() { fun `insert and retrieve`() {
val (testJar, expectedHash) = makeTestJar() val (testJar, expectedHash) = makeTestJar()
val id = testJar.read { storage.importAttachment(it) } val id = testJar.read { storage.importAttachment(it, "test", null) }
assertEquals(expectedHash, id) assertEquals(expectedHash, id)
assertNull(storage.openAttachment(SecureHash.randomSHA256())) assertNull(storage.openAttachment(SecureHash.randomSHA256()))
@ -94,7 +90,7 @@ class NodeAttachmentStorageTest {
val (testJar, expectedHash) = makeTestJar() val (testJar, expectedHash) = makeTestJar()
val (jarB, hashB) = makeTestJar(listOf(Pair("file", "content"))) val (jarB, hashB) = makeTestJar(listOf(Pair("file", "content")))
val id = testJar.read { storage.importAttachment(it) } val id = testJar.read { storage.importAttachment(it, "test", null) }
assertEquals(expectedHash, id) assertEquals(expectedHash, id)
@ -109,7 +105,7 @@ class NodeAttachmentStorageTest {
stream.close() stream.close()
val idB = jarB.read { storage.importAttachment(it) } val idB = jarB.read { storage.importAttachment(it, "test", null) }
assertEquals(hashB, idB) assertEquals(hashB, idB)
storage.openAttachment(id)!!.openAsJAR().use { storage.openAttachment(id)!!.openAsJAR().use {
@ -129,6 +125,7 @@ class NodeAttachmentStorageTest {
val (jarB, hashB) = makeTestJar(listOf(Pair("file", "content"))) val (jarB, hashB) = makeTestJar(listOf(Pair("file", "content")))
val (jarC, hashC) = makeTestJar(listOf(Pair("magic_file", "magic_content_puff"))) val (jarC, hashC) = makeTestJar(listOf(Pair("magic_file", "magic_content_puff")))
@Suppress("DEPRECATION")
jarA.read { storage.importAttachment(it) } jarA.read { storage.importAttachment(it) }
jarB.read { storage.importAttachment(it, "uploaderB", "fileB.zip") } jarB.read { storage.importAttachment(it, "uploaderB", "fileB.zip") }
jarC.read { storage.importAttachment(it, "uploaderC", "fileC.zip") } jarC.read { storage.importAttachment(it, "uploaderC", "fileC.zip") }
@ -196,11 +193,11 @@ class NodeAttachmentStorageTest {
fun `duplicates not allowed`() { fun `duplicates not allowed`() {
val (testJar, _) = makeTestJar() val (testJar, _) = makeTestJar()
testJar.read { testJar.read {
storage.importAttachment(it) storage.importAttachment(it, "test", null)
} }
assertFailsWith<FileAlreadyExistsException> { assertFailsWith<FileAlreadyExistsException> {
testJar.read { testJar.read {
storage.importAttachment(it) storage.importAttachment(it, "test", null)
} }
} }
} }
@ -209,7 +206,7 @@ class NodeAttachmentStorageTest {
fun `corrupt entry throws exception`() { fun `corrupt entry throws exception`() {
val (testJar, _) = makeTestJar() val (testJar, _) = makeTestJar()
val id = database.transaction { val id = database.transaction {
val id = testJar.read { storage.importAttachment(it) } val id = testJar.read { storage.importAttachment(it, "test", null) }
// Corrupt the file in the store. // Corrupt the file in the store.
val bytes = testJar.readAll() val bytes = testJar.readAll()
@ -237,7 +234,7 @@ class NodeAttachmentStorageTest {
path.writeLines(listOf("Hey", "there!")) path.writeLines(listOf("Hey", "there!"))
path.read { path.read {
assertFailsWith<IllegalArgumentException>("either empty or not a JAR") { assertFailsWith<IllegalArgumentException>("either empty or not a JAR") {
storage.importAttachment(it) storage.importAttachment(it, "test", null)
} }
} }
} }

View File

@ -246,7 +246,6 @@ class RunOnceServiceTest {
assertEquals('X', result.id) assertEquals('X', result.id)
assertEquals("machine1", result.machineName) assertEquals("machine1", result.machineName)
assertEquals("123", result.pid) assertEquals("123", result.pid)
assertTrue(result.timestamp is LocalDateTime)
return result return result
} }
@ -256,7 +255,6 @@ class RunOnceServiceTest {
assertEquals('X', result.id) assertEquals('X', result.id)
assertEquals("machine2", result.machineName) assertEquals("machine2", result.machineName)
assertEquals("789", result.pid) assertEquals("789", result.pid)
assertTrue(result.timestamp is LocalDateTime)
return result return result
} }
} }

View File

@ -25,6 +25,7 @@ import net.corda.testing.node.MockServices
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.Test import org.junit.Test
import java.lang.reflect.Method
import java.math.BigInteger import java.math.BigInteger
import java.net.URL import java.net.URL
import javax.persistence.* import javax.persistence.*
@ -32,7 +33,6 @@ import java.net.URLClassLoader
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
class SchemaMigrationTest { class SchemaMigrationTest {
@Test @Test
@ -82,7 +82,7 @@ class SchemaMigrationTest {
// check that the file was picked up // check that the file was picked up
val nrOfChangesOnDiscoveredFile = db.dataSource.connection.use { val nrOfChangesOnDiscoveredFile = db.dataSource.connection.use {
it.createStatement().executeQuery("select count(*) from DATABASECHANGELOG where filename ='migration/${fileName}'").use { rs -> it.createStatement().executeQuery("select count(*) from DATABASECHANGELOG where filename ='migration/$fileName'").use { rs ->
rs.next() rs.next()
rs.getInt(1) rs.getInt(1)
} }
@ -102,9 +102,11 @@ class SchemaMigrationTest {
} }
//hacky way to add a folder to the classpath //hacky way to add a folder to the classpath
fun addToClassPath(file: Path) = URLClassLoader::class.java.getDeclaredMethod("addURL", URL::class.java).apply { private fun addToClassPath(file: Path): Method {
isAccessible = true return URLClassLoader::class.java.getDeclaredMethod("addURL", URL::class.java).apply {
invoke(ClassLoader.getSystemClassLoader(), file.toFile().toURL()) isAccessible = true
invoke(ClassLoader.getSystemClassLoader(), file.toUri().toURL())
}
} }
object DummyTestSchema object DummyTestSchema
@ -116,9 +118,9 @@ class SchemaMigrationTest {
@ElementCollection @ElementCollection
@Column(name = "participants") @Column(name = "participants")
@CollectionTable(name = "dummy_test_states_parts", joinColumns = arrayOf( @CollectionTable(name = "dummy_test_states_parts", joinColumns = [
JoinColumn(name = "output_index", referencedColumnName = "output_index"), JoinColumn(name = "output_index", referencedColumnName = "output_index"),
JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))) JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id")])
override var participants: MutableSet<AbstractParty>? = null, override var participants: MutableSet<AbstractParty>? = null,
@Transient @Transient

View File

@ -15,6 +15,7 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.flows.* import net.corda.core.flows.*
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.InputStreamAndHash import net.corda.core.internal.InputStreamAndHash
import net.corda.core.node.services.AttachmentId
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.common.internal.testNetworkParameters
@ -31,6 +32,7 @@ import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import java.io.InputStream
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
@ -67,10 +69,10 @@ class MaxTransactionSizeTests {
val bigFile3 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 2) val bigFile3 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 2)
val bigFile4 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 3) val bigFile4 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 3)
val flow = aliceNode.transaction { val flow = aliceNode.transaction {
val hash1 = aliceNode.services.attachments.importAttachment(bigFile1.inputStream) val hash1 = aliceNode.importAttachment(bigFile1.inputStream)
val hash2 = aliceNode.services.attachments.importAttachment(bigFile2.inputStream) val hash2 = aliceNode.importAttachment(bigFile2.inputStream)
val hash3 = aliceNode.services.attachments.importAttachment(bigFile3.inputStream) val hash3 = aliceNode.importAttachment(bigFile3.inputStream)
val hash4 = aliceNode.services.attachments.importAttachment(bigFile4.inputStream) val hash4 = aliceNode.importAttachment(bigFile4.inputStream)
assertEquals(hash1, bigFile1.sha256) assertEquals(hash1, bigFile1.sha256)
SendLargeTransactionFlow(notary, bob, hash1, hash2, hash3, hash4) SendLargeTransactionFlow(notary, bob, hash1, hash2, hash3, hash4)
} }
@ -90,10 +92,10 @@ class MaxTransactionSizeTests {
val bigFile3 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 2) val bigFile3 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 2)
val bigFile4 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 3) val bigFile4 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024, 3)
val flow = aliceNode.transaction { val flow = aliceNode.transaction {
val hash1 = aliceNode.services.attachments.importAttachment(bigFile1.inputStream) val hash1 = aliceNode.importAttachment(bigFile1.inputStream)
val hash2 = aliceNode.services.attachments.importAttachment(bigFile2.inputStream) val hash2 = aliceNode.importAttachment(bigFile2.inputStream)
val hash3 = aliceNode.services.attachments.importAttachment(bigFile3.inputStream) val hash3 = aliceNode.importAttachment(bigFile3.inputStream)
val hash4 = aliceNode.services.attachments.importAttachment(bigFile4.inputStream) val hash4 = aliceNode.importAttachment(bigFile4.inputStream)
assertEquals(hash1, bigFile1.sha256) assertEquals(hash1, bigFile1.sha256)
SendLargeTransactionFlow(notary, bob, hash1, hash2, hash3, hash4, verify = false) SendLargeTransactionFlow(notary, bob, hash1, hash2, hash3, hash4, verify = false)
} }
@ -104,6 +106,10 @@ class MaxTransactionSizeTests {
} }
} }
private fun StartedMockNode.importAttachment(inputStream: InputStream): AttachmentId {
return services.attachments.importAttachment(inputStream, "test", null)
}
@StartableByRPC @StartableByRPC
@InitiatingFlow @InitiatingFlow
class SendLargeTransactionFlow(private val notary: Party, class SendLargeTransactionFlow(private val notary: Party,

View File

@ -51,7 +51,6 @@ import org.junit.Test
import org.junit.rules.ExpectedException import org.junit.rules.ExpectedException
import org.junit.rules.ExternalResource import org.junit.rules.ExternalResource
import java.time.Duration import java.time.Duration
import java.time.Instant
import java.time.LocalDate import java.time.LocalDate
import java.time.ZoneOffset import java.time.ZoneOffset
import java.time.temporal.ChronoUnit import java.time.temporal.ChronoUnit
@ -113,7 +112,7 @@ open class VaultQueryTestRule : ExternalResource(), VaultQueryParties {
override val bob = TestIdentity(BOB_NAME, 80) override val bob = TestIdentity(BOB_NAME, 80)
override val cashNotary = TestIdentity(CordaX500Name("Cash Notary Service", "Zurich", "CH"), 21) override val cashNotary = TestIdentity(CordaX500Name("Cash Notary Service", "Zurich", "CH"), 21)
override val charlie = TestIdentity(CHARLIE_NAME, 90) override val charlie = TestIdentity(CHARLIE_NAME, 90)
override val dummyCashIssuer = TestIdentity(CordaX500Name("Snake Oil Issuer", "London", "GB"), 10) final override val dummyCashIssuer = TestIdentity(CordaX500Name("Snake Oil Issuer", "London", "GB"), 10)
override val DUMMY_CASH_ISSUER = dummyCashIssuer.ref(1) override val DUMMY_CASH_ISSUER = dummyCashIssuer.ref(1)
override val dummyNotary = TestIdentity(DUMMY_NOTARY_NAME, 20) override val dummyNotary = TestIdentity(DUMMY_NOTARY_NAME, 20)
override val DUMMY_OBLIGATION_ISSUER = TestIdentity(CordaX500Name("Snake Oil Issuer", "London", "GB"), 10).party override val DUMMY_OBLIGATION_ISSUER = TestIdentity(CordaX500Name("Snake Oil Issuer", "London", "GB"), 10).party
@ -143,7 +142,7 @@ open class VaultQueryTestRule : ExternalResource(), VaultQueryParties {
cordappPackages, cordappPackages,
makeTestIdentityService(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, dummyCashIssuer.identity, dummyNotary.identity), makeTestIdentityService(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, dummyCashIssuer.identity, dummyNotary.identity),
megaCorp, megaCorp,
moreKeys = DUMMY_NOTARY_KEY) moreKeys = *arrayOf(DUMMY_NOTARY_KEY))
database = databaseAndServices.first database = databaseAndServices.first
services = databaseAndServices.second services = databaseAndServices.second
vaultFiller = VaultFiller(services, dummyNotary) vaultFiller = VaultFiller(services, dummyNotary)
@ -161,7 +160,7 @@ open class VaultQueryTestRule : ExternalResource(), VaultQueryParties {
} }
} }
class VaultQueryRollbackRule(val vaultQueryParties: VaultQueryParties) : ExternalResource() { class VaultQueryRollbackRule(private val vaultQueryParties: VaultQueryParties) : ExternalResource() {
lateinit var transaction: DatabaseTransaction lateinit var transaction: DatabaseTransaction

View File

@ -75,7 +75,7 @@ class VaultWithCashTest {
private val servicesKey = generateKeyPair() private val servicesKey = generateKeyPair()
lateinit var services: MockServices lateinit var services: MockServices
private lateinit var vaultFiller: VaultFiller private lateinit var vaultFiller: VaultFiller
lateinit var issuerServices: MockServices private lateinit var issuerServices: MockServices
val vaultService: VaultService get() = services.vaultService val vaultService: VaultService get() = services.vaultService
lateinit var database: CordaPersistence lateinit var database: CordaPersistence
private lateinit var notaryServices: MockServices private lateinit var notaryServices: MockServices
@ -88,7 +88,7 @@ class VaultWithCashTest {
cordappPackages, cordappPackages,
makeTestIdentityService(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, dummyCashIssuer.identity, dummyNotary.identity), makeTestIdentityService(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, dummyCashIssuer.identity, dummyNotary.identity),
TestIdentity(MEGA_CORP.name, servicesKey), TestIdentity(MEGA_CORP.name, servicesKey),
moreKeys = dummyNotary.keyPair) moreKeys = *arrayOf(dummyNotary.keyPair))
database = databaseAndServices.first database = databaseAndServices.first
services = databaseAndServices.second services = databaseAndServices.second
vaultFiller = VaultFiller(services, dummyNotary) vaultFiller = VaultFiller(services, dummyNotary)
@ -141,7 +141,7 @@ class VaultWithCashTest {
database.transaction { database.transaction {
// A tx that spends our money. // A tx that spends our money.
val spendTXBuilder = TransactionBuilder(DUMMY_NOTARY) val spendTXBuilder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, spendTXBuilder, 80.DOLLARS, BOB) Cash.generateSpend(services, spendTXBuilder, 80.DOLLARS, services.myInfo.legalIdentitiesAndCerts.single(), BOB)
val spendPTX = services.signInitialTransaction(spendTXBuilder, freshKey) val spendPTX = services.signInitialTransaction(spendTXBuilder, freshKey)
notaryServices.addSignature(spendPTX) notaryServices.addSignature(spendPTX)
} }
@ -189,7 +189,7 @@ class VaultWithCashTest {
val first = backgroundExecutor.fork { val first = backgroundExecutor.fork {
database.transaction { database.transaction {
val txn1Builder = TransactionBuilder(DUMMY_NOTARY) val txn1Builder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, txn1Builder, 60.DOLLARS, BOB) Cash.generateSpend(services, txn1Builder, 60.DOLLARS, services.myInfo.legalIdentitiesAndCerts.single(), BOB)
val ptxn1 = notaryServices.signInitialTransaction(txn1Builder) val ptxn1 = notaryServices.signInitialTransaction(txn1Builder)
val txn1 = services.addSignature(ptxn1, freshKey) val txn1 = services.addSignature(ptxn1, freshKey)
println("txn1: ${txn1.id} spent ${((txn1.tx.outputs[0].data) as Cash.State).amount}") println("txn1: ${txn1.id} spent ${((txn1.tx.outputs[0].data) as Cash.State).amount}")
@ -220,7 +220,7 @@ class VaultWithCashTest {
val second = backgroundExecutor.fork { val second = backgroundExecutor.fork {
database.transaction { database.transaction {
val txn2Builder = TransactionBuilder(DUMMY_NOTARY) val txn2Builder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, txn2Builder, 80.DOLLARS, BOB) Cash.generateSpend(services, txn2Builder, 80.DOLLARS, services.myInfo.legalIdentitiesAndCerts.single(), BOB)
val ptxn2 = notaryServices.signInitialTransaction(txn2Builder) val ptxn2 = notaryServices.signInitialTransaction(txn2Builder)
val txn2 = services.addSignature(ptxn2, freshKey) val txn2 = services.addSignature(ptxn2, freshKey)
println("txn2: ${txn2.id} spent ${((txn2.tx.outputs[0].data) as Cash.State).amount}") println("txn2: ${txn2.id} spent ${((txn2.tx.outputs[0].data) as Cash.State).amount}")
@ -344,7 +344,7 @@ class VaultWithCashTest {
database.transaction { database.transaction {
// A tx that spends our money. // A tx that spends our money.
val spendTXBuilder = TransactionBuilder(DUMMY_NOTARY) val spendTXBuilder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, spendTXBuilder, 80.DOLLARS, BOB) Cash.generateSpend(services, spendTXBuilder, 80.DOLLARS, services.myInfo.legalIdentitiesAndCerts.single(), BOB)
val spendPTX = notaryServices.signInitialTransaction(spendTXBuilder) val spendPTX = notaryServices.signInitialTransaction(spendTXBuilder)
val spendTX = services.addSignature(spendPTX, freshKey) val spendTX = services.addSignature(spendPTX, freshKey)
services.recordTransactions(spendTX) services.recordTransactions(spendTX)

View File

@ -23,7 +23,6 @@ import rx.Observable
import rx.subjects.PublishSubject import rx.subjects.PublishSubject
import java.io.Closeable import java.io.Closeable
import java.util.* import java.util.*
import kotlin.test.fail
class ObservablesTests { class ObservablesTests {
private fun isInDatabaseTransaction() = contextTransactionOrNull != null private fun isInDatabaseTransaction() = contextTransactionOrNull != null
@ -68,7 +67,7 @@ class ObservablesTests {
assertThat(secondEvent.get()).isEqualTo(0 to false) assertThat(secondEvent.get()).isEqualTo(0 to false)
} }
class TestException : Exception("Synthetic exception for tests") {} class TestException : Exception("Synthetic exception for tests")
@Test @Test
fun `bufferUntilDatabaseCommit swallows if transaction rolled back`() { fun `bufferUntilDatabaseCommit swallows if transaction rolled back`() {
@ -93,7 +92,6 @@ class ObservablesTests {
assertThat(secondEvent.isDone).isFalse() assertThat(secondEvent.isDone).isFalse()
throw TestException() throw TestException()
} }
fail("Should not have successfully completed transaction")
} catch (e: TestException) { } catch (e: TestException) {
} }
assertThat(secondEvent.isDone).isFalse() assertThat(secondEvent.isDone).isFalse()
@ -125,7 +123,6 @@ class ObservablesTests {
assertThat(secondEvent.isDone).isFalse() assertThat(secondEvent.isDone).isFalse()
throw TestException() throw TestException()
} }
fail("Should not have successfully completed transaction")
} catch (e: TestException) { } catch (e: TestException) {
} }
assertThat(secondEvent.isDone).isTrue() assertThat(secondEvent.isDone).isTrue()

View File

@ -40,7 +40,6 @@ class LinearStateBatchNotariseContract : Contract {
} }
override fun verify(tx: LedgerTransaction) { override fun verify(tx: LedgerTransaction) {
val command = tx.commands.requireSingleCommand<Commands>() tx.commands.requireSingleCommand<Commands>()
val timeWindow: TimeWindow? = tx.timeWindow
} }
} }

View File

@ -230,27 +230,6 @@ abstract class OnLedgerAsset<T : Any, C : CommandData, S : FungibleAsset<T>> : C
return Pair(gathered, gatheredAmount) return Pair(gathered, gatheredAmount)
} }
/**
* Generate an transaction exiting fungible assets from the ledger.
*
* @param tx transaction builder to add states and commands to.
* @param amountIssued the amount to be exited, represented as a quantity of issued currency.
* @param assetStates the asset states to take funds from. No checks are done about ownership of these states, it is
* the responsibility of the caller to check that they do not attempt to exit funds held by others.
* @return the public keys which must sign the transaction for it to be valid.
*/
@Throws(InsufficientBalanceException::class)
@JvmStatic
@Deprecated("Replaced with generateExit() which takes in a party to pay change to")
fun <S : FungibleAsset<T>, T: Any> generateExit(tx: TransactionBuilder, amountIssued: Amount<Issued<T>>,
assetStates: List<StateAndRef<S>>,
deriveState: (TransactionState<S>, Amount<Issued<T>>, AbstractParty) -> TransactionState<S>,
generateMoveCommand: () -> CommandData,
generateExitCommand: (Amount<Issued<T>>) -> CommandData): Set<PublicKey> {
val owner = assetStates.map { it.state.data.owner }.toSet().firstOrNull() ?: throw InsufficientBalanceException(amountIssued)
return generateExit(tx, amountIssued, assetStates, owner, deriveState, generateMoveCommand, generateExitCommand)
}
/** /**
* Generate an transaction exiting fungible assets from the ledger. * Generate an transaction exiting fungible assets from the ledger.
* *
@ -323,31 +302,6 @@ abstract class OnLedgerAsset<T : Any, C : CommandData, S : FungibleAsset<T>> : C
abstract fun extractCommands(commands: Collection<CommandWithParties<CommandData>>): Collection<CommandWithParties<C>> abstract fun extractCommands(commands: Collection<CommandWithParties<CommandData>>): Collection<CommandWithParties<C>>
/**
* Generate an transaction exiting assets from the ledger.
*
* @param tx transaction builder to add states and commands to.
* @param amountIssued the amount to be exited, represented as a quantity of issued currency.
* @param assetStates the asset states to take funds from. No checks are done about ownership of these states, it is
* the responsibility of the caller to check that they do not exit funds held by others.
* @param payChangeTo party to pay any change to; this is normally a confidential identity of the calling
* party.
* @return the public keys which must sign the transaction for it to be valid.
*/
@Throws(InsufficientBalanceException::class)
@Deprecated("Replaced with generateExit() which takes in a party to pay change to")
fun generateExit(tx: TransactionBuilder, amountIssued: Amount<Issued<T>>,
assetStates: List<StateAndRef<S>>): Set<PublicKey> {
return generateExit(
tx,
amountIssued,
assetStates,
deriveState = { state, amount, owner -> deriveState(state, amount, owner) },
generateMoveCommand = { -> generateMoveCommand() },
generateExitCommand = { amount -> generateExitCommand(amount) }
)
}
/** /**
* Generate an transaction exiting assets from the ledger. * Generate an transaction exiting assets from the ledger.
* *
@ -367,8 +321,8 @@ abstract class OnLedgerAsset<T : Any, C : CommandData, S : FungibleAsset<T>> : C
assetStates, assetStates,
payChangeTo, payChangeTo,
deriveState = { state, amount, owner -> deriveState(state, amount, owner) }, deriveState = { state, amount, owner -> deriveState(state, amount, owner) },
generateMoveCommand = { -> generateMoveCommand() }, generateMoveCommand = { generateMoveCommand() },
generateExitCommand = { amount -> generateExitCommand(amount) } generateExitCommand = { generateExitCommand(it) }
) )
} }

View File

@ -14,22 +14,18 @@ import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.StateRef import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionState
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.node.services.StatesNotAvailableException import net.corda.core.node.services.StatesNotAvailableException
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.deserialize
import net.corda.core.utilities.* import net.corda.core.utilities.*
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
import net.corda.core.internal.uncheckedCast
import java.sql.* import java.sql.*
import java.util.* import java.util.*
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
/** /**
* Pluggable interface to allow for different cash selection provider implementations * Pluggable interface to allow for different cash selection provider implementations
@ -41,17 +37,17 @@ import kotlin.concurrent.withLock
abstract class AbstractCashSelection(private val maxRetries: Int = 8, private val retrySleep: Int = 100, abstract class AbstractCashSelection(private val maxRetries: Int = 8, private val retrySleep: Int = 100,
private val retryCap: Int = 2000) { private val retryCap: Int = 2000) {
companion object { companion object {
val instance = AtomicReference<AbstractCashSelection>() private val instance = AtomicReference<AbstractCashSelection>()
fun getInstance(metadata: () -> java.sql.DatabaseMetaData): AbstractCashSelection { fun getInstance(metadata: () -> java.sql.DatabaseMetaData): AbstractCashSelection {
return instance.get() ?: { return instance.get() ?: {
val _metadata = metadata() val metadataResult = metadata()
val cashSelectionAlgos = ServiceLoader.load(AbstractCashSelection::class.java).toList() val cashSelectionAlgos = ServiceLoader.load(AbstractCashSelection::class.java).toList()
val cashSelectionAlgo = cashSelectionAlgos.firstOrNull { it.isCompatible(_metadata) } val cashSelectionAlgo = cashSelectionAlgos.firstOrNull { it.isCompatible(metadataResult) }
cashSelectionAlgo?.let { cashSelectionAlgo?.let {
instance.set(cashSelectionAlgo) instance.set(cashSelectionAlgo)
cashSelectionAlgo cashSelectionAlgo
} ?: throw ClassNotFoundException("\nUnable to load compatible cash selection algorithm implementation for JDBC driver ($_metadata)." + } ?: throw ClassNotFoundException("\nUnable to load compatible cash selection algorithm implementation for JDBC driver ($metadataResult)." +
"\nPlease specify an implementation in META-INF/services/${AbstractCashSelection::class.java}") "\nPlease specify an implementation in META-INF/services/${AbstractCashSelection::class.java}")
}.invoke() }.invoke()
} }
@ -84,7 +80,7 @@ abstract class AbstractCashSelection(private val maxRetries: Int = 8, private va
abstract fun executeQuery(connection: Connection, amount: Amount<Currency>, lockId: UUID, notary: Party?, abstract fun executeQuery(connection: Connection, amount: Amount<Currency>, lockId: UUID, notary: Party?,
onlyFromIssuerParties: Set<AbstractParty>, withIssuerRefs: Set<OpaqueBytes>, withResultSet: (ResultSet) -> Boolean): Boolean onlyFromIssuerParties: Set<AbstractParty>, withIssuerRefs: Set<OpaqueBytes>, withResultSet: (ResultSet) -> Boolean): Boolean
override abstract fun toString(): String abstract override fun toString(): String
/** /**
* Query to gather Cash states that are available and retry if they are temporarily unavailable. * Query to gather Cash states that are available and retry if they are temporarily unavailable.
@ -149,7 +145,7 @@ abstract class AbstractCashSelection(private val maxRetries: Int = 8, private va
if (stateRefs.isNotEmpty()) { if (stateRefs.isNotEmpty()) {
// TODO: future implementation to retrieve contract states from a Vault BLOB store // TODO: future implementation to retrieve contract states from a Vault BLOB store
stateAndRefs.addAll(services.loadStates(stateRefs) as Collection<StateAndRef<Cash.State>>) stateAndRefs.addAll(uncheckedCast(services.loadStates(stateRefs)))
} }
val success = stateAndRefs.isNotEmpty() && totalPennies >= amount.quantity val success = stateAndRefs.isNotEmpty() && totalPennies >= amount.quantity

View File

@ -13,6 +13,9 @@ package com.r3.corda.enterprise.perftestcordapp.flows
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.cash.selection.AbstractCashSelection import com.r3.corda.enterprise.perftestcordapp.contracts.asset.cash.selection.AbstractCashSelection
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
import com.r3.corda.enterprise.perftestcordapp.issuedBy import com.r3.corda.enterprise.perftestcordapp.issuedBy
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.contracts.InsufficientBalanceException import net.corda.core.contracts.InsufficientBalanceException
@ -60,10 +63,13 @@ class CashExitFlow(private val amount: Amount<Currency>,
.getInstance { serviceHub.jdbcSession().metaData } .getInstance { serviceHub.jdbcSession().metaData }
.unconsumedCashStatesForSpending(serviceHub, amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference)) .unconsumedCashStatesForSpending(serviceHub, amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))
val signers = try { val signers = try {
val changeOwner = exitStates.map { it.state.data.owner }.toSet().firstOrNull() ?: throw InsufficientBalanceException(amount)
Cash().generateExit( Cash().generateExit(
builder, builder,
amount.issuedBy(issuer), amount.issuedBy(issuer),
exitStates) exitStates,
changeOwner
)
} catch (e: InsufficientBalanceException) { } catch (e: InsufficientBalanceException) {
throw CashException("Exiting more cash than exists", e) throw CashException("Exiting more cash than exists", e)
} }

View File

@ -14,6 +14,10 @@ import co.paralleluniverse.fibers.Suspendable
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.OnLedgerAsset import com.r3.corda.enterprise.perftestcordapp.contracts.asset.OnLedgerAsset
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.PartyAndAmount import com.r3.corda.enterprise.perftestcordapp.contracts.asset.PartyAndAmount
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_ID
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
import net.corda.confidential.SwapIdentitiesFlow import net.corda.confidential.SwapIdentitiesFlow
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.flows.FlowException import net.corda.core.flows.FlowException
@ -23,6 +27,7 @@ import net.corda.core.flows.StartableByRPC
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.uncheckedCast
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.ProgressTracker
@ -54,7 +59,7 @@ class CashIssueAndDoublePayment(val amount: Amount<Currency>,
= txState.copy(data = txState.data.copy(amount = amt, owner = owner)) = txState.copy(data = txState.data.copy(amount = amt, owner = owner))
val issueResult = subFlow(CashIssueFlow(amount, issueRef, notary)) val issueResult = subFlow(CashIssueFlow(amount, issueRef, notary))
val cashStateAndRef = serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single() as StateAndRef<Cash.State> val cashStateAndRef: StateAndRef<Cash.State> = uncheckedCast(serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single())
progressTracker.currentStep = GENERATING_ID progressTracker.currentStep = GENERATING_ID
val txIdentities = if (anonymous) { val txIdentities = if (anonymous) {
@ -86,7 +91,7 @@ class CashIssueAndDoublePayment(val amount: Amount<Currency>,
progressTracker.currentStep = FINALISING_TX progressTracker.currentStep = FINALISING_TX
val notarised1 = finaliseTx(tx1, setOf(recipient), "Unable to notarise spend first time") val notarised1 = finaliseTx(tx1, setOf(recipient), "Unable to notarise spend first time")
try { try {
val notarised2 = finaliseTx(tx2, setOf(recipient), "Unable to notarise spend second time") finaliseTx(tx2, setOf(recipient), "Unable to notarise spend second time")
} catch (expected: CashException) { } catch (expected: CashException) {
val cause = expected.cause val cause = expected.cause
if (cause is NotaryException) { if (cause is NotaryException) {

View File

@ -14,12 +14,17 @@ import co.paralleluniverse.fibers.Suspendable
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.OnLedgerAsset import com.r3.corda.enterprise.perftestcordapp.contracts.asset.OnLedgerAsset
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.PartyAndAmount import com.r3.corda.enterprise.perftestcordapp.contracts.asset.PartyAndAmount
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_ID
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
import net.corda.confidential.SwapIdentitiesFlow import net.corda.confidential.SwapIdentitiesFlow
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.flows.StartableByRPC import net.corda.core.flows.StartableByRPC
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.uncheckedCast
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.ProgressTracker
@ -51,7 +56,7 @@ class CashIssueAndDuplicatePayment(val amount: Amount<Currency>,
= txState.copy(data = txState.data.copy(amount = amt, owner = owner)) = txState.copy(data = txState.data.copy(amount = amt, owner = owner))
val issueResult = subFlow(CashIssueFlow(amount, issueRef, notary)) val issueResult = subFlow(CashIssueFlow(amount, issueRef, notary))
val cashStateAndRef = serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single() as StateAndRef<Cash.State> val cashStateAndRef: StateAndRef<Cash.State> = uncheckedCast(serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single())
progressTracker.currentStep = GENERATING_ID progressTracker.currentStep = GENERATING_ID
val txIdentities = if (anonymous) { val txIdentities = if (anonymous) {
@ -74,7 +79,7 @@ class CashIssueAndDuplicatePayment(val amount: Amount<Currency>,
val tx = serviceHub.signInitialTransaction(spendTx, keysForSigning) val tx = serviceHub.signInitialTransaction(spendTx, keysForSigning)
progressTracker.currentStep = FINALISING_TX progressTracker.currentStep = FINALISING_TX
val notarised1 = finaliseTx(tx, setOf(recipient), "Unable to notarise spend first time") finaliseTx(tx, setOf(recipient), "Unable to notarise spend first time")
val notarised2 = finaliseTx(tx, setOf(recipient), "Unable to notarise spend second time") val notarised2 = finaliseTx(tx, setOf(recipient), "Unable to notarise spend second time")
return Result(notarised2.id, recipient) return Result(notarised2.id, recipient)

View File

@ -14,12 +14,17 @@ import co.paralleluniverse.fibers.Suspendable
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.OnLedgerAsset import com.r3.corda.enterprise.perftestcordapp.contracts.asset.OnLedgerAsset
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.PartyAndAmount import com.r3.corda.enterprise.perftestcordapp.contracts.asset.PartyAndAmount
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_ID
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
import net.corda.confidential.SwapIdentitiesFlow import net.corda.confidential.SwapIdentitiesFlow
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.flows.StartableByRPC import net.corda.core.flows.StartableByRPC
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.uncheckedCast
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.ProgressTracker
@ -51,7 +56,7 @@ class CashIssueAndPaymentNoSelection(val amount: Amount<Currency>,
progressTracker.currentStep = GENERATING_TX progressTracker.currentStep = GENERATING_TX
val issueResult = subFlow(CashIssueFlow(amount, issueRef, notary)) val issueResult = subFlow(CashIssueFlow(amount, issueRef, notary))
val cashStateAndRef = serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single() as StateAndRef<Cash.State> val cashStateAndRef: StateAndRef<Cash.State> = uncheckedCast(serviceHub.loadStates(setOf(StateRef(issueResult.id, 0))).single())
progressTracker.currentStep = GENERATING_ID progressTracker.currentStep = GENERATING_ID
val txIdentities = if (anonymous) { val txIdentities = if (anonymous) {

View File

@ -12,6 +12,9 @@ package com.r3.corda.enterprise.perftestcordapp.flows
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
import com.r3.corda.enterprise.perftestcordapp.issuedBy import com.r3.corda.enterprise.perftestcordapp.issuedBy
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.flows.StartableByRPC import net.corda.core.flows.StartableByRPC

View File

@ -12,6 +12,10 @@ package com.r3.corda.enterprise.perftestcordapp.flows
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.FINALISING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_ID
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.GENERATING_TX
import com.r3.corda.enterprise.perftestcordapp.flows.AbstractCashFlow.Companion.SIGNING_TX
import net.corda.confidential.SwapIdentitiesFlow import net.corda.confidential.SwapIdentitiesFlow
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.contracts.InsufficientBalanceException import net.corda.core.contracts.InsufficientBalanceException

Some files were not shown because too many files have changed in this diff Show More