diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 0000000000..2d31baad9b --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,137 @@ +# List of Contributors + +We'd like to thank the following people for contributing ideas to Corda, +either during architecture review sessions of the R3 Architecture Working Group, +or in design reviews since Corda has been open-sourced. Some people have moved to +a different organisation since their contribution. Please forgive any omissions, and +create a pull request, or email , if you wish to see +changes to this list. + +* Alberto Arri (R3) +* Andras Slemmer (R3) +* Andrius Dagys (R3) +* Andrzej Cichocki (R3) +* Anthony Coates (Deutsche Bank) +* Anton Semenov (Commerzbank) +* Antonio Cerrato (SEB) +* Anthony Woolley (Société Générale) +* Arnaud Stevens (Natixis) +* Arijit Das (Northern Trust) +* Arun Battu (BNY Mellon) +* Austin Moothart (R3) +* Barry Childe (HSBC) +* Barry Flower (Westpac) +* Benjamin Abineri (R3) +* Benoit Lafontaine (OCTO) +* Berit Bourgonje (ING) +* Bob Crozier (AIA) +* Bogdan Paunescu (R3) +* Cais Manai (R3) +* Carl Worrall (BCS) +* Chaitanya Jadhav (HSBC) +* Chris Akers (R3) +* Chris Burlinchon (R3) +* Chris Rankin (R3) +* Christian Kaufmann (Credit Suisse) +* Christian Sailer (R3) +* Christopher Saunders (Credit Suisse) +* Christopher Swanson (US Bank) +* Clark Thompson (R3) +* Clay Ratliff (Thoughtworks) +* Clemens Wan (R3) +* Clinton Alexander (R3) +* Daniel Roig (SEB) +* Dave Hudson (R3) +* David Lee (BCS) +* Farzad Pezeshkpour (RBS) +* Frederic Dalibard (Natixis) +* Garrett Macey (Wells Fargo) +* Gavin Thomas (R3) +* George Marcel Smetana (Bradesco) +* Giulio Katis (Westpac) +* Giuseppe Cardone (Intesa Sanpaolo) +* Guy Hochstetler (IBM) +* Ian Cusden (UBS) +* Ian Grigg (R3) +* Igor Nitto (R3) +* Igor Panov (CIBC) +* Ivan Schasny (R3) +* James Brown (R3) +* James Carlyle (R3) +* Jared Harwayne-Gidansky (BNY Mellon) +* Joel Dudley (R3) +* Johan Hörmark (SEB) +* Johann Palychata (BNP Paribas) +* Jonathan Sartin (R3) +* Jose Coll (R3) +* Jose Luu (Natixis) +* Josh Lindl (BCS) +* Justin Chapman (Northern Trust) +* Kai-Michael Schramm (Credit Suisse) +* Karel Hajek (Barclays Capital) +* Kasia Streich (R3) +* Kat Baker (R3) +* Khaild Ahmed (Northern Trust) +* Klaus Apolinario (Bradesco) +* Koen Vingerhoets (KBC) +* Kostas Chalkias (R3) +* Lars Stage Thomsen (Danske Bank) +* Lee Braine (Barclays) +* Lucas Salmen (Itau) +* Maksymillian Pawlak (R3) +* Marek Scocovsky (ABSA) +* Mark Lauer (Westpac) +* Mark Oldfield (R3) +* Mark Raynes (Thomson Reuters) +* Mark Simpson (RBS) +* Mark Tiggas (Wells Fargo) +* Massimo Morini (Banca IMI) +* Mat Rizzo (R3) +* Matt Britton (BCS) +* Matthew Nesbit (R3) +* Matthijs van den Bos (ING) +* Michal Kit (R3) +* Micheal Hinstridge (Thoughtworks) +* Michelle Sollecito (R3) +* Mike Hearn (R3) +* Mike Reichelt (US Bank) +* Mustafa Ozturk (Natixis) +* Nick Skinner (Northern Trust) +* Nigel King (R3) +* Nuam Athaweth (MUFG) +* Oscar Zibordi de Paiva (Bradesco) +* Patrick Kuo (R3) +* Pekka Kaipio (OP Financial) +* Piotr Piskorski (Nordea) +* Przemyslaw Bak (R3) +* Rex Maudsley (Société Générale) +* Richard Green (R3) +* Rick Parker (R3) +* Rhett Brewer (Goldman Sachs) +* Roberto Karpinski (Bradesco) +* Robin Green (CIBC) +* Rodrigo Bueno (Itau) +* Roger Willis (R3) +* Ross Burnett (Macquarie) +* Ross Nicoll (R3) +* Sajindra Jayasena (Deutsche Bank) +* Saket Sharma (BNY Mellon) +* Sam Chadwick (Thomson Reuters) +* Sasmit Sahu (Credit Suisse) +* Scott James (Credit Suisse) +* Shams Asari (R3) +* Simon Taylor (Barclays) +* Sofus Mortensen (Digital Asset Holdings) +* Szymon Sztuka (R3) +* Stephen Lane-Smith (BMO) +* Thomas O'Donnell (Macquarie) +* Thomas Schroeter (R3) +* Tom Menner (R3) +* Tudor Malene (R3) +* Tim Swanson (R3) +* Timothy Smith (Credit Suisse) +* Tommy Lillehagen (R3) +* Viktor Kolomeyko (R3) +* Wawrzek Niewodniczanski (R3) +* Wei Wu Zhang (Commonwealth Bank of Australia) +* Zabrina Smith (Northern Trust) \ No newline at end of file diff --git a/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt b/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt index ad83ee723e..b70d60bd55 100644 --- a/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt +++ b/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt @@ -28,7 +28,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.driver.driver import org.junit.Test diff --git a/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java b/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java index 698aca77c9..01966d3a97 100644 --- a/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java +++ b/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java @@ -10,7 +10,7 @@ import net.corda.finance.flows.CashPaymentFlow; import net.corda.finance.schemas.CashSchemaV1; import net.corda.node.internal.Node; import net.corda.node.internal.StartedNode; -import net.corda.nodeapi.User; +import net.corda.nodeapi.internal.config.User; import net.corda.testing.CoreTestUtils; import net.corda.testing.internal.NodeBasedTest; import org.junit.After; diff --git a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt index fd14bf35d0..5c14c3becb 100644 --- a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt +++ b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt @@ -20,7 +20,7 @@ import net.corda.node.internal.Node import net.corda.node.internal.StartedNode import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.internal.NodeBasedTest import org.apache.activemq.artemis.api.core.ActiveMQSecurityException diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt index f7318b34b3..756f07216e 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt @@ -15,7 +15,7 @@ import net.corda.core.utilities.* import net.corda.nodeapi.ArtemisTcpTransport.Companion.tcpTransport import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.RPCApi -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.TransportConfiguration import org.apache.activemq.artemis.api.core.client.ActiveMQClient diff --git a/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java b/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java index 66e1880100..30edeeb897 100644 --- a/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java +++ b/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java @@ -9,7 +9,7 @@ import net.corda.core.messaging.FlowHandle; import net.corda.core.utilities.OpaqueBytes; import net.corda.finance.flows.AbstractCashFlow; import net.corda.finance.flows.CashIssueFlow; -import net.corda.nodeapi.User; +import net.corda.nodeapi.internal.config.User; import net.corda.smoketesting.NodeConfig; import net.corda.smoketesting.NodeProcess; import org.junit.After; diff --git a/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt b/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt index 23018f7bfb..09e739819a 100644 --- a/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt +++ b/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt @@ -21,7 +21,7 @@ import net.corda.finance.contracts.getCashBalance import net.corda.finance.contracts.getCashBalances import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.smoketesting.NodeConfig import net.corda.smoketesting.NodeProcess import org.apache.commons.io.output.NullOutputStream diff --git a/client/rpc/src/test/kotlin/net/corda/client/rpc/AbstractRPCTest.kt b/client/rpc/src/test/kotlin/net/corda/client/rpc/AbstractRPCTest.kt index 0c552f8128..546415e247 100644 --- a/client/rpc/src/test/kotlin/net/corda/client/rpc/AbstractRPCTest.kt +++ b/client/rpc/src/test/kotlin/net/corda/client/rpc/AbstractRPCTest.kt @@ -5,7 +5,7 @@ import net.corda.core.internal.concurrent.flatMap import net.corda.core.internal.concurrent.map import net.corda.core.messaging.RPCOps import net.corda.node.services.messaging.RPCServerConfiguration -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.SerializationEnvironmentRule import net.corda.testing.internal.RPCDriverExposedDSLInterface import net.corda.testing.internal.rpcTestUser diff --git a/client/rpc/src/test/kotlin/net/corda/client/rpc/RPCPermissionsTests.kt b/client/rpc/src/test/kotlin/net/corda/client/rpc/RPCPermissionsTests.kt index 82f5c53afc..6e7de32087 100644 --- a/client/rpc/src/test/kotlin/net/corda/client/rpc/RPCPermissionsTests.kt +++ b/client/rpc/src/test/kotlin/net/corda/client/rpc/RPCPermissionsTests.kt @@ -4,7 +4,7 @@ import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.RPCOps import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.messaging.rpcContext -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.internal.RPCDriverExposedDSLInterface import net.corda.testing.internal.rpcDriver import org.junit.Test diff --git a/core/src/smoke-test/kotlin/net/corda/core/NodeVersioningTest.kt b/core/src/smoke-test/kotlin/net/corda/core/NodeVersioningTest.kt index f9844fbce0..f682bfcb75 100644 --- a/core/src/smoke-test/kotlin/net/corda/core/NodeVersioningTest.kt +++ b/core/src/smoke-test/kotlin/net/corda/core/NodeVersioningTest.kt @@ -7,7 +7,7 @@ import net.corda.core.identity.CordaX500Name import net.corda.core.internal.* import net.corda.core.messaging.startFlow import net.corda.core.utilities.getOrThrow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.smoketesting.NodeConfig import net.corda.smoketesting.NodeProcess import net.corda.testing.common.internal.ProjectStructure diff --git a/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt b/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt index 2f826b5f54..1f76e500fd 100644 --- a/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt +++ b/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt @@ -11,7 +11,7 @@ import net.corda.core.internal.list import net.corda.core.messaging.startFlow import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.unwrap -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.smoketesting.NodeConfig import net.corda.smoketesting.NodeProcess import net.corda.smoketesting.NodeProcess.Companion.CORDAPPS_DIR_NAME diff --git a/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt b/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt index 58501ad790..c0346e30fd 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt @@ -38,24 +38,20 @@ class PartialMerkleTreeTest { testLedger = ledger { unverifiedTransaction { attachments(Cash.PROGRAM_ID) - output(Cash.PROGRAM_ID, "MEGA_CORP cash") { + output(Cash.PROGRAM_ID, "MEGA_CORP cash", Cash.State( amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1), - owner = MEGA_CORP - ) - } - output(Cash.PROGRAM_ID, "dummy cash 1") { + owner = MEGA_CORP)) + output(Cash.PROGRAM_ID, "dummy cash 1", Cash.State( amount = 900.DOLLARS `issued by` MEGA_CORP.ref(1, 1), - owner = MINI_CORP - ) - } + owner = MINI_CORP)) } transaction { attachments(Cash.PROGRAM_ID) input("MEGA_CORP cash") output(Cash.PROGRAM_ID, "MEGA_CORP cash".output().copy(owner = MINI_CORP)) - command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() } + command(MEGA_CORP_PUBKEY, Cash.Commands.Move()) timeWindow(TEST_TX_TIME) this.verifies() } diff --git a/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt b/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt index 3287e4f260..a072d9ec34 100644 --- a/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt +++ b/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt @@ -19,7 +19,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.node.internal.SecureCordaRPCOps import net.corda.node.internal.StartedNode import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContractV2 diff --git a/core/src/test/kotlin/net/corda/core/flows/ReceiveAllFlowTests.kt b/core/src/test/kotlin/net/corda/core/flows/ReceiveAllFlowTests.kt index dd2dbab17f..2fc6be8955 100644 --- a/core/src/test/kotlin/net/corda/core/flows/ReceiveAllFlowTests.kt +++ b/core/src/test/kotlin/net/corda/core/flows/ReceiveAllFlowTests.kt @@ -20,6 +20,42 @@ class ReceiveMultipleFlowTests { mockNet.stopNodes() } + @Test + fun showcase_flows_as_closures() { + + val answer = 10.0 + val message = "Hello Ivan" + + val counterParty = nodes[1].info.singleIdentity() + + val initiatingFlow = @InitiatingFlow object : FlowLogic() { + + @Suspendable + override fun call(): Any { + val session = initiateFlow(counterParty) + return session.sendAndReceive(message).unwrap { it } + } + } + + nodes[1].registerInitiatedFlow(initiatingFlow::class) { session -> + object : FlowLogic() { + @Suspendable + override fun call() { + // this is a closure, meaning you can access variables outside its scope e.g., `answer`. + val receivedMessage = session.receive().unwrap { it } + logger.info("Got message from counterParty: $receivedMessage.") + assertThat(receivedMessage).isEqualTo(message) + session.send(answer) + } + } as FlowLogic + } + + val flow = nodes[0].services.startFlow(initiatingFlow) + mockNet.runNetwork() + val receivedAnswer = flow.resultFuture.getOrThrow() + assertThat(receivedAnswer).isEqualTo(answer) + } + @Test fun `receive all messages in parallel using map style`() { val doubleValue = 5.0 diff --git a/core/src/test/kotlin/net/corda/core/transactions/TransactionEncumbranceTests.kt b/core/src/test/kotlin/net/corda/core/transactions/TransactionEncumbranceTests.kt index 87015f9eb9..4cb955faa5 100644 --- a/core/src/test/kotlin/net/corda/core/transactions/TransactionEncumbranceTests.kt +++ b/core/src/test/kotlin/net/corda/core/transactions/TransactionEncumbranceTests.kt @@ -55,10 +55,10 @@ class TransactionEncumbranceTests { ledger { transaction { attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID) - input(Cash.PROGRAM_ID) { state } - output(Cash.PROGRAM_ID, encumbrance = 1) { stateWithNewOwner } - output(TEST_TIMELOCK_ID, "5pm time-lock") { timeLock } - command(MEGA_CORP.owningKey) { Cash.Commands.Move() } + input(Cash.PROGRAM_ID, state) + output(Cash.PROGRAM_ID, encumbrance = 1, contractState = stateWithNewOwner) + output(TEST_TIMELOCK_ID, "5pm time-lock", timeLock) + command(MEGA_CORP.owningKey, Cash.Commands.Move()) verifies() } } @@ -69,16 +69,16 @@ class TransactionEncumbranceTests { ledger { unverifiedTransaction { attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID) - output(Cash.PROGRAM_ID, "state encumbered by 5pm time-lock") { state } - output(TEST_TIMELOCK_ID, "5pm time-lock") { timeLock } + output(Cash.PROGRAM_ID, "state encumbered by 5pm time-lock", state) + output(TEST_TIMELOCK_ID, "5pm time-lock", timeLock) } // Un-encumber the output if the time of the transaction is later than the timelock. transaction { attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID) input("state encumbered by 5pm time-lock") input("5pm time-lock") - output(Cash.PROGRAM_ID) { stateWithNewOwner } - command(MEGA_CORP.owningKey) { Cash.Commands.Move() } + output(Cash.PROGRAM_ID, stateWithNewOwner) + command(MEGA_CORP.owningKey, Cash.Commands.Move()) timeWindow(FIVE_PM) verifies() } @@ -90,16 +90,16 @@ class TransactionEncumbranceTests { ledger { unverifiedTransaction { attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID) - output(Cash.PROGRAM_ID, "state encumbered by 5pm time-lock") { state } - output(TEST_TIMELOCK_ID, "5pm time-lock") { timeLock } + output(Cash.PROGRAM_ID, "state encumbered by 5pm time-lock", state) + output(TEST_TIMELOCK_ID, "5pm time-lock", timeLock) } // The time of the transaction is earlier than the time specified in the encumbering timelock. transaction { attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID) input("state encumbered by 5pm time-lock") input("5pm time-lock") - output(Cash.PROGRAM_ID) { state } - command(MEGA_CORP.owningKey) { Cash.Commands.Move() } + output(Cash.PROGRAM_ID, state) + command(MEGA_CORP.owningKey, Cash.Commands.Move()) timeWindow(FOUR_PM) this `fails with` "the time specified in the time-lock has passed" } @@ -111,14 +111,14 @@ class TransactionEncumbranceTests { ledger { unverifiedTransaction { attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID) - output(Cash.PROGRAM_ID, "state encumbered by 5pm time-lock", encumbrance = 1) { state } - output(TEST_TIMELOCK_ID, "5pm time-lock") { timeLock } + output(Cash.PROGRAM_ID, "state encumbered by 5pm time-lock", encumbrance = 1, contractState = state) + output(TEST_TIMELOCK_ID, "5pm time-lock", timeLock) } transaction { attachments(Cash.PROGRAM_ID) input("state encumbered by 5pm time-lock") - output(Cash.PROGRAM_ID) { stateWithNewOwner } - command(MEGA_CORP.owningKey) { Cash.Commands.Move() } + output(Cash.PROGRAM_ID, stateWithNewOwner) + command(MEGA_CORP.owningKey, Cash.Commands.Move()) timeWindow(FIVE_PM) this `fails with` "Missing required encumbrance 1 in INPUT" } @@ -130,9 +130,9 @@ class TransactionEncumbranceTests { ledger { transaction { attachments(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { state } - output(Cash.PROGRAM_ID, encumbrance = 0) { stateWithNewOwner } - command(MEGA_CORP.owningKey) { Cash.Commands.Move() } + input(Cash.PROGRAM_ID, state) + output(Cash.PROGRAM_ID, encumbrance = 0, contractState = stateWithNewOwner) + command(MEGA_CORP.owningKey, Cash.Commands.Move()) this `fails with` "Missing required encumbrance 0 in OUTPUT" } } @@ -143,10 +143,10 @@ class TransactionEncumbranceTests { ledger { transaction { attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID) - input(Cash.PROGRAM_ID) { state } - output(TEST_TIMELOCK_ID, encumbrance = 2) { stateWithNewOwner } - output(TEST_TIMELOCK_ID) { timeLock } - command(MEGA_CORP.owningKey) { Cash.Commands.Move() } + input(Cash.PROGRAM_ID, state) + output(TEST_TIMELOCK_ID, encumbrance = 2, contractState = stateWithNewOwner) + output(TEST_TIMELOCK_ID, timeLock) + command(MEGA_CORP.owningKey, Cash.Commands.Move()) this `fails with` "Missing required encumbrance 2 in OUTPUT" } } @@ -157,16 +157,16 @@ class TransactionEncumbranceTests { ledger { unverifiedTransaction { attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID) - output(Cash.PROGRAM_ID, "state encumbered by some other state", encumbrance = 1) { state } - output(Cash.PROGRAM_ID, "some other state") { state } - output(TEST_TIMELOCK_ID, "5pm time-lock") { timeLock } + output(Cash.PROGRAM_ID, "state encumbered by some other state", encumbrance = 1, contractState = state) + output(Cash.PROGRAM_ID, "some other state", state) + output(TEST_TIMELOCK_ID, "5pm time-lock", timeLock) } transaction { attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID) input("state encumbered by some other state") input("5pm time-lock") - output(Cash.PROGRAM_ID) { stateWithNewOwner } - command(MEGA_CORP.owningKey) { Cash.Commands.Move() } + output(Cash.PROGRAM_ID, stateWithNewOwner) + command(MEGA_CORP.owningKey, Cash.Commands.Move()) timeWindow(FIVE_PM) this `fails with` "Missing required encumbrance 1 in INPUT" } diff --git a/docs/source/deploying-a-node.rst b/docs/source/deploying-a-node.rst index a829ce81a7..b24d7eac9f 100644 --- a/docs/source/deploying-a-node.rst +++ b/docs/source/deploying-a-node.rst @@ -122,11 +122,11 @@ handling, and ensures the Corda service is run at boot. 9. Provision the required certificates to your node. Contact the network permissioning service or see :doc:`permissioning` -10. You can now start a node and its webserver by running the following ``systemctl`` commands: +10. You can now start a node and its webserver and set the services to start on boot by running the following ``systemctl`` commands: * ``sudo systemctl daemon-reload`` - * ``sudo systemctl corda start`` - * ``sudo systemctl corda-webserver start`` + * ``sudo systemctl enable --now corda`` + * ``sudo systemctl enable --now corda-webserver`` You can run multiple nodes by creating multiple directories and Corda services, modifying the ``node.conf`` and ``service`` files so they are unique. @@ -204,10 +204,11 @@ at boot, and means the Corda service stays running with no users connected to th nssm install cordanode1 C:\ProgramData\Oracle\Java\javapath\java.exe nssm set cordanode1 AppDirectory C:\Corda - nssm set cordanode1 AppParameters "-jar corda.jar -Xmx2048m --config-file=C:\corda\node.conf" + nssm set cordanode1 AppParameters "-Xmx2048m -jar corda.jar --config-file=C:\corda\node.conf" nssm set cordanode1 AppStdout C:\Corda\service.log nssm set cordanode1 AppStderr C:\Corda\service.log nssm set cordanode1 Description Corda Node - Bank of Breakfast Tea + nssm set cordanode1 Start SERVICE_AUTO_START sc start cordanode1 9. Modify the batch file: diff --git a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt b/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt index 9b192038bf..d8a1b64776 100644 --- a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt +++ b/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt @@ -13,7 +13,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.driver.driver import org.junit.Test diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt index f68bc82edd..954a67c239 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt @@ -17,7 +17,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.ALICE import net.corda.testing.driver.driver import org.graphstream.graph.Edge diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/CustomVaultQuery.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/CustomVaultQuery.kt index 506dc8bc02..ac592eaa8f 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/CustomVaultQuery.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/CustomVaultQuery.kt @@ -24,6 +24,7 @@ object CustomVaultQuery { private companion object { private val log = contextLogger() } + fun rebalanceCurrencyReserves(): List> { val nativeQuery = """ select @@ -44,16 +45,18 @@ object CustomVaultQuery { """ log.info("SQL to execute: $nativeQuery") val session = services.jdbcSession() - val prepStatement = session.prepareStatement(nativeQuery) - val rs = prepStatement.executeQuery() - val topUpLimits: MutableList> = mutableListOf() - while (rs.next()) { - val currencyStr = rs.getString(1) - val amount = rs.getLong(2) - log.info("$currencyStr : $amount") - topUpLimits.add(Amount(amount, Currency.getInstance(currencyStr))) + return session.prepareStatement(nativeQuery).use { prepStatement -> + prepStatement.executeQuery().use { rs -> + val topUpLimits: MutableList> = mutableListOf() + while (rs.next()) { + val currencyStr = rs.getString(1) + val amount = rs.getLong(2) + log.info("$currencyStr : $amount") + topUpLimits.add(Amount(amount, Currency.getInstance(currencyStr))) + } + topUpLimits + } } - return topUpLimits } } } @@ -69,6 +72,7 @@ object TopupIssuerFlow { data class TopupRequest(val issueToParty: Party, val issuerPartyRef: OpaqueBytes, val notaryParty: Party) + @InitiatingFlow @StartableByRPC class TopupIssuanceRequester(val issueToParty: Party, diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt index 00ff7f02c6..cfde0084a1 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/tutorial/testdsl/TutorialTestDSL.kt @@ -33,7 +33,7 @@ class CommercialPaperTest { ledger { transaction { attachments(CP_PROGRAM_ID) - input(CP_PROGRAM_ID) { inState } + input(CP_PROGRAM_ID, inState) verifies() } } @@ -46,8 +46,8 @@ class CommercialPaperTest { val inState = getPaper() ledger { transaction { - input(CP_PROGRAM_ID) { inState } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() } + input(CP_PROGRAM_ID, inState) + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move()) attachments(CP_PROGRAM_ID) verifies() } @@ -61,8 +61,8 @@ class CommercialPaperTest { val inState = getPaper() ledger { transaction { - input(CP_PROGRAM_ID) { inState } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() } + input(CP_PROGRAM_ID, inState) + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move()) attachments(CP_PROGRAM_ID) `fails with`("the state is propagated") } @@ -76,11 +76,11 @@ class CommercialPaperTest { val inState = getPaper() ledger { transaction { - input(CP_PROGRAM_ID) { inState } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() } + input(CP_PROGRAM_ID, inState) + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move()) attachments(CP_PROGRAM_ID) `fails with`("the state is propagated") - output(CP_PROGRAM_ID, "alice's paper") { inState.withOwner(ALICE) } + output(CP_PROGRAM_ID, "alice's paper", inState.withOwner(ALICE)) verifies() } } @@ -92,15 +92,15 @@ class CommercialPaperTest { fun `simple issuance with tweak`() { ledger { transaction { - output(CP_PROGRAM_ID, "paper") { getPaper() } // Some CP is issued onto the ledger by MegaCorp. + output(CP_PROGRAM_ID, "paper", getPaper()) // Some CP is issued onto the ledger by MegaCorp. attachments(CP_PROGRAM_ID) tweak { // The wrong pubkey. - command(BIG_CORP_PUBKEY) { CommercialPaper.Commands.Issue() } + command(BIG_CORP_PUBKEY, CommercialPaper.Commands.Issue()) timeWindow(TEST_TX_TIME) `fails with`("output states are issued by a command signer") } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() } + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Issue()) timeWindow(TEST_TX_TIME) verifies() } @@ -112,15 +112,15 @@ class CommercialPaperTest { @Test fun `simple issuance with tweak and top level transaction`() { transaction { - output(CP_PROGRAM_ID, "paper") { getPaper() } // Some CP is issued onto the ledger by MegaCorp. + output(CP_PROGRAM_ID, "paper", getPaper()) // Some CP is issued onto the ledger by MegaCorp. attachments(CP_PROGRAM_ID) tweak { // The wrong pubkey. - command(BIG_CORP_PUBKEY) { CommercialPaper.Commands.Issue() } + command(BIG_CORP_PUBKEY, CommercialPaper.Commands.Issue()) timeWindow(TEST_TX_TIME) `fails with`("output states are issued by a command signer") } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() } + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Issue()) timeWindow(TEST_TX_TIME) verifies() } @@ -140,8 +140,8 @@ class CommercialPaperTest { // Some CP is issued onto the ledger by MegaCorp. transaction("Issuance") { - output(CP_PROGRAM_ID, "paper") { getPaper() } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() } + output(CP_PROGRAM_ID, "paper", getPaper()) + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Issue()) attachments(CP_PROGRAM_ID) timeWindow(TEST_TX_TIME) verifies() @@ -151,10 +151,10 @@ class CommercialPaperTest { transaction("Trade") { input("paper") input("alice's $900") - output(Cash.PROGRAM_ID, "borrowed $900") { 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP } - output(CP_PROGRAM_ID, "alice's paper") { "paper".output().withOwner(ALICE) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() } + output(Cash.PROGRAM_ID, "borrowed $900", 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP) + output(CP_PROGRAM_ID, "alice's paper", "paper".output().withOwner(ALICE)) + command(ALICE_PUBKEY, Cash.Commands.Move()) + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move()) verifies() } } @@ -173,8 +173,8 @@ class CommercialPaperTest { // Some CP is issued onto the ledger by MegaCorp. transaction("Issuance") { - output(CP_PROGRAM_ID, "paper") { getPaper() } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() } + output(CP_PROGRAM_ID, "paper", getPaper()) + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Issue()) attachments(CP_PROGRAM_ID) timeWindow(TEST_TX_TIME) verifies() @@ -183,18 +183,18 @@ class CommercialPaperTest { transaction("Trade") { input("paper") input("alice's $900") - output(Cash.PROGRAM_ID, "borrowed $900") { 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP } - output(CP_PROGRAM_ID, "alice's paper") { "paper".output().withOwner(ALICE) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() } + output(Cash.PROGRAM_ID, "borrowed $900", 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP) + output(CP_PROGRAM_ID, "alice's paper", "paper".output().withOwner(ALICE)) + command(ALICE_PUBKEY, Cash.Commands.Move()) + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move()) verifies() } transaction { input("paper") // We moved a paper to another pubkey. - output(CP_PROGRAM_ID, "bob's paper") { "paper".output().withOwner(BOB) } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() } + output(CP_PROGRAM_ID, "bob's paper", "paper".output().withOwner(BOB)) + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move()) verifies() } @@ -215,8 +215,8 @@ class CommercialPaperTest { // Some CP is issued onto the ledger by MegaCorp. transaction("Issuance") { - output(CP_PROGRAM_ID, "paper") { getPaper() } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() } + output(CP_PROGRAM_ID, "paper", getPaper()) + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Issue()) attachments(CP_PROGRAM_ID) timeWindow(TEST_TX_TIME) verifies() @@ -225,10 +225,10 @@ class CommercialPaperTest { transaction("Trade") { input("paper") input("alice's $900") - output(Cash.PROGRAM_ID, "borrowed $900") { 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP } - output(CP_PROGRAM_ID, "alice's paper") { "paper".output().withOwner(ALICE) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() } + output(Cash.PROGRAM_ID, "borrowed $900", 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP) + output(CP_PROGRAM_ID, "alice's paper", "paper".output().withOwner(ALICE)) + command(ALICE_PUBKEY, Cash.Commands.Move()) + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move()) verifies() } @@ -236,8 +236,8 @@ class CommercialPaperTest { transaction { input("paper") // We moved a paper to another pubkey. - output(CP_PROGRAM_ID, "bob's paper") { "paper".output().withOwner(BOB) } - command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() } + output(CP_PROGRAM_ID, "bob's paper", "paper".output().withOwner(BOB)) + command(MEGA_CORP_PUBKEY, CommercialPaper.Commands.Move()) verifies() } fails() diff --git a/docs/source/running-a-node.rst b/docs/source/running-a-node.rst index b5c2ddf845..34fde7652b 100644 --- a/docs/source/running-a-node.rst +++ b/docs/source/running-a-node.rst @@ -22,6 +22,12 @@ Start the nodes with ``runnodes`` by running the following command from the root .. warn:: On macOS, do not click/change focus until all the node terminal windows have opened, or some processes may fail to start. +If you receive an ``OutOfMemoryError`` exception when interacting with the nodes, you need to increase the amount of +Java heap memory available to them, which you can do when running them individually. See +:ref:`starting-an-individual-corda-node`. + +.. _starting-an-individual-corda-node: + Starting an individual Corda node --------------------------------- Run the node by opening a terminal window in the node's folder and running: @@ -30,9 +36,18 @@ Run the node by opening a terminal window in the node's folder and running: java -jar corda.jar -.. warning:: By default, the node will look for a configuration file called ``node.conf`` and a CorDapps folder called - ``cordapps`` in the current working directory. You can override the configuration file and workspace paths on the - command line (e.g. ``./corda.jar --config-file=test.conf --base-directory=/opt/r3corda/nodes/test``). +By default, the node will look for a configuration file called ``node.conf`` and a CorDapps folder called ``cordapps`` +in the current working directory. You can override the configuration file and workspace paths on the command line (e.g. +``./corda.jar --config-file=test.conf --base-directory=/opt/corda/nodes/test``). + +You can increase the amount of Java heap memory available to the node using the ``-Xmx`` command line argument. For +example, the following would run the node with a heap size of 2048MB: + +.. code-block:: shell + + java -Xmx2048m -jar corda.jar + +You should do this if you receive an ``OutOfMemoryError`` exception when interacting with the node. Optionally run the node's webserver as well by opening a terminal window in the node's folder and running: diff --git a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Cap.kt b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Cap.kt index be94480f2a..9d683682a6 100644 --- a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Cap.kt +++ b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Cap.kt @@ -172,16 +172,14 @@ class Cap { @Test fun issue() { transaction { - output(UNIVERSAL_PROGRAM_ID) { stateInitial } + output(UNIVERSAL_PROGRAM_ID, stateInitial) timeWindow(TEST_TX_TIME_1) tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() } + command(acmeCorp.owningKey, UniversalContract.Commands.Issue()) this `fails with` "the transaction is signed by all liable parties" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() } - + command(highStreetBank.owningKey, UniversalContract.Commands.Issue()) this.verifies() } } @@ -189,44 +187,38 @@ class Cap { @Test fun `first fixing`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { stateInitial } - output(UNIVERSAL_PROGRAM_ID) { stateAfterFixingFirst } + input(UNIVERSAL_PROGRAM_ID, stateInitial) + output(UNIVERSAL_PROGRAM_ID, stateAfterFixingFirst) timeWindow(TEST_TX_TIME_1) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } tweak { // wrong source - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBORx", tradeDate, Tenor("3M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBORx", tradeDate, Tenor("3M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { // wrong date - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate.plusYears(1), Tenor("3M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate.plusYears(1), Tenor("3M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { // wrong tenor - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("9M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("9M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.5.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.5.bd)))) this `fails with` "output state does not reflect fix command" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.0.bd)))) this.verifies() } } @@ -234,19 +226,16 @@ class Cap { @Test fun `first execute`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { stateAfterFixingFirst } - output(UNIVERSAL_PROGRAM_ID) { stateAfterExecutionFirst } - output(UNIVERSAL_PROGRAM_ID) { statePaymentFirst } - + input(UNIVERSAL_PROGRAM_ID, stateAfterFixingFirst) + output(UNIVERSAL_PROGRAM_ID, stateAfterExecutionFirst) + output(UNIVERSAL_PROGRAM_ID, statePaymentFirst) timeWindow(TEST_TX_TIME_1) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("exercise") } - + command(highStreetBank.owningKey, UniversalContract.Commands.Action("exercise")) this.verifies() } } @@ -254,18 +243,15 @@ class Cap { @Test fun `final execute`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { stateAfterFixingFinal } - output(UNIVERSAL_PROGRAM_ID) { statePaymentFinal } - + input(UNIVERSAL_PROGRAM_ID, stateAfterFixingFinal) + output(UNIVERSAL_PROGRAM_ID, statePaymentFinal) timeWindow(TEST_TX_TIME_1) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("exercise") } - + command(highStreetBank.owningKey, UniversalContract.Commands.Action("exercise")) this.verifies() } } @@ -273,44 +259,38 @@ class Cap { @Test fun `second fixing`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { stateAfterExecutionFirst } - output(UNIVERSAL_PROGRAM_ID) { stateAfterFixingFinal } + input(UNIVERSAL_PROGRAM_ID, stateAfterExecutionFirst) + output(UNIVERSAL_PROGRAM_ID, stateAfterFixingFinal) timeWindow(TEST_TX_TIME_1) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } tweak { // wrong source - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBORx", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBORx", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { // wrong date - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01").plusYears(1), Tenor("3M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01").plusYears(1), Tenor("3M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { // wrong tenor - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("9M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("9M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.5.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.5.bd)))) this `fails with` "output state does not reflect fix command" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.0.bd)))) this.verifies() } } diff --git a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Caplet.kt b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Caplet.kt index 1bf39cfacd..7436161cd4 100644 --- a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Caplet.kt +++ b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Caplet.kt @@ -55,16 +55,14 @@ class Caplet { @Test fun issue() { transaction { - output(UNIVERSAL_PROGRAM_ID) { stateStart } + output(UNIVERSAL_PROGRAM_ID, stateStart) timeWindow(TEST_TX_TIME_1) tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() } + command(acmeCorp.owningKey, UniversalContract.Commands.Issue()) this `fails with` "the transaction is signed by all liable parties" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() } - + command(highStreetBank.owningKey, UniversalContract.Commands.Issue()) this.verifies() } } @@ -72,17 +70,15 @@ class Caplet { @Test fun `execute`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { stateFixed } - output(UNIVERSAL_PROGRAM_ID) { stateFinal } + input(UNIVERSAL_PROGRAM_ID, stateFixed) + output(UNIVERSAL_PROGRAM_ID, stateFinal) timeWindow(TEST_TX_TIME_1) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("exercise") } - + command(highStreetBank.owningKey, UniversalContract.Commands.Action("exercise")) this.verifies() } } @@ -90,44 +86,38 @@ class Caplet { @Test fun `fixing`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { stateStart } - output(UNIVERSAL_PROGRAM_ID) { stateFixed } + input(UNIVERSAL_PROGRAM_ID, stateStart) + output(UNIVERSAL_PROGRAM_ID, stateFixed) timeWindow(TEST_TX_TIME_1) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } tweak { // wrong source - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBORx", tradeDate, Tenor("6M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBORx", tradeDate, Tenor("6M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { // wrong date - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate.plusYears(1), Tenor("6M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate.plusYears(1), Tenor("6M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { // wrong tenor - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("6M")), 1.5.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("6M")), 1.5.bd)))) this `fails with` "output state does not reflect fix command" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("6M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("6M")), 1.0.bd)))) this.verifies() } } diff --git a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/FXFwdTimeOption.kt b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/FXFwdTimeOption.kt index 603eceb0f7..1d05fe061a 100644 --- a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/FXFwdTimeOption.kt +++ b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/FXFwdTimeOption.kt @@ -52,20 +52,18 @@ class FXFwdTimeOption { @Test fun `issue - signature`() { transaction { - output(UNIVERSAL_PROGRAM_ID) { inState } + output(UNIVERSAL_PROGRAM_ID, inState) timeWindow(TEST_TX_TIME_1) tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() } + command(acmeCorp.owningKey, UniversalContract.Commands.Issue()) this `fails with` "the transaction is signed by all liable parties" } tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() } + command(highStreetBank.owningKey, UniversalContract.Commands.Issue()) this `fails with` "the transaction is signed by all liable parties" } - - command(highStreetBank.owningKey, acmeCorp.owningKey) { UniversalContract.Commands.Issue() } - + command(listOf(highStreetBank.owningKey, acmeCorp.owningKey), UniversalContract.Commands.Issue()) this.verifies() } } @@ -73,31 +71,28 @@ class FXFwdTimeOption { @Test fun `maturity, bank exercise`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outState1 } - output(UNIVERSAL_PROGRAM_ID) { outState2 } - + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outState1) + output(UNIVERSAL_PROGRAM_ID, outState2) timeWindow(TEST_TX_TIME_AFTER_MATURITY) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("exercise") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("exercise")) this `fails with` "condition must be met" } tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Action("exercise") } + command(acmeCorp.owningKey, UniversalContract.Commands.Action("exercise")) this `fails with` "condition must be met" } tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Action("expire") } + command(acmeCorp.owningKey, UniversalContract.Commands.Action("expire")) this `fails with` "condition must be met" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("expire") } - + command(highStreetBank.owningKey, UniversalContract.Commands.Action("expire")) this.verifies() } } @@ -105,31 +100,28 @@ class FXFwdTimeOption { @Test fun `maturity, corp exercise`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outState1 } - output(UNIVERSAL_PROGRAM_ID) { outState2 } - + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outState1) + output(UNIVERSAL_PROGRAM_ID, outState2) timeWindow(TEST_TX_TIME_BEFORE_MATURITY) tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(acmeCorp.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Action("expire") } + command(acmeCorp.owningKey, UniversalContract.Commands.Action("expire")) this `fails with` "condition must be met" } tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("expire") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("expire")) this `fails with` "condition must be met" } tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("exercise") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("exercise")) this `fails with` "condition must be met" } - - command(acmeCorp.owningKey) { UniversalContract.Commands.Action("exercise") } - + command(acmeCorp.owningKey, UniversalContract.Commands.Action("exercise")) this.verifies() } } diff --git a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/FXSwap.kt b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/FXSwap.kt index dc0d27a258..fc91215046 100644 --- a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/FXSwap.kt +++ b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/FXSwap.kt @@ -44,20 +44,18 @@ class FXSwap { fun `issue - signature`() { transaction { - output(UNIVERSAL_PROGRAM_ID) { inState } + output(UNIVERSAL_PROGRAM_ID, inState) timeWindow(TEST_TX_TIME_1) tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() } + command(acmeCorp.owningKey, UniversalContract.Commands.Issue()) this `fails with` "the transaction is signed by all liable parties" } tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() } + command(highStreetBank.owningKey, UniversalContract.Commands.Issue()) this `fails with` "the transaction is signed by all liable parties" } - - command(highStreetBank.owningKey, acmeCorp.owningKey) { UniversalContract.Commands.Issue() } - + command(listOf(highStreetBank.owningKey, acmeCorp.owningKey), UniversalContract.Commands.Issue()) this.verifies() } } @@ -65,18 +63,16 @@ class FXSwap { @Test fun `execute`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outState1 } - output(UNIVERSAL_PROGRAM_ID) { outState2 } + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outState1) + output(UNIVERSAL_PROGRAM_ID, outState2) timeWindow(TEST_TX_TIME_1) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("execute") } - + command(highStreetBank.owningKey, UniversalContract.Commands.Action("execute")) this.verifies() } } @@ -84,18 +80,16 @@ class FXSwap { @Test fun `execute - reversed order`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outState2 } - output(UNIVERSAL_PROGRAM_ID) { outState1 } + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outState2) + output(UNIVERSAL_PROGRAM_ID, outState1) timeWindow(TEST_TX_TIME_1) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("execute") } - + command(highStreetBank.owningKey, UniversalContract.Commands.Action("execute")) this.verifies() } } @@ -103,12 +97,11 @@ class FXSwap { @Test fun `execute - not authorized`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outState1 } - output(UNIVERSAL_PROGRAM_ID) { outState2 } + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outState1) + output(UNIVERSAL_PROGRAM_ID, outState2) timeWindow(TEST_TX_TIME_1) - - command(momAndPop.owningKey) { UniversalContract.Commands.Action("execute") } + command(momAndPop.owningKey, UniversalContract.Commands.Action("execute")) this `fails with` "condition must be met" } } @@ -116,12 +109,11 @@ class FXSwap { @Test fun `execute - before maturity`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outState1 } - output(UNIVERSAL_PROGRAM_ID) { outState2 } + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outState1) + output(UNIVERSAL_PROGRAM_ID, outState2) timeWindow(TEST_TX_TIME_TOO_EARLY) - - command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") } + command(acmeCorp.owningKey, UniversalContract.Commands.Action("execute")) this `fails with` "condition must be met" } } @@ -129,11 +121,10 @@ class FXSwap { @Test fun `execute - outState mismatch 1`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outState1 } + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outState1) timeWindow(TEST_TX_TIME_1) - - command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") } + command(acmeCorp.owningKey, UniversalContract.Commands.Action("execute")) this `fails with` "output state must match action result state" } } @@ -141,12 +132,11 @@ class FXSwap { @Test fun `execute - outState mismatch 2`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outState1 } - output(UNIVERSAL_PROGRAM_ID) { outStateBad2 } + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outState1) + output(UNIVERSAL_PROGRAM_ID, outStateBad2) timeWindow(TEST_TX_TIME_1) - - command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") } + command(acmeCorp.owningKey, UniversalContract.Commands.Action("execute")) this `fails with` "output states must match action result state" } } @@ -154,12 +144,11 @@ class FXSwap { @Test fun `execute - outState mismatch 3`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outStateBad1 } - output(UNIVERSAL_PROGRAM_ID) { outState2 } + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outStateBad1) + output(UNIVERSAL_PROGRAM_ID, outState2) timeWindow(TEST_TX_TIME_1) - - command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") } + command(acmeCorp.owningKey, UniversalContract.Commands.Action("execute")) this `fails with` "output states must match action result state" } } @@ -167,12 +156,11 @@ class FXSwap { @Test fun `execute - outState mismatch 4`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outState1 } - output(UNIVERSAL_PROGRAM_ID) { outStateBad3 } + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outState1) + output(UNIVERSAL_PROGRAM_ID, outStateBad3) timeWindow(TEST_TX_TIME_1) - - command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") } + command(acmeCorp.owningKey, UniversalContract.Commands.Action("execute")) this `fails with` "output states must match action result state" } } diff --git a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/IRS.kt b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/IRS.kt index c2a2653318..e2f0d4f942 100644 --- a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/IRS.kt +++ b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/IRS.kt @@ -134,16 +134,14 @@ class IRS { @Test fun issue() { transaction { - output(UNIVERSAL_PROGRAM_ID) { stateInitial } + output(UNIVERSAL_PROGRAM_ID, stateInitial) timeWindow(TEST_TX_TIME_1) tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() } + command(acmeCorp.owningKey, UniversalContract.Commands.Issue()) this `fails with` "the transaction is signed by all liable parties" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() } - + command(highStreetBank.owningKey, UniversalContract.Commands.Issue()) this.verifies() } } @@ -151,44 +149,38 @@ class IRS { @Test fun `first fixing`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { stateInitial } - output(UNIVERSAL_PROGRAM_ID) { stateAfterFixingFirst } + input(UNIVERSAL_PROGRAM_ID, stateInitial) + output(UNIVERSAL_PROGRAM_ID, stateAfterFixingFirst) timeWindow(TEST_TX_TIME_1) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } tweak { // wrong source - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBORx", tradeDate, Tenor("3M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBORx", tradeDate, Tenor("3M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { // wrong date - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate.plusYears(1), Tenor("3M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate.plusYears(1), Tenor("3M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { // wrong tenor - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("9M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("9M")), 1.0.bd)))) this `fails with` "relevant fixing must be included" } tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.5.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.5.bd)))) this `fails with` "output state does not reflect fix command" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.0.bd))) } - + command(highStreetBank.owningKey, UniversalContract.Commands.Fix(listOf(net.corda.finance.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.0.bd)))) this.verifies() } } @@ -196,19 +188,16 @@ class IRS { @Test fun `first execute`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { stateAfterFixingFirst } - output(UNIVERSAL_PROGRAM_ID) { stateAfterExecutionFirst } - output(UNIVERSAL_PROGRAM_ID) { statePaymentFirst } - + input(UNIVERSAL_PROGRAM_ID, stateAfterFixingFirst) + output(UNIVERSAL_PROGRAM_ID, stateAfterExecutionFirst) + output(UNIVERSAL_PROGRAM_ID, statePaymentFirst) timeWindow(TEST_TX_TIME_1) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("pay floating") } - + command(highStreetBank.owningKey, UniversalContract.Commands.Action("pay floating")) this.verifies() } } diff --git a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/RollOutTests.kt b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/RollOutTests.kt index 289b58c4d0..34ba966a0c 100644 --- a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/RollOutTests.kt +++ b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/RollOutTests.kt @@ -145,16 +145,14 @@ class RollOutTests { @Test fun issue() { transaction { - output(UNIVERSAL_PROGRAM_ID) { stateStart } + output(UNIVERSAL_PROGRAM_ID, stateStart) timeWindow(TEST_TX_TIME_1) tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() } + command(acmeCorp.owningKey, UniversalContract.Commands.Issue()) this `fails with` "the transaction is signed by all liable parties" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() } - + command(highStreetBank.owningKey, UniversalContract.Commands.Issue()) this.verifies() } } @@ -162,18 +160,16 @@ class RollOutTests { @Test fun `execute`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { stateStart } - output(UNIVERSAL_PROGRAM_ID) { stateStep1a } - output(UNIVERSAL_PROGRAM_ID) { stateStep1b } + input(UNIVERSAL_PROGRAM_ID, stateStart) + output(UNIVERSAL_PROGRAM_ID, stateStep1a) + output(UNIVERSAL_PROGRAM_ID, stateStep1b) timeWindow(TEST_TX_TIME_1) /* tweak { command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } this `fails with` "action must be defined" }*/ - - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("transfer") } - + command(highStreetBank.owningKey, UniversalContract.Commands.Action("transfer")) this.verifies() } } diff --git a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Swaption.kt b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Swaption.kt index c1e25625e5..f80c3d5fd3 100644 --- a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Swaption.kt +++ b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/Swaption.kt @@ -61,16 +61,14 @@ class Swaption { @Test fun issue() { transaction { - output(UNIVERSAL_PROGRAM_ID) { stateInitial } + output(UNIVERSAL_PROGRAM_ID, stateInitial) timeWindow(TEST_TX_TIME_1) tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() } + command(acmeCorp.owningKey, UniversalContract.Commands.Issue()) this `fails with` "the transaction is signed by all liable parties" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() } - + command(highStreetBank.owningKey, UniversalContract.Commands.Issue()) this.verifies() } } diff --git a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/ZeroCouponBond.kt b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/ZeroCouponBond.kt index 0b3898176d..2554b0c58b 100644 --- a/experimental/src/test/kotlin/net/corda/finance/contracts/universal/ZeroCouponBond.kt +++ b/experimental/src/test/kotlin/net/corda/finance/contracts/universal/ZeroCouponBond.kt @@ -51,15 +51,12 @@ class ZeroCouponBond { @Test fun `issue - signature`() { transaction { - output(UNIVERSAL_PROGRAM_ID) { inState } - + output(UNIVERSAL_PROGRAM_ID, inState) tweak { - command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() } + command(acmeCorp.owningKey, UniversalContract.Commands.Issue()) this `fails with` "the transaction is signed by all liable parties" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() } - + command(highStreetBank.owningKey, UniversalContract.Commands.Issue()) this.verifies() } } @@ -67,17 +64,15 @@ class ZeroCouponBond { @Test fun `execute`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outState } + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outState) timeWindow(TEST_TX_TIME_1) tweak { - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") } + command(highStreetBank.owningKey, UniversalContract.Commands.Action("some undefined name")) this `fails with` "action must be defined" } - - command(highStreetBank.owningKey) { UniversalContract.Commands.Action("execute") } - + command(highStreetBank.owningKey, UniversalContract.Commands.Action("execute")) this.verifies() } } @@ -85,11 +80,10 @@ class ZeroCouponBond { @Test fun `execute - not authorized`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outState } + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outState) timeWindow(TEST_TX_TIME_1) - - command(momAndPop.owningKey) { UniversalContract.Commands.Action("execute") } + command(momAndPop.owningKey, UniversalContract.Commands.Action("execute")) this `fails with` "condition must be met" } } @@ -97,11 +91,10 @@ class ZeroCouponBond { @Test fun `execute - outState mismatch`() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - output(UNIVERSAL_PROGRAM_ID) { outStateWrong } + input(UNIVERSAL_PROGRAM_ID, inState) + output(UNIVERSAL_PROGRAM_ID, outStateWrong) timeWindow(TEST_TX_TIME_1) - - command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") } + command(acmeCorp.owningKey, UniversalContract.Commands.Action("execute")) this `fails with` "output state must match action result state" } } @@ -109,29 +102,23 @@ class ZeroCouponBond { @Test fun move() { transaction { - input(UNIVERSAL_PROGRAM_ID) { inState } - + input(UNIVERSAL_PROGRAM_ID, inState) tweak { - output(UNIVERSAL_PROGRAM_ID) { outStateMove } - command(acmeCorp.owningKey) { - UniversalContract.Commands.Move(acmeCorp, momAndPop) - } + output(UNIVERSAL_PROGRAM_ID, outStateMove) + command(acmeCorp.owningKey, + UniversalContract.Commands.Move(acmeCorp, momAndPop)) this `fails with` "the transaction is signed by all liable parties" } tweak { - output(UNIVERSAL_PROGRAM_ID) { inState } - command(acmeCorp.owningKey, momAndPop.owningKey, highStreetBank.owningKey) { - UniversalContract.Commands.Move(acmeCorp, momAndPop) - } + output(UNIVERSAL_PROGRAM_ID, inState) + command(listOf(acmeCorp.owningKey, momAndPop.owningKey, highStreetBank.owningKey), + UniversalContract.Commands.Move(acmeCorp, momAndPop)) this `fails with` "output state does not reflect move command" } - - output(UNIVERSAL_PROGRAM_ID) { outStateMove } - - command(acmeCorp.owningKey, momAndPop.owningKey, highStreetBank.owningKey) { - UniversalContract.Commands.Move(acmeCorp, momAndPop) - } + output(UNIVERSAL_PROGRAM_ID, outStateMove) + command(listOf(acmeCorp.owningKey, momAndPop.owningKey, highStreetBank.owningKey), + UniversalContract.Commands.Move(acmeCorp, momAndPop)) this.verifies() } } diff --git a/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/AbstractCashSelection.kt b/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/AbstractCashSelection.kt index b5d2113f8d..eff93f6d3f 100644 --- a/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/AbstractCashSelection.kt +++ b/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/AbstractCashSelection.kt @@ -69,13 +69,14 @@ abstract class AbstractCashSelection { * with this notary are included. * @param onlyFromIssuerParties Optional issuer parties to match against. * @param withIssuerRefs Optional issuer references to match against. - * @return JDBC ResultSet with the matching states that were found. If sufficient funds were found these will be locked, + * @param withResultSet Function that contains the business logic. The JDBC ResultSet with the matching states that were found. If sufficient funds were found these will be locked, * otherwise what is available is returned unlocked for informational purposes. + * @return The result of the withResultSet function */ abstract fun executeQuery(connection: Connection, amount: Amount, lockId: UUID, notary: Party?, - onlyFromIssuerParties: Set, withIssuerRefs: Set) : ResultSet + onlyFromIssuerParties: Set, withIssuerRefs: Set, withResultSet: (ResultSet) -> Boolean): Boolean - override abstract fun toString() : String + override abstract fun toString(): String /** * Query to gather Cash states that are available and retry if they are temporarily unavailable. @@ -124,34 +125,40 @@ abstract class AbstractCashSelection { try { // we select spendable states irrespective of lock but prioritised by unlocked ones (Eg. null) // the softLockReserve update will detect whether we try to lock states locked by others - val rs = executeQuery(connection, amount, lockId, notary, onlyFromIssuerParties, withIssuerRefs) - stateAndRefs.clear() + return executeQuery(connection, amount, lockId, notary, onlyFromIssuerParties, withIssuerRefs) { rs -> + stateAndRefs.clear() - var totalPennies = 0L - val stateRefs = mutableSetOf() - while (rs.next()) { - val txHash = SecureHash.parse(rs.getString(1)) - val index = rs.getInt(2) - val pennies = rs.getLong(3) - totalPennies = rs.getLong(4) - val rowLockId = rs.getString(5) - stateRefs.add(StateRef(txHash, index)) - log.trace { "ROW: $rowLockId ($lockId): ${StateRef(txHash, index)} : $pennies ($totalPennies)" } + var totalPennies = 0L + val stateRefs = mutableSetOf() + while (rs.next()) { + val txHash = SecureHash.parse(rs.getString(1)) + val index = rs.getInt(2) + val pennies = rs.getLong(3) + totalPennies = rs.getLong(4) + val rowLockId = rs.getString(5) + stateRefs.add(StateRef(txHash, index)) + log.trace { "ROW: $rowLockId ($lockId): ${StateRef(txHash, index)} : $pennies ($totalPennies)" } + } + + if (stateRefs.isNotEmpty()) { + // TODO: future implementation to retrieve contract states from a Vault BLOB store + stateAndRefs.addAll(services.loadStates(stateRefs) as Collection>) + } + + val success = stateAndRefs.isNotEmpty() && totalPennies >= amount.quantity + if (success) { + // we should have a minimum number of states to satisfy our selection `amount` criteria + log.trace("Coin selection for $amount retrieved ${stateAndRefs.count()} states totalling $totalPennies pennies: $stateAndRefs") + + // With the current single threaded state machine available states are guaranteed to lock. + // TODO However, we will have to revisit these methods in the future multi-threaded. + services.vaultService.softLockReserve(lockId, (stateAndRefs.map { it.ref }).toNonEmptySet()) + } else { + log.trace("Coin selection requested $amount but retrieved $totalPennies pennies with state refs: ${stateAndRefs.map { it.ref }}") + } + success } - if (stateRefs.isNotEmpty()) - // TODO: future implementation to retrieve contract states from a Vault BLOB store - stateAndRefs.addAll(services.loadStates(stateRefs) as Collection>) - if (stateAndRefs.isNotEmpty() && totalPennies >= amount.quantity) { - // we should have a minimum number of states to satisfy our selection `amount` criteria - log.trace("Coin selection for $amount retrieved ${stateAndRefs.count()} states totalling $totalPennies pennies: $stateAndRefs") - - // With the current single threaded state machine available states are guaranteed to lock. - // TODO However, we will have to revisit these methods in the future multi-threaded. - services.vaultService.softLockReserve(lockId, (stateAndRefs.map { it.ref }).toNonEmptySet()) - return true - } - log.trace("Coin selection requested $amount but retrieved $totalPennies pennies with state refs: ${stateAndRefs.map { it.ref }}") // retry as more states may become available } catch (e: SQLException) { log.error("""Failed retrieving unconsumed states for: amount [$amount], onlyFromIssuerParties [$onlyFromIssuerParties], notary [$notary], lockId [$lockId] diff --git a/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionH2Impl.kt b/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionH2Impl.kt index 440047f19d..3c21246dee 100644 --- a/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionH2Impl.kt +++ b/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionH2Impl.kt @@ -30,9 +30,8 @@ class CashSelectionH2Impl : AbstractCashSelection() { // 2) H2 uses session variables to perform this accumulator function: // http://www.h2database.com/html/functions.html#set // 3) H2 does not support JOIN's in FOR UPDATE (hence we are forced to execute 2 queries) - override fun executeQuery(connection: Connection, amount: Amount, lockId: UUID, notary: Party?, - onlyFromIssuerParties: Set, withIssuerRefs: Set) : ResultSet { - connection.createStatement().execute("CALL SET(@t, CAST(0 AS BIGINT));") + override fun executeQuery(connection: Connection, amount: Amount, lockId: UUID, notary: Party?, onlyFromIssuerParties: Set, withIssuerRefs: Set, withResultSet: (ResultSet) -> Boolean): Boolean { + connection.createStatement().use { it.execute("CALL SET(@t, CAST(0 AS BIGINT));") } val selectJoin = """ SELECT vs.transaction_id, vs.output_index, ccs.pennies, SET(@t, ifnull(@t,0)+ccs.pennies) total_pennies, vs.lock_id @@ -50,19 +49,22 @@ class CashSelectionH2Impl : AbstractCashSelection() { " AND ccs.issuer_ref IN (?)" else "") // Use prepared statement for protection against SQL Injection (http://www.h2database.com/html/advanced.html#sql_injection) - val psSelectJoin = connection.prepareStatement(selectJoin) - var pIndex = 0 - psSelectJoin.setString(++pIndex, amount.token.currencyCode) - psSelectJoin.setLong(++pIndex, amount.quantity) - psSelectJoin.setString(++pIndex, lockId.toString()) - if (notary != null) - psSelectJoin.setString(++pIndex, notary.name.toString()) - if (onlyFromIssuerParties.isNotEmpty()) - psSelectJoin.setObject(++pIndex, onlyFromIssuerParties.map { it.owningKey.toStringShort() as Any}.toTypedArray() ) - if (withIssuerRefs.isNotEmpty()) - psSelectJoin.setObject(++pIndex, withIssuerRefs.map { it.bytes as Any }.toTypedArray()) - log.debug { psSelectJoin.toString() } + connection.prepareStatement(selectJoin).use { psSelectJoin -> + var pIndex = 0 + psSelectJoin.setString(++pIndex, amount.token.currencyCode) + psSelectJoin.setLong(++pIndex, amount.quantity) + psSelectJoin.setString(++pIndex, lockId.toString()) + if (notary != null) + psSelectJoin.setString(++pIndex, notary.name.toString()) + if (onlyFromIssuerParties.isNotEmpty()) + psSelectJoin.setObject(++pIndex, onlyFromIssuerParties.map { it.owningKey.toStringShort() as Any }.toTypedArray()) + if (withIssuerRefs.isNotEmpty()) + psSelectJoin.setObject(++pIndex, withIssuerRefs.map { it.bytes as Any }.toTypedArray()) + log.debug { psSelectJoin.toString() } - return psSelectJoin.executeQuery() + psSelectJoin.executeQuery().use { rs -> + return withResultSet(rs) + } + } } } \ No newline at end of file diff --git a/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionMySQLImpl.kt b/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionMySQLImpl.kt index 853ba23d07..e197e5a962 100644 --- a/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionMySQLImpl.kt +++ b/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionMySQLImpl.kt @@ -19,7 +19,7 @@ class CashSelectionMySQLImpl : AbstractCashSelection() { return metadata.driverName == JDBC_DRIVER_NAME } - override fun executeQuery(statement: Connection, amount: Amount, lockId: UUID, notary: Party?, issuerKeysStr: Set, issuerRefsStr: Set): ResultSet { + override fun executeQuery(statement: Connection, amount: Amount, lockId: UUID, notary: Party?, issuerKeysStr: Set, issuerRefsStr: Set, withResultSet: (ResultSet) -> Boolean): Boolean { TODO("MySQL cash selection not implemented") } diff --git a/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionPostgreSQLImpl.kt b/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionPostgreSQLImpl.kt index f96ef6f441..47e59386c3 100644 --- a/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionPostgreSQLImpl.kt +++ b/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionPostgreSQLImpl.kt @@ -27,8 +27,7 @@ class CashSelectionPostgreSQLImpl : AbstractCashSelection() { // 2) The window function accumulated column (`total`) does not include the current row (starts from 0) and cannot // appear in the WHERE clause, hence restricting row selection and adjusting the returned total in the outer query. // 3) Currently (version 9.6), FOR UPDATE cannot be specified with window functions - override fun executeQuery(connection: Connection, amount: Amount, lockId: UUID, notary: Party?, - onlyFromIssuerParties: Set, withIssuerRefs: Set) : ResultSet { + override fun executeQuery(connection: Connection, amount: Amount, lockId: UUID, notary: Party?, onlyFromIssuerParties: Set, withIssuerRefs: Set, withResultSet: (ResultSet) -> Boolean): Boolean { val selectJoin = """SELECT nested.transaction_id, nested.output_index, nested.pennies, nested.total+nested.pennies as total_pennies, nested.lock_id FROM @@ -51,29 +50,32 @@ class CashSelectionPostgreSQLImpl : AbstractCashSelection() { nested WHERE nested.total < ? """ - val statement = connection.prepareStatement(selectJoin) - statement.setString(1, amount.token.toString()) - statement.setString(2, lockId.toString()) - var paramOffset = 0 - if (notary != null) { - statement.setString(3, notary.name.toString()) - paramOffset += 1 - } - if (onlyFromIssuerParties.isNotEmpty()) { - val issuerKeys = connection.createArrayOf("VARCHAR", onlyFromIssuerParties.map - { it.owningKey.toBase58String() }.toTypedArray()) - statement.setArray(3 + paramOffset, issuerKeys) - paramOffset += 1 - } - if (withIssuerRefs.isNotEmpty()) { - val issuerRefs = connection.createArrayOf("BYTEA", withIssuerRefs.map - { it.bytes }.toTypedArray()) - statement.setArray(3 + paramOffset, issuerRefs) - paramOffset += 1 - } - statement.setLong(3 + paramOffset, amount.quantity) - log.debug { statement.toString() } + connection.prepareStatement(selectJoin).use { statement -> + statement.setString(1, amount.token.toString()) + statement.setString(2, lockId.toString()) + var paramOffset = 0 + if (notary != null) { + statement.setString(3, notary.name.toString()) + paramOffset += 1 + } + if (onlyFromIssuerParties.isNotEmpty()) { + val issuerKeys = connection.createArrayOf("VARCHAR", onlyFromIssuerParties.map + { it.owningKey.toBase58String() }.toTypedArray()) + statement.setArray(3 + paramOffset, issuerKeys) + paramOffset += 1 + } + if (withIssuerRefs.isNotEmpty()) { + val issuerRefs = connection.createArrayOf("BYTEA", withIssuerRefs.map + { it.bytes }.toTypedArray()) + statement.setArray(3 + paramOffset, issuerRefs) + paramOffset += 1 + } + statement.setLong(3 + paramOffset, amount.quantity) + log.debug { statement.toString() } - return statement.executeQuery() + statement.executeQuery().use { rs -> + return withResultSet(rs) + } + } } } diff --git a/finance/src/test/java/net/corda/finance/contracts/asset/CashTestsJava.java b/finance/src/test/java/net/corda/finance/contracts/asset/CashTestsJava.java index 0a4f3b9849..bfff1987d1 100644 --- a/finance/src/test/java/net/corda/finance/contracts/asset/CashTestsJava.java +++ b/finance/src/test/java/net/corda/finance/contracts/asset/CashTestsJava.java @@ -32,34 +32,34 @@ public class CashTestsJava { tx.input(Cash.PROGRAM_ID, inState); tx.tweak(tw -> { - tw.output(Cash.PROGRAM_ID, () -> new Cash.State(issuedBy(DOLLARS(2000), defaultIssuer), new AnonymousParty(getMINI_CORP_PUBKEY()))); + tw.output(Cash.PROGRAM_ID, new Cash.State(issuedBy(DOLLARS(2000), defaultIssuer), new AnonymousParty(getMINI_CORP_PUBKEY()))); tw.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move()); return tw.failsWith("the amounts balance"); }); tx.tweak(tw -> { - tw.output(Cash.PROGRAM_ID, () -> outState); + tw.output(Cash.PROGRAM_ID, outState); tw.command(getMEGA_CORP_PUBKEY(), DummyCommandData.INSTANCE); // Invalid command return tw.failsWith("required net.corda.finance.contracts.asset.Cash.Commands.Move command"); }); tx.tweak(tw -> { - tw.output(Cash.PROGRAM_ID, () -> outState); + tw.output(Cash.PROGRAM_ID, outState); tw.command(getMINI_CORP_PUBKEY(), new Cash.Commands.Move()); return tw.failsWith("the owning keys are a subset of the signing keys"); }); tx.tweak(tw -> { - tw.output(Cash.PROGRAM_ID, () -> outState); + tw.output(Cash.PROGRAM_ID, outState); // issuedBy() can't be directly imported because it conflicts with other identically named functions // with different overloads (for some reason). - tw.output(Cash.PROGRAM_ID, () -> outState.issuedBy(getMINI_CORP())); + tw.output(Cash.PROGRAM_ID, outState.issuedBy(getMINI_CORP())); tw.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move()); return tw.failsWith("at least one cash input"); }); // Simple reallocation works. return tx.tweak(tw -> { - tw.output(Cash.PROGRAM_ID, () -> outState); + tw.output(Cash.PROGRAM_ID, outState); tw.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move()); return tw.verifies(); }); diff --git a/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt b/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt index e4056fe36c..0684675724 100644 --- a/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt +++ b/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt @@ -106,8 +106,8 @@ class CommercialPaperTestsGeneric { // Some CP is issued onto the ledger by MegaCorp. transaction("Issuance") { attachments(CP_PROGRAM_ID, JavaCommercialPaper.JCP_PROGRAM_ID) - output(thisTest.getContract(), "paper") { thisTest.getPaper() } - command(MEGA_CORP_PUBKEY) { thisTest.getIssueCommand(DUMMY_NOTARY) } + output(thisTest.getContract(), "paper", thisTest.getPaper()) + command(MEGA_CORP_PUBKEY, thisTest.getIssueCommand(DUMMY_NOTARY)) timeWindow(TEST_TX_TIME) this.verifies() } @@ -118,10 +118,10 @@ class CommercialPaperTestsGeneric { attachments(Cash.PROGRAM_ID, JavaCommercialPaper.JCP_PROGRAM_ID) input("paper") input("alice's $900") - output(Cash.PROGRAM_ID, "borrowed $900") { 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP } - output(thisTest.getContract(), "alice's paper") { "paper".output().withOwner(ALICE) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } - command(MEGA_CORP_PUBKEY) { thisTest.getMoveCommand() } + output(Cash.PROGRAM_ID, "borrowed $900", 900.DOLLARS.CASH issuedBy issuer ownedBy MEGA_CORP) + output(thisTest.getContract(), "alice's paper", "paper".output().withOwner(ALICE)) + command(ALICE_PUBKEY, Cash.Commands.Move()) + command(MEGA_CORP_PUBKEY, thisTest.getMoveCommand()) this.verifies() } @@ -133,13 +133,11 @@ class CommercialPaperTestsGeneric { input("some profits") fun TransactionDSL.outputs(aliceGetsBack: Amount>) { - output(Cash.PROGRAM_ID, "Alice's profit") { aliceGetsBack.STATE ownedBy ALICE } - output(Cash.PROGRAM_ID, "Change") { (someProfits - aliceGetsBack).STATE ownedBy MEGA_CORP } + output(Cash.PROGRAM_ID, "Alice's profit", aliceGetsBack.STATE ownedBy ALICE) + output(Cash.PROGRAM_ID, "Change", (someProfits - aliceGetsBack).STATE ownedBy MEGA_CORP) } - - command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() } - command(ALICE_PUBKEY) { thisTest.getRedeemCommand(DUMMY_NOTARY) } - + command(MEGA_CORP_PUBKEY, Cash.Commands.Move()) + command(ALICE_PUBKEY, thisTest.getRedeemCommand(DUMMY_NOTARY)) tweak { outputs(700.DOLLARS `issued by` issuer) timeWindow(TEST_TX_TIME + 8.days) @@ -155,7 +153,7 @@ class CommercialPaperTestsGeneric { timeWindow(TEST_TX_TIME + 8.days) tweak { - output(thisTest.getContract()) { "paper".output() } + output(thisTest.getContract(), "paper".output()) this `fails with` "must be destroyed" } @@ -169,8 +167,8 @@ class CommercialPaperTestsGeneric { transaction { attachment(CP_PROGRAM_ID) attachment(JavaCommercialPaper.JCP_PROGRAM_ID) - output(thisTest.getContract()) { thisTest.getPaper() } - command(MINI_CORP_PUBKEY) { thisTest.getIssueCommand(DUMMY_NOTARY) } + output(thisTest.getContract(), thisTest.getPaper()) + command(MINI_CORP_PUBKEY, thisTest.getIssueCommand(DUMMY_NOTARY)) timeWindow(TEST_TX_TIME) this `fails with` "output states are issued by a command signer" } @@ -181,8 +179,8 @@ class CommercialPaperTestsGeneric { transaction { attachment(CP_PROGRAM_ID) attachment(JavaCommercialPaper.JCP_PROGRAM_ID) - output(thisTest.getContract()) { thisTest.getPaper().withFaceValue(0.DOLLARS `issued by` issuer) } - command(MEGA_CORP_PUBKEY) { thisTest.getIssueCommand(DUMMY_NOTARY) } + output(thisTest.getContract(), thisTest.getPaper().withFaceValue(0.DOLLARS `issued by` issuer)) + command(MEGA_CORP_PUBKEY, thisTest.getIssueCommand(DUMMY_NOTARY)) timeWindow(TEST_TX_TIME) this `fails with` "output values sum to more than the inputs" } @@ -193,8 +191,8 @@ class CommercialPaperTestsGeneric { transaction { attachment(CP_PROGRAM_ID) attachment(JavaCommercialPaper.JCP_PROGRAM_ID) - output(thisTest.getContract()) { thisTest.getPaper().withMaturityDate(TEST_TX_TIME - 10.days) } - command(MEGA_CORP_PUBKEY) { thisTest.getIssueCommand(DUMMY_NOTARY) } + output(thisTest.getContract(), thisTest.getPaper().withMaturityDate(TEST_TX_TIME - 10.days)) + command(MEGA_CORP_PUBKEY, thisTest.getIssueCommand(DUMMY_NOTARY)) timeWindow(TEST_TX_TIME) this `fails with` "maturity date is not in the past" } @@ -206,8 +204,8 @@ class CommercialPaperTestsGeneric { attachment(CP_PROGRAM_ID) attachment(JavaCommercialPaper.JCP_PROGRAM_ID) input(thisTest.getContract(), thisTest.getPaper()) - output(thisTest.getContract()) { thisTest.getPaper() } - command(MEGA_CORP_PUBKEY) { thisTest.getIssueCommand(DUMMY_NOTARY) } + output(thisTest.getContract(), thisTest.getPaper()) + command(MEGA_CORP_PUBKEY, thisTest.getIssueCommand(DUMMY_NOTARY)) timeWindow(TEST_TX_TIME) this `fails with` "output values sum to more than the inputs" } diff --git a/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt b/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt index e2dd05dd2b..faa9665f63 100644 --- a/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt +++ b/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt @@ -111,34 +111,33 @@ class CashTests { fun trivial() { transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - + input(Cash.PROGRAM_ID, inState) tweak { - output(Cash.PROGRAM_ID) { outState.copy(amount = 2000.DOLLARS `issued by` defaultIssuer) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + output(Cash.PROGRAM_ID, outState.copy(amount = 2000.DOLLARS `issued by` defaultIssuer)) + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "the amounts balance" } tweak { - output(Cash.PROGRAM_ID) { outState } - command(ALICE_PUBKEY) { DummyCommandData } + output(Cash.PROGRAM_ID, outState) + command(ALICE_PUBKEY, DummyCommandData) // Invalid command this `fails with` "required net.corda.finance.contracts.asset.Cash.Commands.Move command" } tweak { - output(Cash.PROGRAM_ID) { outState } - command(BOB_PUBKEY) { Cash.Commands.Move() } + output(Cash.PROGRAM_ID, outState) + command(BOB_PUBKEY, Cash.Commands.Move()) this `fails with` "the owning keys are a subset of the signing keys" } tweak { - output(Cash.PROGRAM_ID) { outState } - output(Cash.PROGRAM_ID) { outState issuedBy MINI_CORP } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + output(Cash.PROGRAM_ID, outState) + output(Cash.PROGRAM_ID, outState issuedBy MINI_CORP) + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "at least one cash input" } // Simple reallocation works. tweak { - output(Cash.PROGRAM_ID) { outState } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + output(Cash.PROGRAM_ID, outState) + command(ALICE_PUBKEY, Cash.Commands.Move()) this.verifies() } } @@ -149,10 +148,9 @@ class CashTests { // Check we can't "move" money into existence. transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { DummyState() } - output(Cash.PROGRAM_ID) { outState } - command(MINI_CORP_PUBKEY) { Cash.Commands.Move() } - + input(Cash.PROGRAM_ID, DummyState()) + output(Cash.PROGRAM_ID, outState) + command(MINI_CORP_PUBKEY, Cash.Commands.Move()) this `fails with` "there is at least one cash input for this group" } } @@ -163,19 +161,17 @@ class CashTests { // institution is allowed to issue as much cash as they want. transaction { attachment(Cash.PROGRAM_ID) - output(Cash.PROGRAM_ID) { outState } - command(ALICE_PUBKEY) { Cash.Commands.Issue() } + output(Cash.PROGRAM_ID, outState) + command(ALICE_PUBKEY, Cash.Commands.Issue()) this `fails with` "output states are issued by a command signer" } transaction { attachment(Cash.PROGRAM_ID) - output(Cash.PROGRAM_ID) { + output(Cash.PROGRAM_ID, Cash.State( amount = 1000.DOLLARS `issued by` MINI_CORP.ref(12, 34), - owner = AnonymousParty(ALICE_PUBKEY) - ) - } - command(MINI_CORP_PUBKEY) { Cash.Commands.Issue() } + owner = AnonymousParty(ALICE_PUBKEY))) + command(MINI_CORP_PUBKEY, Cash.Commands.Issue()) this.verifies() } } @@ -211,18 +207,17 @@ class CashTests { // We can consume $1000 in a transaction and output $2000 as long as it's signed by an issuer. transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { issuerInState } - output(Cash.PROGRAM_ID) { inState.copy(amount = inState.amount * 2) } - + input(Cash.PROGRAM_ID, issuerInState) + output(Cash.PROGRAM_ID, inState.copy(amount = inState.amount * 2)) // Move fails: not allowed to summon money. tweak { - command(ALICE_PUBKEY) { Cash.Commands.Move() } + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "the amounts balance" } // Issue works. tweak { - command(MEGA_CORP_PUBKEY) { Cash.Commands.Issue() } + command(MEGA_CORP_PUBKEY, Cash.Commands.Issue()) this.verifies() } } @@ -230,29 +225,29 @@ class CashTests { // Can't use an issue command to lower the amount. transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - output(Cash.PROGRAM_ID) { inState.copy(amount = inState.amount.splitEvenly(2).first()) } - command(MEGA_CORP_PUBKEY) { Cash.Commands.Issue() } + input(Cash.PROGRAM_ID, inState) + output(Cash.PROGRAM_ID, inState.copy(amount = inState.amount.splitEvenly(2).first())) + command(MEGA_CORP_PUBKEY, Cash.Commands.Issue()) this `fails with` "output values sum to more than the inputs" } // Can't have an issue command that doesn't actually issue money. transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - output(Cash.PROGRAM_ID) { inState } - command(MEGA_CORP_PUBKEY) { Cash.Commands.Issue() } + input(Cash.PROGRAM_ID, inState) + output(Cash.PROGRAM_ID, inState) + command(MEGA_CORP_PUBKEY, Cash.Commands.Issue()) this `fails with` "output values sum to more than the inputs" } // Can't have any other commands if we have an issue command (because the issue command overrules them) transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - output(Cash.PROGRAM_ID) { inState.copy(amount = inState.amount * 2) } - command(MEGA_CORP_PUBKEY) { Cash.Commands.Issue() } + input(Cash.PROGRAM_ID, inState) + output(Cash.PROGRAM_ID, inState.copy(amount = inState.amount * 2)) + command(MEGA_CORP_PUBKEY, Cash.Commands.Issue()) tweak { - command(MEGA_CORP_PUBKEY) { Cash.Commands.Issue() } + command(MEGA_CORP_PUBKEY, Cash.Commands.Issue()) this `fails with` "there is only a single issue command" } this.verifies() @@ -282,26 +277,26 @@ class CashTests { // Splitting value works. transaction { attachment(Cash.PROGRAM_ID) - command(ALICE_PUBKEY) { Cash.Commands.Move() } + command(ALICE_PUBKEY, Cash.Commands.Move()) tweak { - input(Cash.PROGRAM_ID) { inState } + input(Cash.PROGRAM_ID, inState) val splits4 = inState.amount.splitEvenly(4) - for (i in 0..3) output(Cash.PROGRAM_ID) { inState.copy(amount = splits4[i]) } + for (i in 0..3) output(Cash.PROGRAM_ID, inState.copy(amount = splits4[i])) this.verifies() } // Merging 4 inputs into 2 outputs works. tweak { val splits2 = inState.amount.splitEvenly(2) val splits4 = inState.amount.splitEvenly(4) - for (i in 0..3) input(Cash.PROGRAM_ID) { inState.copy(amount = splits4[i]) } - for (i in 0..1) output(Cash.PROGRAM_ID) { inState.copy(amount = splits2[i]) } + for (i in 0..3) input(Cash.PROGRAM_ID, inState.copy(amount = splits4[i])) + for (i in 0..1) output(Cash.PROGRAM_ID, inState.copy(amount = splits2[i])) this.verifies() } // Merging 2 inputs into 1 works. tweak { val splits2 = inState.amount.splitEvenly(2) - for (i in 0..1) input(Cash.PROGRAM_ID) { inState.copy(amount = splits2[i]) } - output(Cash.PROGRAM_ID) { inState } + for (i in 0..1) input(Cash.PROGRAM_ID, inState.copy(amount = splits2[i])) + output(Cash.PROGRAM_ID, inState) this.verifies() } } @@ -311,17 +306,17 @@ class CashTests { fun zeroSizedValues() { transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - input(Cash.PROGRAM_ID) { inState.copy(amount = 0.DOLLARS `issued by` defaultIssuer) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + input(Cash.PROGRAM_ID, inState) + input(Cash.PROGRAM_ID, inState.copy(amount = 0.DOLLARS `issued by` defaultIssuer)) + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "zero sized inputs" } transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - output(Cash.PROGRAM_ID) { inState } - output(Cash.PROGRAM_ID) { inState.copy(amount = 0.DOLLARS `issued by` defaultIssuer) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + input(Cash.PROGRAM_ID, inState) + output(Cash.PROGRAM_ID, inState) + output(Cash.PROGRAM_ID, inState.copy(amount = 0.DOLLARS `issued by` defaultIssuer)) + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "zero sized outputs" } } @@ -331,58 +326,56 @@ class CashTests { // Can't change issuer. transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - output(Cash.PROGRAM_ID) { outState issuedBy MINI_CORP } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + input(Cash.PROGRAM_ID, inState) + output(Cash.PROGRAM_ID, outState issuedBy MINI_CORP) + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "the amounts balance" } // Can't change deposit reference when splitting. transaction { attachment(Cash.PROGRAM_ID) val splits2 = inState.amount.splitEvenly(2) - input(Cash.PROGRAM_ID) { inState } - for (i in 0..1) output(Cash.PROGRAM_ID) { outState.copy(amount = splits2[i]).editDepositRef(i.toByte()) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + input(Cash.PROGRAM_ID, inState) + for (i in 0..1) output(Cash.PROGRAM_ID, outState.copy(amount = splits2[i]).editDepositRef(i.toByte())) + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "the amounts balance" } // Can't mix currencies. transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - output(Cash.PROGRAM_ID) { outState.copy(amount = 800.DOLLARS `issued by` defaultIssuer) } - output(Cash.PROGRAM_ID) { outState.copy(amount = 200.POUNDS `issued by` defaultIssuer) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + input(Cash.PROGRAM_ID, inState) + output(Cash.PROGRAM_ID, outState.copy(amount = 800.DOLLARS `issued by` defaultIssuer)) + output(Cash.PROGRAM_ID, outState.copy(amount = 200.POUNDS `issued by` defaultIssuer)) + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "the amounts balance" } transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - input(Cash.PROGRAM_ID) { + input(Cash.PROGRAM_ID, inState) + input(Cash.PROGRAM_ID, inState.copy( amount = 150.POUNDS `issued by` defaultIssuer, - owner = AnonymousParty(BOB_PUBKEY) - ) - } - output(Cash.PROGRAM_ID) { outState.copy(amount = 1150.DOLLARS `issued by` defaultIssuer) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + owner = AnonymousParty(BOB_PUBKEY))) + output(Cash.PROGRAM_ID, outState.copy(amount = 1150.DOLLARS `issued by` defaultIssuer)) + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "the amounts balance" } // Can't have superfluous input states from different issuers. transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - input(Cash.PROGRAM_ID) { inState issuedBy MINI_CORP } - output(Cash.PROGRAM_ID) { outState } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + input(Cash.PROGRAM_ID, inState) + input(Cash.PROGRAM_ID, inState issuedBy MINI_CORP) + output(Cash.PROGRAM_ID, outState) + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "the amounts balance" } // Can't combine two different deposits at the same issuer. transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - input(Cash.PROGRAM_ID) { inState.editDepositRef(3) } - output(Cash.PROGRAM_ID) { outState.copy(amount = inState.amount * 2).editDepositRef(3) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + input(Cash.PROGRAM_ID, inState) + input(Cash.PROGRAM_ID, inState.editDepositRef(3)) + output(Cash.PROGRAM_ID, outState.copy(amount = inState.amount * 2).editDepositRef(3)) + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "for reference [01]" } } @@ -392,21 +385,20 @@ class CashTests { // Single input/output straightforward case. transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { issuerInState } - output(Cash.PROGRAM_ID) { issuerInState.copy(amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) } - + input(Cash.PROGRAM_ID, issuerInState) + output(Cash.PROGRAM_ID, issuerInState.copy(amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer))) tweak { - command(MEGA_CORP_PUBKEY) { Cash.Commands.Exit(100.DOLLARS `issued by` defaultIssuer) } - command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() } + command(MEGA_CORP_PUBKEY, Cash.Commands.Exit(100.DOLLARS `issued by` defaultIssuer)) + command(MEGA_CORP_PUBKEY, Cash.Commands.Move()) this `fails with` "the amounts balance" } tweak { - command(MEGA_CORP_PUBKEY) { Cash.Commands.Exit(200.DOLLARS `issued by` defaultIssuer) } + command(MEGA_CORP_PUBKEY, Cash.Commands.Exit(200.DOLLARS `issued by` defaultIssuer)) this `fails with` "required net.corda.finance.contracts.asset.Cash.Commands.Move command" tweak { - command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() } + command(MEGA_CORP_PUBKEY, Cash.Commands.Move()) this.verifies() } } @@ -418,20 +410,15 @@ class CashTests { // Multi-issuer case. transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { issuerInState } - input(Cash.PROGRAM_ID) { issuerInState.copy(owner = MINI_CORP) issuedBy MINI_CORP } - - output(Cash.PROGRAM_ID) { issuerInState.copy(amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) issuedBy MINI_CORP } - output(Cash.PROGRAM_ID) { issuerInState.copy(owner = MINI_CORP, amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) } - - command(MEGA_CORP_PUBKEY, MINI_CORP_PUBKEY) { Cash.Commands.Move() } - + input(Cash.PROGRAM_ID, issuerInState) + input(Cash.PROGRAM_ID, issuerInState.copy(owner = MINI_CORP) issuedBy MINI_CORP) + output(Cash.PROGRAM_ID, issuerInState.copy(amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) issuedBy MINI_CORP) + output(Cash.PROGRAM_ID, issuerInState.copy(owner = MINI_CORP, amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer))) + command(listOf(MEGA_CORP_PUBKEY, MINI_CORP_PUBKEY), Cash.Commands.Move()) this `fails with` "the amounts balance" - - command(MEGA_CORP_PUBKEY) { Cash.Commands.Exit(200.DOLLARS `issued by` defaultIssuer) } + command(MEGA_CORP_PUBKEY, Cash.Commands.Exit(200.DOLLARS `issued by` defaultIssuer)) this `fails with` "the amounts balance" - - command(MINI_CORP_PUBKEY) { Cash.Commands.Exit(200.DOLLARS `issued by` MINI_CORP.ref(defaultRef)) } + command(MINI_CORP_PUBKEY, Cash.Commands.Exit(200.DOLLARS `issued by` MINI_CORP.ref(defaultRef))) this.verifies() } } @@ -441,10 +428,10 @@ class CashTests { // Single input/output straightforward case. transaction { attachment(Cash.PROGRAM_ID) - input(Cash.PROGRAM_ID) { inState } - output(Cash.PROGRAM_ID) { outState.copy(amount = inState.amount - (200.DOLLARS `issued by` defaultIssuer)) } - command(MEGA_CORP_PUBKEY) { Cash.Commands.Exit(200.DOLLARS `issued by` defaultIssuer) } - command(ALICE_PUBKEY) { Cash.Commands.Move() } + input(Cash.PROGRAM_ID, inState) + output(Cash.PROGRAM_ID, outState.copy(amount = inState.amount - (200.DOLLARS `issued by` defaultIssuer))) + command(MEGA_CORP_PUBKEY, Cash.Commands.Exit(200.DOLLARS `issued by` defaultIssuer)) + command(ALICE_PUBKEY, Cash.Commands.Move()) this `fails with` "the amounts balance" } } @@ -454,25 +441,24 @@ class CashTests { transaction { attachment(Cash.PROGRAM_ID) // Gather 2000 dollars from two different issuers. - input(Cash.PROGRAM_ID) { inState } - input(Cash.PROGRAM_ID) { inState issuedBy MINI_CORP } - command(ALICE_PUBKEY) { Cash.Commands.Move() } - + input(Cash.PROGRAM_ID, inState) + input(Cash.PROGRAM_ID, inState issuedBy MINI_CORP) + command(ALICE_PUBKEY, Cash.Commands.Move()) // Can't merge them together. tweak { - output(Cash.PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY), amount = 2000.DOLLARS `issued by` defaultIssuer) } + output(Cash.PROGRAM_ID, inState.copy(owner = AnonymousParty(BOB_PUBKEY), amount = 2000.DOLLARS `issued by` defaultIssuer)) this `fails with` "the amounts balance" } // Missing MiniCorp deposit tweak { - output(Cash.PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) } - output(Cash.PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) } + output(Cash.PROGRAM_ID, inState.copy(owner = AnonymousParty(BOB_PUBKEY))) + output(Cash.PROGRAM_ID, inState.copy(owner = AnonymousParty(BOB_PUBKEY))) this `fails with` "the amounts balance" } // This works. - output(Cash.PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) } - output(Cash.PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) issuedBy MINI_CORP } + output(Cash.PROGRAM_ID, inState.copy(owner = AnonymousParty(BOB_PUBKEY))) + output(Cash.PROGRAM_ID, inState.copy(owner = AnonymousParty(BOB_PUBKEY)) issuedBy MINI_CORP) this.verifies() } } @@ -483,12 +469,11 @@ class CashTests { transaction { attachment(Cash.PROGRAM_ID) val pounds = Cash.State(658.POUNDS `issued by` MINI_CORP.ref(3, 4, 5), AnonymousParty(BOB_PUBKEY)) - input(Cash.PROGRAM_ID) { inState ownedBy AnonymousParty(ALICE_PUBKEY) } - input(Cash.PROGRAM_ID) { pounds } - output(Cash.PROGRAM_ID) { inState ownedBy AnonymousParty(BOB_PUBKEY) } - output(Cash.PROGRAM_ID) { pounds ownedBy AnonymousParty(ALICE_PUBKEY) } - command(ALICE_PUBKEY, BOB_PUBKEY) { Cash.Commands.Move() } - + input(Cash.PROGRAM_ID, inState ownedBy AnonymousParty(ALICE_PUBKEY)) + input(Cash.PROGRAM_ID, pounds) + output(Cash.PROGRAM_ID, inState ownedBy AnonymousParty(BOB_PUBKEY)) + output(Cash.PROGRAM_ID, pounds ownedBy AnonymousParty(ALICE_PUBKEY)) + command(listOf(ALICE_PUBKEY, BOB_PUBKEY), Cash.Commands.Move()) this.verifies() } } @@ -792,19 +777,17 @@ class CashTests { ledger(mockService) { unverifiedTransaction { attachment(Cash.PROGRAM_ID) - output(Cash.PROGRAM_ID, "MEGA_CORP cash") { + output(Cash.PROGRAM_ID, "MEGA_CORP cash", Cash.State( amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1), - owner = MEGA_CORP - ) - } + owner = MEGA_CORP)) } transaction { attachment(Cash.PROGRAM_ID) input("MEGA_CORP cash") output(Cash.PROGRAM_ID, "MEGA_CORP cash 2", "MEGA_CORP cash".output().copy(owner = AnonymousParty(ALICE_PUBKEY))) - command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() } + command(MEGA_CORP_PUBKEY, Cash.Commands.Move()) this.verifies() } @@ -814,7 +797,7 @@ class CashTests { input("MEGA_CORP cash") // We send it to another pubkey so that the transaction is not identical to the previous one output(Cash.PROGRAM_ID, "MEGA_CORP cash 3", "MEGA_CORP cash".output().copy(owner = ALICE)) - command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() } + command(MEGA_CORP_PUBKEY, Cash.Commands.Move()) this.verifies() } this.fails() diff --git a/finance/src/test/kotlin/net/corda/finance/contracts/asset/ObligationTests.kt b/finance/src/test/kotlin/net/corda/finance/contracts/asset/ObligationTests.kt index b927f09516..22e7db887f 100644 --- a/finance/src/test/kotlin/net/corda/finance/contracts/asset/ObligationTests.kt +++ b/finance/src/test/kotlin/net/corda/finance/contracts/asset/ObligationTests.kt @@ -71,34 +71,33 @@ class ObligationTests { fun trivial() { transaction { attachments(Obligation.PROGRAM_ID) - input(Obligation.PROGRAM_ID) { inState } - + input(Obligation.PROGRAM_ID, inState) tweak { - output(Obligation.PROGRAM_ID) { outState.copy(quantity = 2000.DOLLARS.quantity) } - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + output(Obligation.PROGRAM_ID, outState.copy(quantity = 2000.DOLLARS.quantity)) + command(CHARLIE.owningKey, Obligation.Commands.Move()) this `fails with` "the amounts balance" } tweak { - output(Obligation.PROGRAM_ID) { outState } - command(CHARLIE.owningKey) { DummyCommandData } + output(Obligation.PROGRAM_ID, outState) + command(CHARLIE.owningKey, DummyCommandData) // Invalid command this `fails with` "required net.corda.finance.contracts.asset.Obligation.Commands.Move command" } tweak { - output(Obligation.PROGRAM_ID) { outState } - command(BOB_PUBKEY) { Obligation.Commands.Move() } + output(Obligation.PROGRAM_ID, outState) + command(BOB_PUBKEY, Obligation.Commands.Move()) this `fails with` "the owning keys are a subset of the signing keys" } tweak { - output(Obligation.PROGRAM_ID) { outState } - output(Obligation.PROGRAM_ID) { outState `issued by` MINI_CORP } - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + output(Obligation.PROGRAM_ID, outState) + output(Obligation.PROGRAM_ID, outState `issued by` MINI_CORP) + command(CHARLIE.owningKey, Obligation.Commands.Move()) this `fails with` "at least one obligation input" } // Simple reallocation works. tweak { - output(Obligation.PROGRAM_ID) { outState } - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + output(Obligation.PROGRAM_ID, outState) + command(CHARLIE.owningKey, Obligation.Commands.Move()) this.verifies() } } @@ -109,10 +108,9 @@ class ObligationTests { // Check we can't "move" debt into existence. transaction { attachments(DummyContract.PROGRAM_ID, Obligation.PROGRAM_ID) - input(DummyContract.PROGRAM_ID) { DummyState() } - output(Obligation.PROGRAM_ID) { outState } - command(MINI_CORP_PUBKEY) { Obligation.Commands.Move() } - + input(DummyContract.PROGRAM_ID, DummyState()) + output(Obligation.PROGRAM_ID, outState) + command(MINI_CORP_PUBKEY, Obligation.Commands.Move()) this `fails with` "at least one obligation input" } @@ -120,21 +118,19 @@ class ObligationTests { // institution is allowed to issue as much cash as they want. transaction { attachments(Obligation.PROGRAM_ID) - output(Obligation.PROGRAM_ID) { outState } - command(CHARLIE.owningKey) { Obligation.Commands.Issue() } + output(Obligation.PROGRAM_ID, outState) + command(CHARLIE.owningKey, Obligation.Commands.Issue()) this `fails with` "output states are issued by a command signer" } transaction { attachments(Obligation.PROGRAM_ID) - output(Obligation.PROGRAM_ID) { + output(Obligation.PROGRAM_ID, Obligation.State( obligor = MINI_CORP, quantity = 1000.DOLLARS.quantity, beneficiary = CHARLIE, - template = megaCorpDollarSettlement - ) - } - command(MINI_CORP_PUBKEY) { Obligation.Commands.Issue() } + template = megaCorpDollarSettlement)) + command(MINI_CORP_PUBKEY, Obligation.Commands.Issue()) this.verifies() } run { @@ -157,18 +153,17 @@ class ObligationTests { // We can consume $1000 in a transaction and output $2000 as long as it's signed by an issuer. transaction { attachments(Obligation.PROGRAM_ID) - input(Obligation.PROGRAM_ID) { inState } - output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.amount.quantity * 2) } - + input(Obligation.PROGRAM_ID, inState) + output(Obligation.PROGRAM_ID, inState.copy(quantity = inState.amount.quantity * 2)) // Move fails: not allowed to summon money. tweak { - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + command(CHARLIE.owningKey, Obligation.Commands.Move()) this `fails with` "the amounts balance" } // Issue works. tweak { - command(MEGA_CORP_PUBKEY) { Obligation.Commands.Issue() } + command(MEGA_CORP_PUBKEY, Obligation.Commands.Issue()) this.verifies() } } @@ -176,29 +171,29 @@ class ObligationTests { // Can't use an issue command to lower the amount. transaction { attachments(Obligation.PROGRAM_ID) - input(Obligation.PROGRAM_ID) { inState } - output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.amount.quantity / 2) } - command(MEGA_CORP_PUBKEY) { Obligation.Commands.Issue() } + input(Obligation.PROGRAM_ID, inState) + output(Obligation.PROGRAM_ID, inState.copy(quantity = inState.amount.quantity / 2)) + command(MEGA_CORP_PUBKEY, Obligation.Commands.Issue()) this `fails with` "output values sum to more than the inputs" } // Can't have an issue command that doesn't actually issue money. transaction { attachments(Obligation.PROGRAM_ID) - input(Obligation.PROGRAM_ID) { inState } - output(Obligation.PROGRAM_ID) { inState } - command(MEGA_CORP_PUBKEY) { Obligation.Commands.Issue() } + input(Obligation.PROGRAM_ID, inState) + output(Obligation.PROGRAM_ID, inState) + command(MEGA_CORP_PUBKEY, Obligation.Commands.Issue()) this `fails with` "" } // Can't have any other commands if we have an issue command (because the issue command overrules them). transaction { attachments(Obligation.PROGRAM_ID) - input(Obligation.PROGRAM_ID) { inState } - output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.amount.quantity * 2) } - command(MEGA_CORP_PUBKEY) { Obligation.Commands.Issue() } + input(Obligation.PROGRAM_ID, inState) + output(Obligation.PROGRAM_ID, inState.copy(quantity = inState.amount.quantity * 2)) + command(MEGA_CORP_PUBKEY, Obligation.Commands.Issue()) tweak { - command(MEGA_CORP_PUBKEY) { Obligation.Commands.Issue() } + command(MEGA_CORP_PUBKEY, Obligation.Commands.Issue()) this `fails with` "there is only a single issue command" } this.verifies() @@ -352,7 +347,7 @@ class ObligationTests { input("Alice's $1,000,000 obligation to Bob") input("Bob's $1,000,000 obligation to Alice") // Note we can sign with either key here - command(ALICE_PUBKEY) { Obligation.Commands.Net(NetType.CLOSE_OUT) } + command(ALICE_PUBKEY, Obligation.Commands.Net(NetType.CLOSE_OUT)) timeWindow(TEST_TX_TIME) this.verifies() } @@ -368,8 +363,8 @@ class ObligationTests { input("Alice's $1,000,000 obligation to Bob") input("Bob's $1,000,000 obligation to Alice") input("MegaCorp's $1,000,000 obligation to Bob") - output(Obligation.PROGRAM_ID, "change") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, BOB) } - command(BOB_PUBKEY, MEGA_CORP_PUBKEY) { Obligation.Commands.Net(NetType.CLOSE_OUT) } + output(Obligation.PROGRAM_ID, "change", oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, BOB)) + command(listOf(BOB_PUBKEY, MEGA_CORP_PUBKEY), Obligation.Commands.Net(NetType.CLOSE_OUT)) timeWindow(TEST_TX_TIME) this.verifies() } @@ -383,8 +378,8 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID) input("Alice's $1,000,000 obligation to Bob") input("Bob's $1,000,000 obligation to Alice") - output(Obligation.PROGRAM_ID, "change") { (oneMillionDollars.splitEvenly(2).first()).OBLIGATION between Pair(ALICE, BOB) } - command(BOB_PUBKEY) { Obligation.Commands.Net(NetType.CLOSE_OUT) } + output(Obligation.PROGRAM_ID, "change", oneMillionDollars.splitEvenly(2).first().OBLIGATION between Pair(ALICE, BOB)) + command(BOB_PUBKEY, Obligation.Commands.Net(NetType.CLOSE_OUT)) timeWindow(TEST_TX_TIME) this `fails with` "amounts owed on input and output must match" } @@ -397,7 +392,7 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID) input("Alice's $1,000,000 obligation to Bob") input("Bob's $1,000,000 obligation to Alice") - command(MEGA_CORP_PUBKEY) { Obligation.Commands.Net(NetType.CLOSE_OUT) } + command(MEGA_CORP_PUBKEY, Obligation.Commands.Net(NetType.CLOSE_OUT)) timeWindow(TEST_TX_TIME) this `fails with` "any involved party has signed" } @@ -413,7 +408,7 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID) input("Alice's $1,000,000 obligation to Bob") input("Bob's $1,000,000 obligation to Alice") - command(ALICE_PUBKEY, BOB_PUBKEY) { Obligation.Commands.Net(NetType.PAYMENT) } + command(listOf(ALICE_PUBKEY, BOB_PUBKEY), Obligation.Commands.Net(NetType.PAYMENT)) timeWindow(TEST_TX_TIME) this.verifies() } @@ -428,7 +423,7 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID) input("Alice's $1,000,000 obligation to Bob") input("Bob's $1,000,000 obligation to Alice") - command(BOB_PUBKEY) { Obligation.Commands.Net(NetType.PAYMENT) } + command(BOB_PUBKEY, Obligation.Commands.Net(NetType.PAYMENT)) timeWindow(TEST_TX_TIME) this `fails with` "all involved parties have signed" } @@ -441,8 +436,8 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID) input("Bob's $1,000,000 obligation to Alice") input("MegaCorp's $1,000,000 obligation to Bob") - output(Obligation.PROGRAM_ID, "MegaCorp's $1,000,000 obligation to Alice") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, ALICE) } - command(ALICE_PUBKEY, BOB_PUBKEY, MEGA_CORP_PUBKEY) { Obligation.Commands.Net(NetType.PAYMENT) } + output(Obligation.PROGRAM_ID, "MegaCorp's $1,000,000 obligation to Alice", oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, ALICE)) + command(listOf(ALICE_PUBKEY, BOB_PUBKEY, MEGA_CORP_PUBKEY), Obligation.Commands.Net(NetType.PAYMENT)) timeWindow(TEST_TX_TIME) this.verifies() } @@ -456,8 +451,8 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID) input("Bob's $1,000,000 obligation to Alice") input("MegaCorp's $1,000,000 obligation to Bob") - output(Obligation.PROGRAM_ID, "MegaCorp's $1,000,000 obligation to Alice") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, ALICE) } - command(ALICE_PUBKEY, BOB_PUBKEY) { Obligation.Commands.Net(NetType.PAYMENT) } + output(Obligation.PROGRAM_ID, "MegaCorp's $1,000,000 obligation to Alice", oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, ALICE)) + command(listOf(ALICE_PUBKEY, BOB_PUBKEY), Obligation.Commands.Net(NetType.PAYMENT)) timeWindow(TEST_TX_TIME) this `fails with` "all involved parties have signed" } @@ -473,9 +468,9 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID) input("Alice's $1,000,000 obligation to Bob") input("Alice's $1,000,000") - output(Obligation.PROGRAM_ID, "Bob's $1,000,000") { 1000000.DOLLARS.CASH issuedBy defaultIssuer ownedBy BOB } - command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity, inState.amount.token)) } - command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation::class.java) } + output(Obligation.PROGRAM_ID, "Bob's $1,000,000", 1000000.DOLLARS.CASH issuedBy defaultIssuer ownedBy BOB) + command(ALICE_PUBKEY, Obligation.Commands.Settle(Amount(oneMillionDollars.quantity, inState.amount.token))) + command(ALICE_PUBKEY, Cash.Commands.Move(Obligation::class.java)) attachment(attachment(cashContractBytes.inputStream())) this.verifies() } @@ -488,10 +483,10 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID, Cash.PROGRAM_ID) input(Obligation.PROGRAM_ID, oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)) input(Cash.PROGRAM_ID, 500000.DOLLARS.CASH issuedBy defaultIssuer ownedBy ALICE) - output(Obligation.PROGRAM_ID, "Alice's $500,000 obligation to Bob") { halfAMillionDollars.OBLIGATION between Pair(ALICE, BOB) } - output(Obligation.PROGRAM_ID, "Bob's $500,000") { 500000.DOLLARS.CASH issuedBy defaultIssuer ownedBy BOB } - command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity / 2, inState.amount.token)) } - command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation::class.java) } + output(Obligation.PROGRAM_ID, "Alice's $500,000 obligation to Bob", halfAMillionDollars.OBLIGATION between Pair(ALICE, BOB)) + output(Obligation.PROGRAM_ID, "Bob's $500,000", 500000.DOLLARS.CASH issuedBy defaultIssuer ownedBy BOB) + command(ALICE_PUBKEY, Obligation.Commands.Settle(Amount(oneMillionDollars.quantity / 2, inState.amount.token))) + command(ALICE_PUBKEY, Cash.Commands.Move(Obligation::class.java)) attachment(attachment(cashContractBytes.inputStream())) this.verifies() } @@ -504,9 +499,9 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID, Cash.PROGRAM_ID) input(Obligation.PROGRAM_ID, defaultedObligation) // Alice's defaulted $1,000,000 obligation to Bob input(Cash.PROGRAM_ID, 1000000.DOLLARS.CASH issuedBy defaultIssuer ownedBy ALICE) - output(Obligation.PROGRAM_ID, "Bob's $1,000,000") { 1000000.DOLLARS.CASH issuedBy defaultIssuer ownedBy BOB } - command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity, inState.amount.token)) } - command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation::class.java) } + output(Obligation.PROGRAM_ID, "Bob's $1,000,000", 1000000.DOLLARS.CASH issuedBy defaultIssuer ownedBy BOB) + command(ALICE_PUBKEY, Obligation.Commands.Settle(Amount(oneMillionDollars.quantity, inState.amount.token))) + command(ALICE_PUBKEY, Cash.Commands.Move(Obligation::class.java)) this `fails with` "all inputs are in the normal state" } } @@ -518,9 +513,9 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID) input("Alice's $1,000,000 obligation to Bob") input("Alice's $1,000,000") - output(Obligation.PROGRAM_ID, "Bob's $1,000,000") { 1000000.DOLLARS.CASH issuedBy defaultIssuer ownedBy BOB } - command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity / 2, inState.amount.token)) } - command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation::class.java) } + output(Obligation.PROGRAM_ID, "Bob's $1,000,000", 1000000.DOLLARS.CASH issuedBy defaultIssuer ownedBy BOB) + command(ALICE_PUBKEY, Obligation.Commands.Settle(Amount(oneMillionDollars.quantity / 2, inState.amount.token))) + command(ALICE_PUBKEY, Cash.Commands.Move(Obligation::class.java)) attachment(attachment(cashContractBytes.inputStream())) this `fails with` "amount in settle command" } @@ -546,9 +541,9 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID) input("Alice's 1 FCOJ obligation to Bob") input("Alice's 1 FCOJ") - output(Obligation.PROGRAM_ID, "Bob's 1 FCOJ") { CommodityContract.State(oneUnitFcoj, BOB) } - command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneUnitFcoj.quantity, oneUnitFcojObligation.amount.token)) } - command(ALICE_PUBKEY) { CommodityContract.Commands.Move(Obligation::class.java) } + output(Obligation.PROGRAM_ID, "Bob's 1 FCOJ", CommodityContract.State(oneUnitFcoj, BOB)) + command(ALICE_PUBKEY, Obligation.Commands.Settle(Amount(oneUnitFcoj.quantity, oneUnitFcojObligation.amount.token))) + command(ALICE_PUBKEY, CommodityContract.Commands.Move(Obligation::class.java)) attachment(attachment(commodityContractBytes.inputStream())) verifies() } @@ -563,8 +558,8 @@ class ObligationTests { transaction("Settlement") { attachments(Obligation.PROGRAM_ID) input("Alice's $1,000,000 obligation to Bob") - output(Obligation.PROGRAM_ID, "Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)).copy(lifecycle = Lifecycle.DEFAULTED) } - command(BOB_PUBKEY) { Obligation.Commands.SetLifecycle(Lifecycle.DEFAULTED) } + output(Obligation.PROGRAM_ID, "Alice's defaulted $1,000,000 obligation to Bob", (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)).copy(lifecycle = Lifecycle.DEFAULTED)) + command(BOB_PUBKEY, Obligation.Commands.SetLifecycle(Lifecycle.DEFAULTED)) this `fails with` "there is a time-window from the authority" } } @@ -575,8 +570,8 @@ class ObligationTests { transaction { attachments(Obligation.PROGRAM_ID) input(Obligation.PROGRAM_ID, oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` futureTestTime) - output(Obligation.PROGRAM_ID, "Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` futureTestTime).copy(lifecycle = Lifecycle.DEFAULTED) } - command(BOB_PUBKEY) { Obligation.Commands.SetLifecycle(Lifecycle.DEFAULTED) } + output(Obligation.PROGRAM_ID, "Alice's defaulted $1,000,000 obligation to Bob", (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` futureTestTime).copy(lifecycle = Lifecycle.DEFAULTED)) + command(BOB_PUBKEY, Obligation.Commands.SetLifecycle(Lifecycle.DEFAULTED)) timeWindow(TEST_TX_TIME) this `fails with` "the due date has passed" } @@ -586,8 +581,8 @@ class ObligationTests { transaction { attachments(Obligation.PROGRAM_ID) input(Obligation.PROGRAM_ID, oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` pastTestTime) - output(Obligation.PROGRAM_ID, "Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` pastTestTime).copy(lifecycle = Lifecycle.DEFAULTED) } - command(BOB_PUBKEY) { Obligation.Commands.SetLifecycle(Lifecycle.DEFAULTED) } + output(Obligation.PROGRAM_ID, "Alice's defaulted $1,000,000 obligation to Bob", (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` pastTestTime).copy(lifecycle = Lifecycle.DEFAULTED)) + command(BOB_PUBKEY, Obligation.Commands.SetLifecycle(Lifecycle.DEFAULTED)) timeWindow(TEST_TX_TIME) this.verifies() } @@ -600,24 +595,24 @@ class ObligationTests { // Splitting value works. transaction { attachments(Obligation.PROGRAM_ID) - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + command(CHARLIE.owningKey, Obligation.Commands.Move()) tweak { - input(Obligation.PROGRAM_ID) { inState } - repeat(4) { output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 4) } } + input(Obligation.PROGRAM_ID, inState) + repeat(4) { output(Obligation.PROGRAM_ID, inState.copy(quantity = inState.quantity / 4)) } this.verifies() } // Merging 4 inputs into 2 outputs works. tweak { - repeat(4) { input(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 4) } } - output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) } - output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) } + repeat(4) { input(Obligation.PROGRAM_ID, inState.copy(quantity = inState.quantity / 4)) } + output(Obligation.PROGRAM_ID, inState.copy(quantity = inState.quantity / 2)) + output(Obligation.PROGRAM_ID, inState.copy(quantity = inState.quantity / 2)) this.verifies() } // Merging 2 inputs into 1 works. tweak { - input(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) } - input(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) } - output(Obligation.PROGRAM_ID) { inState } + input(Obligation.PROGRAM_ID, inState.copy(quantity = inState.quantity / 2)) + input(Obligation.PROGRAM_ID, inState.copy(quantity = inState.quantity / 2)) + output(Obligation.PROGRAM_ID, inState) this.verifies() } } @@ -627,18 +622,16 @@ class ObligationTests { fun zeroSizedValues() { transaction { attachments(Obligation.PROGRAM_ID) - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + command(CHARLIE.owningKey, Obligation.Commands.Move()) tweak { - input(Obligation.PROGRAM_ID) { inState } - input(Obligation.PROGRAM_ID) { inState.copy(quantity = 0L) } - + input(Obligation.PROGRAM_ID, inState) + input(Obligation.PROGRAM_ID, inState.copy(quantity = 0L)) this `fails with` "zero sized inputs" } tweak { - input(Obligation.PROGRAM_ID) { inState } - output(Obligation.PROGRAM_ID) { inState } - output(Obligation.PROGRAM_ID) { inState.copy(quantity = 0L) } - + input(Obligation.PROGRAM_ID, inState) + output(Obligation.PROGRAM_ID, inState) + output(Obligation.PROGRAM_ID, inState.copy(quantity = 0L)) this `fails with` "zero sized outputs" } } @@ -649,41 +642,39 @@ class ObligationTests { // Can't change issuer. transaction { attachments(Obligation.PROGRAM_ID) - input(Obligation.PROGRAM_ID) { inState } - output(Obligation.PROGRAM_ID) { outState `issued by` MINI_CORP } - command(MINI_CORP_PUBKEY) { Obligation.Commands.Move() } + input(Obligation.PROGRAM_ID, inState) + output(Obligation.PROGRAM_ID, outState `issued by` MINI_CORP) + command(MINI_CORP_PUBKEY, Obligation.Commands.Move()) this `fails with` "the amounts balance" } // Can't mix currencies. transaction { attachments(Obligation.PROGRAM_ID) - input(Obligation.PROGRAM_ID) { inState } - output(Obligation.PROGRAM_ID) { outState.copy(quantity = 80000, template = megaCorpDollarSettlement) } - output(Obligation.PROGRAM_ID) { outState.copy(quantity = 20000, template = megaCorpPoundSettlement) } - command(MINI_CORP_PUBKEY) { Obligation.Commands.Move() } + input(Obligation.PROGRAM_ID, inState) + output(Obligation.PROGRAM_ID, outState.copy(quantity = 80000, template = megaCorpDollarSettlement)) + output(Obligation.PROGRAM_ID, outState.copy(quantity = 20000, template = megaCorpPoundSettlement)) + command(MINI_CORP_PUBKEY, Obligation.Commands.Move()) this `fails with` "the amounts balance" } transaction { attachments(Obligation.PROGRAM_ID) - input(Obligation.PROGRAM_ID) { inState } - input(Obligation.PROGRAM_ID) { + input(Obligation.PROGRAM_ID, inState) + input(Obligation.PROGRAM_ID, inState.copy( quantity = 15000, template = megaCorpPoundSettlement, - beneficiary = AnonymousParty(BOB_PUBKEY) - ) - } - output(Obligation.PROGRAM_ID) { outState.copy(quantity = 115000) } - command(MINI_CORP_PUBKEY) { Obligation.Commands.Move() } + beneficiary = AnonymousParty(BOB_PUBKEY))) + output(Obligation.PROGRAM_ID, outState.copy(quantity = 115000)) + command(MINI_CORP_PUBKEY, Obligation.Commands.Move()) this `fails with` "the amounts balance" } // Can't have superfluous input states from different issuers. transaction { attachments(Obligation.PROGRAM_ID) - input(Obligation.PROGRAM_ID) { inState } - input(Obligation.PROGRAM_ID) { inState `issued by` MINI_CORP } - output(Obligation.PROGRAM_ID) { outState } - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + input(Obligation.PROGRAM_ID, inState) + input(Obligation.PROGRAM_ID, inState `issued by` MINI_CORP) + output(Obligation.PROGRAM_ID, outState) + command(CHARLIE.owningKey, Obligation.Commands.Move()) this `fails with` "the amounts balance" } } @@ -693,21 +684,20 @@ class ObligationTests { // Single input/output straightforward case. transaction { attachments(Obligation.PROGRAM_ID) - input(Obligation.PROGRAM_ID) { inState } - output(Obligation.PROGRAM_ID) { outState.copy(quantity = inState.quantity - 200.DOLLARS.quantity) } - + input(Obligation.PROGRAM_ID, inState) + output(Obligation.PROGRAM_ID, outState.copy(quantity = inState.quantity - 200.DOLLARS.quantity)) tweak { - command(CHARLIE.owningKey) { Obligation.Commands.Exit(Amount(100.DOLLARS.quantity, inState.amount.token)) } - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + command(CHARLIE.owningKey, Obligation.Commands.Exit(Amount(100.DOLLARS.quantity, inState.amount.token))) + command(CHARLIE.owningKey, Obligation.Commands.Move()) this `fails with` "the amounts balance" } tweak { - command(CHARLIE.owningKey) { Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.amount.token)) } + command(CHARLIE.owningKey, Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.amount.token))) this `fails with` "required net.corda.finance.contracts.asset.Obligation.Commands.Move command" tweak { - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + command(CHARLIE.owningKey, Obligation.Commands.Move()) this.verifies() } } @@ -720,21 +710,15 @@ class ObligationTests { // Multi-product case. transaction { attachments(Obligation.PROGRAM_ID) - - input(Obligation.PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedPounds)) } - input(Obligation.PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedDollars)) } - - output(Obligation.PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedPounds), quantity = inState.quantity - 200.POUNDS.quantity) } - output(Obligation.PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedDollars), quantity = inState.quantity - 200.DOLLARS.quantity) } - - command(CHARLIE.owningKey) { Obligation.Commands.Move() } - + input(Obligation.PROGRAM_ID, inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedPounds))) + input(Obligation.PROGRAM_ID, inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedDollars))) + output(Obligation.PROGRAM_ID, inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedPounds), quantity = inState.quantity - 200.POUNDS.quantity)) + output(Obligation.PROGRAM_ID, inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedDollars), quantity = inState.quantity - 200.DOLLARS.quantity)) + command(CHARLIE.owningKey, Obligation.Commands.Move()) this `fails with` "the amounts balance" - - command(CHARLIE.owningKey) { Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.amount.token.copy(product = megaCorpDollarSettlement))) } + command(CHARLIE.owningKey, Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.amount.token.copy(product = megaCorpDollarSettlement)))) this `fails with` "the amounts balance" - - command(CHARLIE.owningKey) { Obligation.Commands.Exit(Amount(200.POUNDS.quantity, inState.amount.token.copy(product = megaCorpPoundSettlement))) } + command(CHARLIE.owningKey, Obligation.Commands.Exit(Amount(200.POUNDS.quantity, inState.amount.token.copy(product = megaCorpPoundSettlement)))) this.verifies() } } @@ -745,27 +729,26 @@ class ObligationTests { attachments(Obligation.PROGRAM_ID) // Gather 2000 dollars from two different issuers. - input(Obligation.PROGRAM_ID) { inState } - input(Obligation.PROGRAM_ID) { inState `issued by` MINI_CORP } - + input(Obligation.PROGRAM_ID, inState) + input(Obligation.PROGRAM_ID, inState `issued by` MINI_CORP) // Can't merge them together. tweak { - output(Obligation.PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY), quantity = 200000L) } - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + output(Obligation.PROGRAM_ID, inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY), quantity = 200000L)) + command(CHARLIE.owningKey, Obligation.Commands.Move()) this `fails with` "the amounts balance" } // Missing MiniCorp deposit tweak { - output(Obligation.PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) } - output(Obligation.PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) } - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + output(Obligation.PROGRAM_ID, inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY))) + output(Obligation.PROGRAM_ID, inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY))) + command(CHARLIE.owningKey, Obligation.Commands.Move()) this `fails with` "the amounts balance" } // This works. - output(Obligation.PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) } - output(Obligation.PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) `issued by` MINI_CORP } - command(CHARLIE.owningKey) { Obligation.Commands.Move() } + output(Obligation.PROGRAM_ID, inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY))) + output(Obligation.PROGRAM_ID, inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) `issued by` MINI_CORP) + command(CHARLIE.owningKey, Obligation.Commands.Move()) this.verifies() } } @@ -776,12 +759,11 @@ class ObligationTests { transaction { attachments(Obligation.PROGRAM_ID) val pounds = Obligation.State(Lifecycle.NORMAL, MINI_CORP, megaCorpPoundSettlement, 658.POUNDS.quantity, AnonymousParty(BOB_PUBKEY)) - input(Obligation.PROGRAM_ID) { inState `owned by` CHARLIE } - input(Obligation.PROGRAM_ID) { pounds } - output(Obligation.PROGRAM_ID) { inState `owned by` AnonymousParty(BOB_PUBKEY) } - output(Obligation.PROGRAM_ID) { pounds `owned by` CHARLIE } - command(CHARLIE.owningKey, BOB_PUBKEY) { Obligation.Commands.Move() } - + input(Obligation.PROGRAM_ID, inState `owned by` CHARLIE) + input(Obligation.PROGRAM_ID, pounds) + output(Obligation.PROGRAM_ID, inState `owned by` AnonymousParty(BOB_PUBKEY)) + output(Obligation.PROGRAM_ID, pounds `owned by` CHARLIE) + command(listOf(CHARLIE.owningKey, BOB_PUBKEY), Obligation.Commands.Move()) this.verifies() } } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisTcpTransport.kt b/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisTcpTransport.kt index 947560c257..ab1720934a 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisTcpTransport.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisTcpTransport.kt @@ -3,7 +3,8 @@ package net.corda.nodeapi import net.corda.core.identity.CordaX500Name import net.corda.core.serialization.internal.nodeSerializationEnv import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration +import net.corda.nodeapi.internal.requireOnDefaultFileSystem import org.apache.activemq.artemis.api.core.TransportConfiguration import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisUtils.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/ArtemisUtils.kt similarity index 92% rename from node-api/src/main/kotlin/net/corda/nodeapi/ArtemisUtils.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/ArtemisUtils.kt index 644fdb363a..3f1e887fa8 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisUtils.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/ArtemisUtils.kt @@ -1,6 +1,6 @@ @file:JvmName("ArtemisUtils") -package net.corda.nodeapi +package net.corda.nodeapi.internal import java.nio.file.FileSystems import java.nio.file.Path diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/config/ConfigUtilities.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt similarity index 99% rename from node-api/src/main/kotlin/net/corda/nodeapi/config/ConfigUtilities.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt index 19987de81c..33a5e237ff 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/config/ConfigUtilities.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt @@ -1,6 +1,6 @@ @file:JvmName("ConfigUtilities") -package net.corda.nodeapi.config +package net.corda.nodeapi.internal.config import com.typesafe.config.Config import com.typesafe.config.ConfigFactory @@ -200,4 +200,4 @@ private fun Iterable<*>.toConfigIterable(field: Field): Iterable { } } -private val logger = LoggerFactory.getLogger("net.corda.nodeapi.config") +private val logger = LoggerFactory.getLogger("net.corda.nodeapi.internal.config") diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/config/SSLConfiguration.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/SSLConfiguration.kt similarity index 94% rename from node-api/src/main/kotlin/net/corda/nodeapi/config/SSLConfiguration.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/config/SSLConfiguration.kt index a357bf7093..dbe587373c 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/config/SSLConfiguration.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/SSLConfiguration.kt @@ -1,4 +1,4 @@ -package net.corda.nodeapi.config +package net.corda.nodeapi.internal.config import net.corda.core.internal.div import java.nio.file.Path diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/User.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/User.kt similarity index 77% rename from node-api/src/main/kotlin/net/corda/nodeapi/User.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/config/User.kt index aa86e64414..13ca193f4b 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/User.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/User.kt @@ -1,7 +1,4 @@ -package net.corda.nodeapi - -import net.corda.nodeapi.config.OldConfig -import net.corda.nodeapi.config.toConfig +package net.corda.nodeapi.internal.config data class User( @OldConfig("user") diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/config/ConfigParsingTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/config/ConfigParsingTest.kt similarity index 99% rename from node-api/src/test/kotlin/net/corda/nodeapi/config/ConfigParsingTest.kt rename to node-api/src/test/kotlin/net/corda/nodeapi/internal/config/ConfigParsingTest.kt index 5efdeaf439..a6fa2ca169 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/config/ConfigParsingTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/config/ConfigParsingTest.kt @@ -1,4 +1,4 @@ -package net.corda.nodeapi.config +package net.corda.nodeapi.internal.config import com.typesafe.config.Config import com.typesafe.config.ConfigFactory.empty diff --git a/node/src/integration-test/kotlin/net/corda/node/BootTests.kt b/node/src/integration-test/kotlin/net/corda/node/BootTests.kt index a7561d331f..5efb235eb2 100644 --- a/node/src/integration-test/kotlin/net/corda/node/BootTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/BootTests.kt @@ -8,7 +8,7 @@ import net.corda.core.messaging.startFlow import net.corda.core.utilities.getOrThrow import net.corda.node.internal.NodeStartup import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.ALICE import net.corda.testing.common.internal.ProjectStructure.projectRootDir import net.corda.testing.driver.driver diff --git a/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt b/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt index 8515b9b4ec..c6464056e1 100644 --- a/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt @@ -8,7 +8,7 @@ import net.corda.core.messaging.startFlow import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.unwrap import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.ALICE import net.corda.testing.BOB import net.corda.testing.chooseIdentity diff --git a/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt b/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt index 13ca05b46c..15abb2b06d 100644 --- a/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt @@ -13,7 +13,7 @@ import net.corda.finance.DOLLARS import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.DUMMY_NOTARY import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver diff --git a/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt b/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt index 96c701f761..67b1996596 100644 --- a/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt @@ -9,7 +9,7 @@ import net.corda.core.identity.Party import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.unwrap -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.ALICE import net.corda.testing.driver.driver import org.bouncycastle.util.io.Streams diff --git a/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt index 15a8914e35..a1b9a409ac 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt @@ -13,7 +13,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver diff --git a/node/src/integration-test/kotlin/net/corda/node/services/network/NodeInfoWatcherTest.kt b/node/src/integration-test/kotlin/net/corda/node/services/network/NodeInfoWatcherTest.kt index 5d6731c625..3593240a31 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/network/NodeInfoWatcherTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/network/NodeInfoWatcherTest.kt @@ -49,7 +49,7 @@ class NodeInfoWatcherTest { fun start() { val identityService = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) keyManagementService = MockKeyManagementService(identityService, ALICE_KEY) - nodeInfoWatcher = NodeInfoWatcher(tempFolder.root.toPath(), scheduler = scheduler) + nodeInfoWatcher = NodeInfoWatcher(tempFolder.root.toPath(), scheduler) nodeInfoPath = tempFolder.root.toPath() / CordformNode.NODE_INFO_DIRECTORY } diff --git a/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt b/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt index 9f0212d2cb..342485889e 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt @@ -4,15 +4,15 @@ import co.paralleluniverse.fibers.Suspendable import net.corda.core.crypto.SecureHash import net.corda.core.flows.* import net.corda.core.internal.InputStreamAndHash +import net.corda.core.internal.concurrent.transpose import net.corda.core.messaging.startFlow import net.corda.core.transactions.TransactionBuilder -import net.corda.testing.BOB -import net.corda.testing.DUMMY_NOTARY -import net.corda.testing.aliceAndBob +import net.corda.core.utilities.getOrThrow +import net.corda.nodeapi.internal.config.User +import net.corda.testing.* import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyState import net.corda.testing.driver.driver -import net.corda.testing.dummyCommand import org.junit.Test import kotlin.test.assertEquals @@ -65,15 +65,16 @@ class LargeTransactionsTest { val bigFile3 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024 * 3, 2) val bigFile4 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024 * 3, 3) driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.testing.contracts")) { - val (alice, _) = aliceAndBob() - alice.useRPC { - val hash1 = it.uploadAttachment(bigFile1.inputStream) - val hash2 = it.uploadAttachment(bigFile2.inputStream) - val hash3 = it.uploadAttachment(bigFile3.inputStream) - val hash4 = it.uploadAttachment(bigFile4.inputStream) + val rpcUser = User("admin", "admin", setOf("ALL")) + val (alice, _) = listOf(ALICE_NAME, BOB_NAME).map { startNode(providedName = it, rpcUsers = listOf(rpcUser)) }.transpose().getOrThrow() + alice.rpcClientToNode().use(rpcUser.username, rpcUser.password) { + val hash1 = it.proxy.uploadAttachment(bigFile1.inputStream) + val hash2 = it.proxy.uploadAttachment(bigFile2.inputStream) + val hash3 = it.proxy.uploadAttachment(bigFile3.inputStream) + val hash4 = it.proxy.uploadAttachment(bigFile4.inputStream) assertEquals(hash1, bigFile1.sha256) // Should not throw any exceptions. - it.startFlow(::SendLargeTransactionFlow, hash1, hash2, hash3, hash4).returnValue.get() + it.proxy.startFlow(::SendLargeTransactionFlow, hash1, hash2, hash3, hash4).returnValue.getOrThrow() } } } diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt index ddee610773..fc2c15c746 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt @@ -5,7 +5,7 @@ import net.corda.core.internal.* import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEER_USER import net.corda.nodeapi.RPCApi -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.nodeapi.internal.crypto.* import net.corda.testing.MEGA_CORP import net.corda.testing.MINI_CORP diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsRPCTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsRPCTest.kt index cbb75daedd..d4cd7ca4e4 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsRPCTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsRPCTest.kt @@ -1,6 +1,6 @@ package net.corda.services.messaging -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.messaging.SimpleMQClient import org.junit.Test diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt index ecaa0032a0..45ffb4289a 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt @@ -22,8 +22,8 @@ import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NOTIFICATI import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.P2P_QUEUE import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEERS_PREFIX import net.corda.nodeapi.RPCApi -import net.corda.nodeapi.User -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.testing.* import net.corda.testing.internal.NodeBasedTest import net.corda.testing.messaging.SimpleMQClient diff --git a/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt b/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt index 5a2b531cef..ee94671bca 100644 --- a/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt @@ -19,7 +19,7 @@ import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.getOrThrow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.chooseIdentity import net.corda.testing.driver.driver import org.junit.Assume.assumeFalse diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index c52c7ff1f1..89e394ec16 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -66,6 +66,7 @@ import org.apache.activemq.artemis.utils.ReusableLatch import org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry import org.slf4j.Logger import rx.Observable +import rx.Scheduler import java.io.IOException import java.io.NotSerializableException import java.lang.reflect.InvocationTargetException @@ -232,7 +233,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, } val networkMapUpdater = NetworkMapUpdater(services.networkMapCache, - NodeInfoWatcher(configuration.baseDirectory, Duration.ofMillis(configuration.additionalNodeInfoPollingFrequencyMsec)), + NodeInfoWatcher(configuration.baseDirectory, getRxIoScheduler(), Duration.ofMillis(configuration.additionalNodeInfoPollingFrequencyMsec)), networkMapClient) runOnStop += networkMapUpdater::close @@ -258,6 +259,12 @@ abstract class AbstractNode(val configuration: NodeConfiguration, } } + /** + * Should be [rx.schedulers.Schedulers.io] for production, + * or [rx.internal.schedulers.CachedThreadScheduler] (with shutdown registered with [runOnStop]) for shared-JVM testing. + */ + protected abstract fun getRxIoScheduler(): Scheduler + open fun startShell(rpcOps: CordaRPCOps) { InteractiveShell.startShell(configuration, rpcOps, userService, _services.identityService, _services.database) } diff --git a/node/src/main/kotlin/net/corda/node/internal/Node.kt b/node/src/main/kotlin/net/corda/node/internal/Node.kt index 4be73777ca..4e209e36f9 100644 --- a/node/src/main/kotlin/net/corda/node/internal/Node.kt +++ b/node/src/main/kotlin/net/corda/node/internal/Node.kt @@ -33,6 +33,7 @@ import net.corda.nodeapi.internal.serialization.* import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme import org.slf4j.Logger import org.slf4j.LoggerFactory +import rx.schedulers.Schedulers import java.time.Clock import java.util.concurrent.atomic.AtomicInteger import javax.management.ObjectName @@ -46,7 +47,7 @@ import kotlin.system.exitProcess */ open class Node(configuration: NodeConfiguration, versionInfo: VersionInfo, - val initialiseSerialization: Boolean = true, + private val initialiseSerialization: Boolean = true, cordappLoader: CordappLoader = makeCordappLoader(configuration) ) : AbstractNode(configuration, createClock(configuration), versionInfo, cordappLoader) { companion object { @@ -299,6 +300,7 @@ open class Node(configuration: NodeConfiguration, return started } + override fun getRxIoScheduler() = Schedulers.io()!! private fun initialiseSerialization() { val classloader = cordappLoader.appClassLoader nodeSerializationEnv = SerializationEnvironmentImpl( diff --git a/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt b/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt index e852e764b1..3a7bbdcb9f 100644 --- a/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt +++ b/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt @@ -1,7 +1,7 @@ package net.corda.node.services import net.corda.core.context.AuthServiceId -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User /** * Service for retrieving [User] objects representing RPC users who are authorised to use the RPC system. A [User] diff --git a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt index 5ec42af68a..1da892b994 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt @@ -8,7 +8,7 @@ import net.corda.core.crypto.Crypto import net.corda.core.crypto.SignatureScheme import net.corda.core.identity.CordaX500Name import net.corda.core.internal.* -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.nodeapi.internal.crypto.* import org.bouncycastle.asn1.x509.GeneralName import org.bouncycastle.asn1.x509.GeneralSubtree diff --git a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt index e0290bc168..dd4bddbc87 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt @@ -6,9 +6,9 @@ import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.seconds import net.corda.node.services.messaging.CertificateChainCheckPolicy import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.nodeapi.User -import net.corda.nodeapi.config.NodeSSLConfiguration -import net.corda.nodeapi.config.parseAs +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.NodeSSLConfiguration +import net.corda.nodeapi.internal.config.parseAs import java.net.URL import java.nio.file.Path import java.util.* diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingClient.kt b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingClient.kt index f377087b90..fd36dc9ba7 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingClient.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingClient.kt @@ -6,7 +6,7 @@ import net.corda.core.utilities.loggerFor import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER import net.corda.nodeapi.ArtemisTcpTransport import net.corda.nodeapi.ConnectionDirection -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import org.apache.activemq.artemis.api.core.client.* import org.apache.activemq.artemis.api.core.client.ActiveMQClient.DEFAULT_ACK_BATCH_SIZE diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt index 5fa25f3d86..2b7e496b32 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt @@ -33,6 +33,7 @@ import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEERS_PREF import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEER_USER import net.corda.nodeapi.internal.ArtemisMessagingComponent.ArtemisPeerAddress import net.corda.nodeapi.internal.ArtemisMessagingComponent.NodeAddress +import net.corda.nodeapi.internal.requireOnDefaultFileSystem import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl import org.apache.activemq.artemis.core.config.BridgeConfiguration @@ -43,7 +44,9 @@ import org.apache.activemq.artemis.core.config.impl.SecurityConfiguration import org.apache.activemq.artemis.core.remoting.impl.netty.* import org.apache.activemq.artemis.core.security.Role import org.apache.activemq.artemis.core.server.ActiveMQServer +import org.apache.activemq.artemis.core.server.SecuritySettingPlugin import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl +import org.apache.activemq.artemis.core.settings.HierarchicalRepository import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy import org.apache.activemq.artemis.core.settings.impl.AddressSettings import org.apache.activemq.artemis.spi.core.remoting.* @@ -139,8 +142,8 @@ class ArtemisMessagingServer(private val config: NodeConfiguration, // Artemis IO errors @Throws(IOException::class, KeyStoreException::class) private fun configureAndStartServer() { - val artemisConfig = createArtemisConfig() - val securityManager = createArtemisSecurityManager() + val (artemisConfig, securityPlugin) = createArtemisConfig() + val securityManager = createArtemisSecurityManager(securityPlugin) activeMQServer = ActiveMQServerImpl(artemisConfig, securityManager).apply { // Throw any exceptions which are detected during startup registerActivationFailureListener { exception -> throw exception } @@ -156,7 +159,7 @@ class ArtemisMessagingServer(private val config: NodeConfiguration, } } - private fun createArtemisConfig(): Configuration = ConfigurationImpl().apply { + private fun createArtemisConfig() = ConfigurationImpl().apply { val artemisDir = config.baseDirectory / "artemis" bindingsDirectory = (artemisDir / "bindings").toString() journalDirectory = (artemisDir / "journal").toString() @@ -208,8 +211,7 @@ class ArtemisMessagingServer(private val config: NodeConfiguration, addressFullMessagePolicy = AddressFullMessagePolicy.FAIL } ) - configureAddressSecurity() - } + }.configureAddressSecurity() private fun queueConfig(name: String, address: String = name, filter: String? = null, durable: Boolean): CoreQueueConfiguration { return CoreQueueConfiguration().apply { @@ -227,7 +229,7 @@ class ArtemisMessagingServer(private val config: NodeConfiguration, * 3. RPC users. These are only given sufficient access to perform RPC with us. * 4. Verifiers. These are given read access to the verification request queue and write access to the response queue. */ - private fun ConfigurationImpl.configureAddressSecurity() { + private fun ConfigurationImpl.configureAddressSecurity() : Pair { val nodeInternalRole = Role(NODE_ROLE, true, true, true, true, true, true, true, true) securityRoles["$INTERNAL_PREFIX#"] = setOf(nodeInternalRole) // Do not add any other roles here as it's only for the node securityRoles[P2P_QUEUE] = setOf(nodeInternalRole, restrictedRole(PEER_ROLE, send = true)) @@ -236,13 +238,22 @@ class ArtemisMessagingServer(private val config: NodeConfiguration, securityRoles["${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.$NODE_USER.#"] = setOf(nodeInternalRole) // Each RPC user must have its own role and its own queue. This prevents users accessing each other's queues // and stealing RPC responses. - for ((username) in userService.users) { - securityRoles["${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.$username.#"] = setOf( - nodeInternalRole, - restrictedRole("${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.$username", consume = true, createNonDurableQueue = true, deleteNonDurableQueue = true)) + val rolesAdderOnLogin = RolesAdderOnLogin { username -> + Pair( + "${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.$username.#", + setOf( + nodeInternalRole, + restrictedRole( + "${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.$username", + consume = true, + createNonDurableQueue = true, + deleteNonDurableQueue = true))) } + securitySettingPlugins.add(rolesAdderOnLogin) securityRoles[VerifierApi.VERIFICATION_REQUESTS_QUEUE_NAME] = setOf(nodeInternalRole, restrictedRole(VERIFIER_ROLE, consume = true)) securityRoles["${VerifierApi.VERIFICATION_RESPONSES_QUEUE_NAME_PREFIX}.#"] = setOf(nodeInternalRole, restrictedRole(VERIFIER_ROLE, send = true)) + val onLoginListener = { username: String -> rolesAdderOnLogin.onLogin(username) } + return Pair(this, onLoginListener) } private fun restrictedRole(name: String, send: Boolean = false, consume: Boolean = false, createDurableQueue: Boolean = false, @@ -253,7 +264,7 @@ class ArtemisMessagingServer(private val config: NodeConfiguration, } @Throws(IOException::class, KeyStoreException::class) - private fun createArtemisSecurityManager(): ActiveMQJAASSecurityManager { + private fun createArtemisSecurityManager(loginListener: LoginListener): ActiveMQJAASSecurityManager { val keyStore = loadKeyStore(config.sslKeystore, config.keyStorePassword) val trustStore = loadKeyStore(config.trustStoreFile, config.trustStorePassword) @@ -270,6 +281,7 @@ class ArtemisMessagingServer(private val config: NodeConfiguration, // Override to make it work with our login module override fun getAppConfigurationEntry(name: String): Array { val options = mapOf( + LoginListener::javaClass.name to loginListener, RPCUserService::class.java.name to userService, NodeLoginModule.CERT_CHAIN_CHECKS_OPTION_NAME to certChecks) return arrayOf(AppConfigurationEntry(name, REQUIRED, options)) @@ -546,6 +558,7 @@ class NodeLoginModule : LoginModule { private lateinit var subject: Subject private lateinit var callbackHandler: CallbackHandler private lateinit var userService: RPCUserService + private lateinit var loginListener: LoginListener private lateinit var peerCertCheck: CertificateChainCheckPolicy.Check private lateinit var nodeCertCheck: CertificateChainCheckPolicy.Check private lateinit var verifierCertCheck: CertificateChainCheckPolicy.Check @@ -555,6 +568,7 @@ class NodeLoginModule : LoginModule { this.subject = subject this.callbackHandler = callbackHandler userService = options[RPCUserService::class.java.name] as RPCUserService + loginListener = options[LoginListener::javaClass.name] as LoginListener val certChainChecks: Map = uncheckedCast(options[CERT_CHAIN_CHECKS_OPTION_NAME]) peerCertCheck = certChainChecks[PEER_ROLE]!! nodeCertCheck = certChainChecks[NODE_ROLE]!! @@ -622,6 +636,7 @@ class NodeLoginModule : LoginModule { // TODO Retrieve client IP address to include in exception message throw FailedLoginException("Password for user $username does not match") } + loginListener(username) principals += RolePrincipal(RPC_ROLE) // This enables the RPC client to send requests principals += RolePrincipal("${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.$username") // This enables the RPC client to receive responses return username @@ -676,3 +691,40 @@ class NodeLoginModule : LoginModule { loginSucceeded = false } } + +typealias LoginListener = (String) -> Unit +typealias RolesRepository = HierarchicalRepository> + +/** + * Helper class to dynamically assign security roles to RPC users + * on their authentication. This object is plugged into the server + * as [SecuritySettingPlugin]. It responds to authentication events + * from [NodeLoginModule] by adding the address -> roles association + * generated by the given [source], unless already done before. + */ +private class RolesAdderOnLogin(val source: (String) -> Pair>) + : SecuritySettingPlugin { + + // Artemis internal container storing roles association + private lateinit var repository: RolesRepository + + fun onLogin(username: String) { + val (address, roles) = source(username) + val entry = repository.getMatch(address) + if (entry == null || entry.isEmpty()) { + repository.addMatch(address, roles.toMutableSet()) + } + } + + // Initializer called by the Artemis framework + override fun setSecurityRepository(repository: RolesRepository) { + this.repository = repository + } + + // Part of SecuritySettingPlugin interface which is no-op in this case + override fun stop() = this + + override fun init(options: MutableMap?) = this + + override fun getSecurityRoles() = null +} diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt b/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt index aa9fea626c..0d7bd5a314 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt @@ -5,7 +5,7 @@ import net.corda.core.messaging.RPCOps import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.RPCUserService -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.crypto.getX509Certificate diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/RPCServer.kt b/node/src/main/kotlin/net/corda/node/services/messaging/RPCServer.kt index 54526a76be..2fe7a4b13d 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/RPCServer.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/RPCServer.kt @@ -30,6 +30,7 @@ import net.corda.node.services.RPCUserService import net.corda.node.services.logging.pushToLoggingContext import net.corda.nodeapi.* import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER +import net.corda.nodeapi.internal.config.User import org.apache.activemq.artemis.api.core.Message import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.client.ActiveMQClient.DEFAULT_ACK_BATCH_SIZE diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/VerifierMessagingClient.kt b/node/src/main/kotlin/net/corda/node/services/messaging/VerifierMessagingClient.kt index d916e63cc5..8216b6846b 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/VerifierMessagingClient.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/VerifierMessagingClient.kt @@ -11,7 +11,7 @@ import net.corda.node.utilities.* import net.corda.nodeapi.VerifierApi import net.corda.nodeapi.VerifierApi.VERIFICATION_REQUESTS_QUEUE_NAME import net.corda.nodeapi.VerifierApi.VERIFICATION_RESPONSES_QUEUE_NAME_PREFIX -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import org.apache.activemq.artemis.api.core.RoutingType import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.client.* diff --git a/node/src/main/kotlin/net/corda/node/services/network/NodeInfoWatcher.kt b/node/src/main/kotlin/net/corda/node/services/network/NodeInfoWatcher.kt index c921044091..771604ba6b 100644 --- a/node/src/main/kotlin/net/corda/node/services/network/NodeInfoWatcher.kt +++ b/node/src/main/kotlin/net/corda/node/services/network/NodeInfoWatcher.kt @@ -12,7 +12,6 @@ import net.corda.core.utilities.seconds import net.corda.nodeapi.internal.NodeInfoFilesCopier import rx.Observable import rx.Scheduler -import rx.schedulers.Schedulers import java.io.IOException import java.nio.file.Path import java.time.Duration @@ -31,9 +30,8 @@ import kotlin.streams.toList */ // TODO: Use NIO watch service instead? class NodeInfoWatcher(private val nodePath: Path, - private val pollInterval: Duration = 5.seconds, - private val scheduler: Scheduler = Schedulers.io()) { - + private val scheduler: Scheduler, + private val pollInterval: Duration = 5.seconds) { private val nodeInfoDirectory = nodePath / CordformNode.NODE_INFO_DIRECTORY private val processedNodeInfoFiles = mutableSetOf() private val _processedNodeInfoHashes = mutableSetOf() diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt b/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt index 53e7c19fbe..3b7b78a374 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt @@ -29,8 +29,8 @@ import net.corda.core.serialization.serialize import net.corda.core.utilities.contextLogger import net.corda.node.services.config.RaftConfig import net.corda.node.utilities.AppendOnlyPersistentMap -import net.corda.nodeapi.config.NodeSSLConfiguration -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.NodeSSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX import java.nio.file.Path diff --git a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt index 9196c1d293..145a7b933b 100644 --- a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt @@ -653,13 +653,13 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) { // wants to sell to Bob. val eb1 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) { // Issued money to itself. - output(Cash.PROGRAM_ID, "elbonian money 1", notary = notary) { 800.DOLLARS.CASH issuedBy issuer ownedBy interimOwner } - output(Cash.PROGRAM_ID, "elbonian money 2", notary = notary) { 1000.DOLLARS.CASH issuedBy issuer ownedBy interimOwner } + output(Cash.PROGRAM_ID, "elbonian money 1", notary = notary, contractState = 800.DOLLARS.CASH issuedBy issuer ownedBy interimOwner) + output(Cash.PROGRAM_ID, "elbonian money 2", notary = notary, contractState = 1000.DOLLARS.CASH issuedBy issuer ownedBy interimOwner) if (!withError) { - command(issuer.party.owningKey) { Cash.Commands.Issue() } + command(issuer.party.owningKey, Cash.Commands.Issue()) } else { // Put a broken command on so at least a signature is created - command(issuer.party.owningKey) { Cash.Commands.Move() } + command(issuer.party.owningKey, Cash.Commands.Move()) } timeWindow(TEST_TX_TIME) if (withError) { @@ -672,16 +672,16 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) { // Bob gets some cash onto the ledger from BoE val bc1 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) { input("elbonian money 1") - output(Cash.PROGRAM_ID, "bob cash 1", notary = notary) { 800.DOLLARS.CASH issuedBy issuer ownedBy owner } - command(interimOwner.owningKey) { Cash.Commands.Move() } + output(Cash.PROGRAM_ID, "bob cash 1", notary = notary, contractState = 800.DOLLARS.CASH issuedBy issuer ownedBy owner) + command(interimOwner.owningKey, Cash.Commands.Move()) this.verifies() } val bc2 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) { input("elbonian money 2") - output(Cash.PROGRAM_ID, "bob cash 2", notary = notary) { 300.DOLLARS.CASH issuedBy issuer ownedBy owner } - output(Cash.PROGRAM_ID, notary = notary) { 700.DOLLARS.CASH issuedBy issuer ownedBy interimOwner } // Change output. - command(interimOwner.owningKey) { Cash.Commands.Move() } + output(Cash.PROGRAM_ID, "bob cash 2", notary = notary, contractState = 300.DOLLARS.CASH issuedBy issuer ownedBy owner) + output(Cash.PROGRAM_ID, notary = notary, contractState = 700.DOLLARS.CASH issuedBy issuer ownedBy interimOwner) // Change output. + command(interimOwner.owningKey, Cash.Commands.Move()) this.verifies() } @@ -697,10 +697,9 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) { attachmentID: SecureHash?, notary: Party): Pair, List> { val ap = transaction(transactionBuilder = TransactionBuilder(notary = notary)) { - output(CommercialPaper.CP_PROGRAM_ID, "alice's paper", notary = notary) { - CommercialPaper.State(issuer, owner, amount, TEST_TX_TIME + 7.days) - } - command(issuer.party.owningKey) { CommercialPaper.Commands.Issue() } + output(CommercialPaper.CP_PROGRAM_ID, "alice's paper", notary = notary, + contractState = CommercialPaper.State(issuer, owner, amount, TEST_TX_TIME + 7.days)) + command(issuer.party.owningKey, CommercialPaper.Commands.Issue()) if (!withError) timeWindow(time = TEST_TX_TIME) if (attachmentID != null) diff --git a/node/src/test/kotlin/net/corda/node/services/RPCUserServiceTest.kt b/node/src/test/kotlin/net/corda/node/services/RPCUserServiceTest.kt index 88bdae5579..0f54c85d1c 100644 --- a/node/src/test/kotlin/net/corda/node/services/RPCUserServiceTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/RPCUserServiceTest.kt @@ -1,7 +1,7 @@ package net.corda.node.services -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.Test diff --git a/node/src/test/kotlin/net/corda/node/services/config/ConfigOperatorTests.kt b/node/src/test/kotlin/net/corda/node/services/config/ConfigOperatorTests.kt index 92f7340b16..8178b88c48 100644 --- a/node/src/test/kotlin/net/corda/node/services/config/ConfigOperatorTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/config/ConfigOperatorTests.kt @@ -1,7 +1,7 @@ package net.corda.node.services.config import com.typesafe.config.ConfigFactory -import net.corda.nodeapi.config.toProperties +import net.corda.nodeapi.internal.config.toProperties import org.junit.Test import kotlin.test.assertEquals diff --git a/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt b/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt index 5796609f1c..72b61e053b 100644 --- a/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt @@ -12,9 +12,7 @@ import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.node.NodeInfo import net.corda.core.node.ServiceHub -import net.corda.core.node.StatesToRecord import net.corda.core.serialization.SingletonSerializeAsToken -import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.days import net.corda.node.internal.FlowStarterImpl @@ -44,7 +42,6 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import java.nio.file.Paths -import java.security.PublicKey import java.time.Clock import java.time.Instant import java.util.concurrent.CountDownLatch @@ -105,13 +102,9 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() { doReturn(MonitoringService(MetricRegistry())).whenever(it).monitoringService doReturn(validatedTransactions).whenever(it).validatedTransactions doReturn(NetworkMapCacheImpl(MockNetworkMapCache(database), identityService)).whenever(it).networkMapCache - doCallRealMethod().whenever(it).signInitialTransaction(any(), any()) doReturn(myInfo).whenever(it).myInfo doReturn(kms).whenever(it).keyManagementService doReturn(CordappProviderImpl(CordappLoader.createWithTestPackages(listOf("net.corda.testing.contracts")), MockAttachmentStorage())).whenever(it).cordappProvider - doCallRealMethod().whenever(it).recordTransactions(any(), any()) - doCallRealMethod().whenever(it).recordTransactions(any>()) - doCallRealMethod().whenever(it).recordTransactions(any(), anyVararg()) doReturn(NodeVaultService(testClock, kms, stateLoader, database.hibernateConfig)).whenever(it).vaultService doReturn(this@NodeSchedulerServiceTest).whenever(it).testReference diff --git a/node/src/test/kotlin/net/corda/node/services/network/NetworkMapUpdaterTest.kt b/node/src/test/kotlin/net/corda/node/services/network/NetworkMapUpdaterTest.kt index 12086491ca..fc3542a3d6 100644 --- a/node/src/test/kotlin/net/corda/node/services/network/NetworkMapUpdaterTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/network/NetworkMapUpdaterTest.kt @@ -52,7 +52,7 @@ class NetworkMapUpdaterTest { val networkMapClient = mock() val scheduler = TestScheduler() - val fileWatcher = NodeInfoWatcher(baseDir, scheduler = scheduler) + val fileWatcher = NodeInfoWatcher(baseDir, scheduler) val updater = NetworkMapUpdater(networkMapCache, fileWatcher, networkMapClient) // Publish node info for the first time. @@ -101,7 +101,7 @@ class NetworkMapUpdaterTest { } val scheduler = TestScheduler() - val fileWatcher = NodeInfoWatcher(baseDir, scheduler = scheduler) + val fileWatcher = NodeInfoWatcher(baseDir, scheduler) val updater = NetworkMapUpdater(networkMapCache, fileWatcher, networkMapClient) // Test adding new node. @@ -155,7 +155,7 @@ class NetworkMapUpdaterTest { } val scheduler = TestScheduler() - val fileWatcher = NodeInfoWatcher(baseDir, scheduler = scheduler) + val fileWatcher = NodeInfoWatcher(baseDir, scheduler) val updater = NetworkMapUpdater(networkMapCache, fileWatcher, networkMapClient) // Add all nodes. @@ -199,7 +199,7 @@ class NetworkMapUpdaterTest { val networkMapCache = getMockNetworkMapCache() val scheduler = TestScheduler() - val fileWatcher = NodeInfoWatcher(baseDir, scheduler = scheduler) + val fileWatcher = NodeInfoWatcher(baseDir, scheduler) val updater = NetworkMapUpdater(networkMapCache, fileWatcher, null) // Not subscribed yet. diff --git a/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt b/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt index 16c6d62c43..d79c5560f9 100644 --- a/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt +++ b/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt @@ -4,7 +4,7 @@ import net.corda.core.messaging.CordaRPCOps import net.corda.core.utilities.getOrThrow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_B import net.corda.testing.driver.PortAllocation diff --git a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/Main.kt b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/Main.kt index eafecb2fa8..9c3b8a2304 100644 --- a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/Main.kt +++ b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/Main.kt @@ -1,7 +1,7 @@ package net.corda.attachmentdemo import net.corda.core.internal.div -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_B import net.corda.testing.driver.driver diff --git a/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt b/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt index 229d74ed4b..d53cecafe9 100644 --- a/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt +++ b/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt @@ -10,7 +10,7 @@ import net.corda.finance.contracts.asset.Cash import net.corda.finance.flows.CashIssueAndPaymentFlow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.driver.driver import org.junit.Test diff --git a/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/BankOfCordaCordform.kt b/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/BankOfCordaCordform.kt index a0afe2ad4b..0e286a14a0 100644 --- a/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/BankOfCordaCordform.kt +++ b/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/BankOfCordaCordform.kt @@ -12,7 +12,7 @@ import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.Permissions.Companion.all import net.corda.node.services.config.NotaryConfig -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.BOC import net.corda.testing.internal.demorun.* import java.util.* diff --git a/samples/irs-demo/cordapp/src/test/kotlin/net/corda/irs/contract/IRSTests.kt b/samples/irs-demo/cordapp/src/test/kotlin/net/corda/irs/contract/IRSTests.kt index a0e75da7ac..c200bd7c88 100644 --- a/samples/irs-demo/cordapp/src/test/kotlin/net/corda/irs/contract/IRSTests.kt +++ b/samples/irs-demo/cordapp/src/test/kotlin/net/corda/irs/contract/IRSTests.kt @@ -385,8 +385,8 @@ class IRSTests { return ledger { transaction("Agreement") { attachments(IRS_PROGRAM_ID) - output(IRS_PROGRAM_ID, "irs post agreement") { singleIRS() } - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + output(IRS_PROGRAM_ID, "irs post agreement", singleIRS()) + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this.verifies() } @@ -395,17 +395,14 @@ class IRSTests { attachments(IRS_PROGRAM_ID) input("irs post agreement") val postAgreement = "irs post agreement".output() - output(IRS_PROGRAM_ID, "irs post first fixing") { + output(IRS_PROGRAM_ID, "irs post first fixing", postAgreement.copy( postAgreement.fixedLeg, postAgreement.floatingLeg, postAgreement.calculation.applyFixing(ld, FixedRate(RatioUnit(bd))), - postAgreement.common - ) - } - command(ORACLE_PUBKEY) { - InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)) - } + postAgreement.common)) + command(ORACLE_PUBKEY, + InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd))) timeWindow(TEST_TX_TIME) this.verifies() } @@ -419,7 +416,7 @@ class IRSTests { attachments(IRS_PROGRAM_ID) input(IRS_PROGRAM_ID, irs) output(IRS_PROGRAM_ID, "irs post agreement", irs) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "There are no in states for an agreement" } @@ -432,7 +429,7 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) output(IRS_PROGRAM_ID, irs.copy(calculation = irs.calculation.copy(fixedLegPaymentSchedule = emptySchedule))) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "There are events in the fix schedule" } @@ -445,7 +442,7 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) output(IRS_PROGRAM_ID, irs.copy(calculation = irs.calculation.copy(floatingLegPaymentSchedule = emptySchedule))) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "There are events in the float schedule" } @@ -457,7 +454,7 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) output(IRS_PROGRAM_ID, irs.copy(irs.fixedLeg.copy(notional = irs.fixedLeg.notional.copy(quantity = 0)))) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "All notionals must be non zero" } @@ -465,7 +462,7 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) output(IRS_PROGRAM_ID, irs.copy(irs.fixedLeg.copy(notional = irs.floatingLeg.notional.copy(quantity = 0)))) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "All notionals must be non zero" } @@ -478,7 +475,7 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) output(IRS_PROGRAM_ID, modifiedIRS) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "The fixed leg rate must be positive" } @@ -494,7 +491,7 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) output(IRS_PROGRAM_ID, modifiedIRS) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "The currency of the notionals must be the same" } @@ -507,7 +504,7 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) output(IRS_PROGRAM_ID, modifiedIRS) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "All leg notionals must be the same" } @@ -520,7 +517,7 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) output(IRS_PROGRAM_ID, modifiedIRS1) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "The effective date is before the termination date for the fixed leg" } @@ -529,7 +526,7 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) output(IRS_PROGRAM_ID, modifiedIRS2) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "The effective date is before the termination date for the floating leg" } @@ -543,7 +540,7 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) output(IRS_PROGRAM_ID, modifiedIRS3) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "The termination dates are aligned" } @@ -553,7 +550,7 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) output(IRS_PROGRAM_ID, modifiedIRS4) - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this `fails with` "The effective dates are aligned" } @@ -567,8 +564,8 @@ class IRSTests { transaction { attachments(IRS_PROGRAM_ID) - output(IRS_PROGRAM_ID, "irs post agreement") { singleIRS() } - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + output(IRS_PROGRAM_ID, "irs post agreement", singleIRS()) + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this.verifies() } @@ -585,9 +582,8 @@ class IRSTests { // Templated tweak for reference. A corrent fixing applied should be ok tweak { - command(ORACLE_PUBKEY) { - InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)) - } + command(ORACLE_PUBKEY, + InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd))) timeWindow(TEST_TX_TIME) output(IRS_PROGRAM_ID, newIRS) this.verifies() @@ -595,7 +591,7 @@ class IRSTests { // This test makes sure that verify confirms the fixing was applied and there is a difference in the old and new tweak { - command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)) } + command(ORACLE_PUBKEY, InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd))) timeWindow(TEST_TX_TIME) output(IRS_PROGRAM_ID, oldIRS) this `fails with` "There is at least one difference in the IRS floating leg payment schedules" @@ -603,42 +599,36 @@ class IRSTests { // This tests tries to sneak in a change to another fixing (which may or may not be the latest one) tweak { - command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)) } + command(ORACLE_PUBKEY, InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd))) timeWindow(TEST_TX_TIME) val firstResetKey = newIRS.calculation.floatingLegPaymentSchedule.keys.toList()[1] val firstResetValue = newIRS.calculation.floatingLegPaymentSchedule[firstResetKey] val modifiedFirstResetValue = firstResetValue!!.copy(notional = Amount(firstResetValue.notional.quantity, Currency.getInstance("JPY"))) - - output(IRS_PROGRAM_ID) { + output(IRS_PROGRAM_ID, newIRS.copy( newIRS.fixedLeg, newIRS.floatingLeg, newIRS.calculation.copy(floatingLegPaymentSchedule = newIRS.calculation.floatingLegPaymentSchedule.plus( Pair(firstResetKey, modifiedFirstResetValue))), - newIRS.common - ) - } + newIRS.common)) this `fails with` "There is only one change in the IRS floating leg payment schedule" } // This tests modifies the payment currency for the fixing tweak { - command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)) } + command(ORACLE_PUBKEY, InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd))) timeWindow(TEST_TX_TIME) val latestReset = newIRS.calculation.floatingLegPaymentSchedule.filter { it.value.rate is FixedRate }.maxBy { it.key } val modifiedLatestResetValue = latestReset!!.value.copy(notional = Amount(latestReset.value.notional.quantity, Currency.getInstance("JPY"))) - - output(IRS_PROGRAM_ID) { + output(IRS_PROGRAM_ID, newIRS.copy( newIRS.fixedLeg, newIRS.floatingLeg, newIRS.calculation.copy(floatingLegPaymentSchedule = newIRS.calculation.floatingLegPaymentSchedule.plus( Pair(latestReset.key, modifiedLatestResetValue))), - newIRS.common - ) - } + newIRS.common)) this `fails with` "The fix payment has the same currency as the notional" } } @@ -660,31 +650,27 @@ class IRSTests { return ledger { transaction("Agreement") { attachments(IRS_PROGRAM_ID) - output(IRS_PROGRAM_ID, "irs post agreement1") { + output(IRS_PROGRAM_ID, "irs post agreement1", irs.copy( irs.fixedLeg, irs.floatingLeg, irs.calculation, - irs.common.copy(tradeID = "t1") - ) - } - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + irs.common.copy(tradeID = "t1"))) + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this.verifies() } transaction("Agreement") { attachments(IRS_PROGRAM_ID) - output(IRS_PROGRAM_ID, "irs post agreement2") { + output(IRS_PROGRAM_ID, "irs post agreement2", irs.copy( linearId = UniqueIdentifier("t2"), fixedLeg = irs.fixedLeg, floatingLeg = irs.floatingLeg, calculation = irs.calculation, - common = irs.common.copy(tradeID = "t2") - ) - } - command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() } + common = irs.common.copy(tradeID = "t2"))) + command(MEGA_CORP_PUBKEY, InterestRateSwap.Commands.Agree()) timeWindow(TEST_TX_TIME) this.verifies() } @@ -694,27 +680,21 @@ class IRSTests { input("irs post agreement1") input("irs post agreement2") val postAgreement1 = "irs post agreement1".output() - output(IRS_PROGRAM_ID, "irs post first fixing1") { + output(IRS_PROGRAM_ID, "irs post first fixing1", postAgreement1.copy( postAgreement1.fixedLeg, postAgreement1.floatingLeg, postAgreement1.calculation.applyFixing(ld1, FixedRate(RatioUnit(bd1))), - postAgreement1.common.copy(tradeID = "t1") - ) - } + postAgreement1.common.copy(tradeID = "t1"))) val postAgreement2 = "irs post agreement2".output() - output(IRS_PROGRAM_ID, "irs post first fixing2") { + output(IRS_PROGRAM_ID, "irs post first fixing2", postAgreement2.copy( postAgreement2.fixedLeg, postAgreement2.floatingLeg, postAgreement2.calculation.applyFixing(ld1, FixedRate(RatioUnit(bd1))), - postAgreement2.common.copy(tradeID = "t2") - ) - } - - command(ORACLE_PUBKEY) { - InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld1, Tenor("3M")), bd1)) - } + postAgreement2.common.copy(tradeID = "t2"))) + command(ORACLE_PUBKEY, + InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld1, Tenor("3M")), bd1))) timeWindow(TEST_TX_TIME) this.verifies() } diff --git a/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt b/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt index f47c16a623..bf850cc841 100644 --- a/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt +++ b/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt @@ -21,7 +21,7 @@ import net.corda.finance.plugin.registerFinanceJSONMappers import net.corda.irs.contract.InterestRateSwap import net.corda.irs.web.IrsDemoWebApplication import net.corda.node.services.config.NodeConfiguration -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.test.spring.springDriver import net.corda.testing.* import net.corda.testing.http.HttpApi diff --git a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/SingleNotaryCordform.kt b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/SingleNotaryCordform.kt index 23381b72d1..ea2366c953 100644 --- a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/SingleNotaryCordform.kt +++ b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/SingleNotaryCordform.kt @@ -4,7 +4,7 @@ import net.corda.cordform.CordformContext import net.corda.cordform.CordformDefinition import net.corda.node.services.Permissions.Companion.all import net.corda.node.services.config.NotaryConfig -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.ALICE import net.corda.testing.BOB import net.corda.testing.DUMMY_NOTARY diff --git a/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt b/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt index af253af527..a4b7285938 100644 --- a/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt +++ b/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt @@ -8,7 +8,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.all import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.BOC import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_B diff --git a/samples/trader-demo/src/test/kotlin/net/corda/traderdemo/Main.kt b/samples/trader-demo/src/test/kotlin/net/corda/traderdemo/Main.kt index dce315e84e..b59890ab61 100644 --- a/samples/trader-demo/src/test/kotlin/net/corda/traderdemo/Main.kt +++ b/samples/trader-demo/src/test/kotlin/net/corda/traderdemo/Main.kt @@ -4,7 +4,7 @@ import net.corda.core.internal.div import net.corda.finance.flows.CashIssueFlow import net.corda.node.services.Permissions.Companion.all import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.BOC import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_B diff --git a/testing/node-driver/src/integration-test/kotlin/net/corda/testing/FlowStackSnapshotTest.kt b/testing/node-driver/src/integration-test/kotlin/net/corda/testing/FlowStackSnapshotTest.kt index f33897854c..c6e01c4193 100644 --- a/testing/node-driver/src/integration-test/kotlin/net/corda/testing/FlowStackSnapshotTest.kt +++ b/testing/node-driver/src/integration-test/kotlin/net/corda/testing/FlowStackSnapshotTest.kt @@ -9,7 +9,7 @@ import net.corda.core.internal.read import net.corda.core.messaging.startFlow import net.corda.core.serialization.CordaSerializable import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.driver.driver import net.corda.testing.node.MockNetwork import org.junit.Ignore diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/DriverConstants.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/DriverConstants.kt deleted file mode 100644 index 6c050f24b8..0000000000 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/DriverConstants.kt +++ /dev/null @@ -1,52 +0,0 @@ -@file:JvmName("DriverConstants") - -package net.corda.testing - -import net.corda.core.identity.Party -import net.corda.core.internal.concurrent.transpose -import net.corda.core.messaging.CordaRPCOps -import net.corda.nodeapi.User -import net.corda.testing.driver.DriverDSLExposedInterface - -// -// Extensions to the Driver DSL to auto-manufacture nodes by name. -// - -/** - * A simple wrapper for objects provided by the integration test driver DSL. The fields are lazy so - * node construction won't start until you access the members. You can get one of these from the - * [alice], [bob] and [aliceAndBob] functions. - */ -class PredefinedTestNode internal constructor(party: Party, driver: DriverDSLExposedInterface) { - val rpcUsers = listOf(User("admin", "admin", setOf("ALL"))) // TODO: Randomize? - val nodeFuture by lazy { driver.startNode(providedName = party.name, rpcUsers = rpcUsers) } - val node by lazy { nodeFuture.get()!! } - val rpc by lazy { node.rpcClientToNode() } - - fun useRPC(block: (CordaRPCOps) -> R) = rpc.use(rpcUsers[0].username, rpcUsers[0].password) { block(it.proxy) } -} - -// TODO: Probably we should inject the above keys through the driver to make the nodes use it, rather than have the warnings below. - -/** - * Returns a plain, entirely stock node pre-configured with the [ALICE] identity. Note that a random key will be generated - * for it: you won't have [ALICE_KEY]. - */ -fun DriverDSLExposedInterface.alice(): PredefinedTestNode = PredefinedTestNode(ALICE, this) - -/** - * Returns a plain, entirely stock node pre-configured with the [BOB] identity. Note that a random key will be generated - * for it: you won't have [BOB_KEY]. - */ -fun DriverDSLExposedInterface.bob(): PredefinedTestNode = PredefinedTestNode(BOB, this) - -/** - * Returns plain, entirely stock nodes pre-configured with the [ALICE] and [BOB] X.500 names in that order. They have been - * started up in parallel and are now ready to use. - */ -fun DriverDSLExposedInterface.aliceAndBob(): List { - val alice = alice() - val bob = bob() - listOf(alice.nodeFuture, bob.nodeFuture).transpose().get() - return listOf(alice, bob) -} diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/NodeTestUtils.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/NodeTestUtils.kt index 9271b57bd1..41b4e360ff 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/NodeTestUtils.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/NodeTestUtils.kt @@ -2,7 +2,6 @@ package net.corda.testing -import com.nhaarman.mockito_kotlin.doCallRealMethod import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.whenever import net.corda.core.context.Actor @@ -21,7 +20,7 @@ import net.corda.node.services.config.CertChainPolicyConfig import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.VerifierType -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties import java.nio.file.Path @@ -74,11 +73,6 @@ fun testNodeConfiguration( doReturn(5).whenever(it).messageRedeliveryDelaySeconds doReturn(5.seconds.toMillis()).whenever(it).additionalNodeInfoPollingFrequencyMsec doReturn(null).whenever(it).devModeOptions - doCallRealMethod().whenever(it).certificatesDirectory - doCallRealMethod().whenever(it).trustStoreFile - doCallRealMethod().whenever(it).sslKeystore - doCallRealMethod().whenever(it).nodeKeystore - doCallRealMethod().whenever(it).rootCaCertFile } } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt index 12851cdaf5..26f124813c 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt @@ -26,7 +26,6 @@ import net.corda.core.utilities.* import net.corda.node.internal.Node import net.corda.node.internal.NodeStartup import net.corda.node.internal.StartedNode -import net.corda.node.internal.cordapp.CordappLoader import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.config.* import net.corda.node.services.transactions.BFTNonValidatingNotaryService @@ -36,9 +35,9 @@ import net.corda.nodeapi.internal.ServiceIdentityGenerator import net.corda.node.utilities.registration.HTTPNetworkRegistrationService import net.corda.node.utilities.registration.NetworkRegistrationHelper import net.corda.nodeapi.internal.NodeInfoFilesCopier -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.nodeapi.config.parseAs -import net.corda.nodeapi.config.toConfig +import net.corda.nodeapi.internal.config.toConfig import net.corda.nodeapi.internal.NotaryInfo import net.corda.nodeapi.internal.addShutdownHook import net.corda.nodeapi.internal.crypto.X509Utilities @@ -46,6 +45,7 @@ import net.corda.testing.* import net.corda.nodeapi.internal.NetworkParametersCopier import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.driver.DriverDSL.ClusterType.* +import net.corda.testing.internal.InProcessNode import net.corda.testing.internal.ProcessUtilities import net.corda.testing.node.ClusterSpec import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO @@ -345,7 +345,7 @@ data class NodeParameters( * available from [DriverDSLExposedInterface.notaryHandles]. Defaults to a simple validating notary. * @param compatibilityZoneURL if not null each node is started once in registration mode (which makes the node register and quit), * and then re-starts the node with the given parameters. - * @param rootCertificate if not null every time a node is started for registration that certificate is written on disk + * @param rootCertificate if not null every time a node is started for registration that certificate is written on disk * @param dsl The dsl itself. * @return The value returned in the [dsl] closure. */ @@ -1120,12 +1120,7 @@ class DriverDSL( // Write node.conf writeConfig(nodeConf.baseDirectory, "node.conf", config) // TODO pass the version in? - val node = Node( - nodeConf, - MOCK_VERSION_INFO, - initialiseSerialization = false, - cordappLoader = CordappLoader.createDefaultWithTestPackages(nodeConf, cordappPackages)) - .start() + val node = InProcessNode(nodeConf, MOCK_VERSION_INFO, cordappPackages).start() val nodeThread = thread(name = nodeConf.myLegalName.organisation) { node.internals.run() } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/NodeBasedTest.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/NodeBasedTest.kt index 027232f1f5..c0220e843c 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/NodeBasedTest.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/NodeBasedTest.kt @@ -7,25 +7,28 @@ import net.corda.core.internal.createDirectories import net.corda.core.internal.div import net.corda.core.node.NodeInfo import net.corda.core.utilities.getOrThrow +import net.corda.node.VersionInfo import net.corda.node.internal.Node import net.corda.node.internal.StartedNode import net.corda.node.internal.cordapp.CordappLoader +import net.corda.node.services.config.* import net.corda.node.services.config.ConfigHelper import net.corda.node.services.config.configOf import net.corda.node.services.config.parseAsNodeConfiguration import net.corda.node.services.config.plus -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.SerializationEnvironmentRule import net.corda.nodeapi.internal.NetworkParametersCopier import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.driver.addressMustNotBeBoundFuture import net.corda.testing.getFreeLocalPorts -import net.corda.testing.node.MockServices +import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO import org.apache.logging.log4j.Level import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.rules.TemporaryFolder +import rx.internal.schedulers.CachedThreadScheduler import java.nio.file.Path import java.util.concurrent.Executors import kotlin.concurrent.thread @@ -100,11 +103,7 @@ abstract class NodeBasedTest(private val cordappPackages: List = emptyLi val parsedConfig = config.parseAsNodeConfiguration() defaultNetworkParameters.install(baseDirectory) - val node = Node( - parsedConfig, - MockServices.MOCK_VERSION_INFO.copy(platformVersion = platformVersion), - initialiseSerialization = false, - cordappLoader = CordappLoader.createDefaultWithTestPackages(parsedConfig, cordappPackages)).start() + val node = InProcessNode(parsedConfig, MOCK_VERSION_INFO.copy(platformVersion = platformVersion), cordappPackages).start() nodes += node ensureAllNetworkMapCachesHaveAllNodeInfos() thread(name = legalName.organisation) { @@ -127,3 +126,9 @@ abstract class NodeBasedTest(private val cordappPackages: List = emptyLi } } } + +class InProcessNode( + configuration: NodeConfiguration, versionInfo: VersionInfo, cordappPackages: List) : Node( + configuration, versionInfo, false, CordappLoader.createDefaultWithTestPackages(configuration, cordappPackages)) { + override fun getRxIoScheduler() = CachedThreadScheduler(testThreadFactory()).also { runOnStop += it::shutdown } +} diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/RPCDriver.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/RPCDriver.kt index 1dec5f7076..5dab84146c 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/RPCDriver.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/RPCDriver.kt @@ -23,7 +23,7 @@ import net.corda.node.services.messaging.RPCServerConfiguration import net.corda.nodeapi.ArtemisTcpTransport import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.RPCApi -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.nodeapi.internal.serialization.KRYO_RPC_CLIENT_CONTEXT import net.corda.testing.driver.* import net.corda.testing.node.NotarySpec diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/demorun/CordformUtils.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/demorun/CordformUtils.kt index dcf0255a9a..9e566a0867 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/demorun/CordformUtils.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/demorun/CordformUtils.kt @@ -6,8 +6,8 @@ import net.corda.cordform.CordformDefinition import net.corda.cordform.CordformNode import net.corda.core.identity.CordaX500Name import net.corda.node.services.config.NotaryConfig -import net.corda.nodeapi.User -import net.corda.nodeapi.config.toConfig +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.toConfig fun CordformDefinition.node(configure: CordformNode.() -> Unit) { addNode { cordformNode -> cordformNode.configure() } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt index 420c66ca77..ed9106c8a2 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt @@ -42,12 +42,14 @@ import net.corda.nodeapi.internal.NotaryInfo import net.corda.testing.DUMMY_NOTARY import net.corda.nodeapi.internal.NetworkParametersCopier import net.corda.testing.common.internal.testNetworkParameters +import net.corda.testing.internal.testThreadFactory import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties import net.corda.testing.setGlobalSerialization import net.corda.testing.testNodeConfiguration import org.apache.activemq.artemis.utils.ReusableLatch import org.apache.sshd.common.util.security.SecurityUtils +import rx.internal.schedulers.CachedThreadScheduler import java.math.BigInteger import java.nio.file.Path import java.security.KeyPair @@ -267,6 +269,7 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete return started } + override fun getRxIoScheduler() = CachedThreadScheduler(testThreadFactory()).also { runOnStop += it::shutdown } private fun advertiseNodeToNetwork(newNode: StartedNode) { mockNet.nodes .mapNotNull { it.started } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/NotarySpec.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/NotarySpec.kt index 336d6bfc8d..b8988e50c7 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/NotarySpec.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/NotarySpec.kt @@ -2,7 +2,7 @@ package net.corda.testing.node import net.corda.core.identity.CordaX500Name import net.corda.node.services.config.VerifierType -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User data class NotarySpec( val name: CordaX500Name, diff --git a/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeConfig.kt b/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeConfig.kt index c97f3a8191..4f002c6f9d 100644 --- a/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeConfig.kt +++ b/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeConfig.kt @@ -6,7 +6,7 @@ import com.typesafe.config.ConfigRenderOptions import com.typesafe.config.ConfigValue import com.typesafe.config.ConfigValueFactory import net.corda.core.identity.CordaX500Name -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User class NodeConfig( val legalName: CordaX500Name, diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt index 2fdb34673d..df5d85661c 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt @@ -16,7 +16,7 @@ import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.loggerFor import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER import net.corda.node.services.config.configureDevKeyAndTrustStores -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair import net.corda.nodeapi.internal.crypto.CertificateType import net.corda.nodeapi.internal.crypto.X509CertificateFactory @@ -24,6 +24,7 @@ import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.serialization.amqp.AMQP_ENABLED import org.mockito.Mockito.mock import org.mockito.internal.stubbing.answers.ThrowsException +import java.lang.reflect.Modifier import java.nio.file.Files import java.security.KeyPair import java.security.PublicKey @@ -180,11 +181,16 @@ class UndefinedMockBehaviorException(message: String) : RuntimeException(message inline fun rigorousMock() = rigorousMock(T::class.java) /** - * Create a Mockito mock that has [UndefinedMockBehaviorException] as the default behaviour of all methods. - * @param T the type to mock. Note if you want to use [com.nhaarman.mockito_kotlin.doCallRealMethod] on a Kotlin interface, + * Create a Mockito mock that has [UndefinedMockBehaviorException] as the default behaviour of all abstract methods, + * and [org.mockito.invocation.InvocationOnMock.callRealMethod] as the default for all concrete methods. + * @param T the type to mock. Note if you want concrete methods of a Kotlin interface to be invoked, * it won't work unless you mock a (trivial) abstract implementation of that interface instead. */ fun rigorousMock(clazz: Class): T = mock(clazz) { - // Use ThrowsException to hack the stack trace, and lazily so we can customise the message: - ThrowsException(UndefinedMockBehaviorException("Please specify what should happen when '${it.method}' is called, or don't call it. Args: ${Arrays.toString(it.arguments)}")).answer(it) + if (Modifier.isAbstract(it.method.modifiers)) { + // Use ThrowsException to hack the stack trace, and lazily so we can customise the message: + ThrowsException(UndefinedMockBehaviorException("Please specify what should happen when '${it.method}' is called, or don't call it. Args: ${Arrays.toString(it.arguments)}")).answer(it) + } else { + it.callRealMethod() + } } diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/TestDSL.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/TestDSL.kt index 48658ea021..3167eb7a38 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/TestDSL.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/TestDSL.kt @@ -93,7 +93,7 @@ data class TestTransactionDSLInterpreter private constructor( transactionBuilder.addInputState(StateAndRef(state, stateRef)) } - override fun _output(contractClassName: ContractClassName, + override fun output(contractClassName: ContractClassName, label: String?, notary: Party, encumbrance: Int?, @@ -115,7 +115,7 @@ data class TestTransactionDSLInterpreter private constructor( transactionBuilder.addAttachment(attachmentId) } - override fun _command(signers: List, commandData: CommandData) { + override fun command(signers: List, commandData: CommandData) { val command = Command(commandData, signers) transactionBuilder.addCommand(command) } diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/TransactionDSLInterpreter.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/TransactionDSLInterpreter.kt index af6520f4dc..356323f613 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/TransactionDSLInterpreter.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/TransactionDSLInterpreter.kt @@ -35,12 +35,12 @@ interface TransactionDSLInterpreter : Verifies, OutputStateLookup { * @param contractState The state itself. * @param contractClassName The class name of the contract that verifies this state. */ - fun _output(contractClassName: ContractClassName, - label: String?, - notary: Party, - encumbrance: Int?, - attachmentConstraint: AttachmentConstraint, - contractState: ContractState) + fun output(contractClassName: ContractClassName, + label: String?, + notary: Party, + encumbrance: Int?, + attachmentConstraint: AttachmentConstraint, + contractState: ContractState) /** * Adds an [Attachment] reference to the transaction. @@ -53,7 +53,7 @@ interface TransactionDSLInterpreter : Verifies, OutputStateLookup { * @param signers The signer public keys. * @param commandData The contents of the command. */ - fun _command(signers: List, commandData: CommandData) + fun command(signers: List, commandData: CommandData) /** * Sets the time-window of the transaction. @@ -74,10 +74,10 @@ interface TransactionDSLInterpreter : Verifies, OutputStateLookup { fun _attachment(contractClassName: ContractClassName) } -class TransactionDSL(val interpreter: T) : TransactionDSLInterpreter by interpreter { +class TransactionDSL(interpreter: T) : TransactionDSLInterpreter by interpreter { /** * Looks up the output label and adds the found state as an input. - * @param stateLabel The label of the output state specified when calling [TransactionDSLInterpreter._output] and friends. + * @param stateLabel The label of the output state specified when calling [TransactionDSLInterpreter.output] and friends. */ fun input(stateLabel: String) = input(retrieveOutputStateAndRef(ContractState::class.java, stateLabel).ref) @@ -88,49 +88,51 @@ class TransactionDSL(val interpreter: T) : Tr */ fun input(contractClassName: ContractClassName, state: ContractState) { val transaction = ledgerInterpreter._unverifiedTransaction(null, TransactionBuilder(notary = DUMMY_NOTARY)) { - output(contractClassName, attachmentConstraint = AlwaysAcceptAttachmentConstraint) { state } + output(contractClassName, null, DUMMY_NOTARY, null, AlwaysAcceptAttachmentConstraint, state) } input(transaction.outRef(0).ref) } - fun input(contractClassName: ContractClassName, stateClosure: () -> ContractState) = input(contractClassName, stateClosure()) - /** - * Adds an output to the transaction. + * Adds a labelled output to the transaction. */ - @JvmOverloads - fun output(contractClassName: ContractClassName, - label: String? = null, - notary: Party = DUMMY_NOTARY, - encumbrance: Int? = null, - attachmentConstraint: AttachmentConstraint = AutomaticHashConstraint, - contractStateClosure: () -> ContractState) = - _output(contractClassName, label, notary, encumbrance, attachmentConstraint, contractStateClosure()) + fun output(contractClassName: ContractClassName, label: String, notary: Party, contractState: ContractState) = + output(contractClassName, label, notary, null, AutomaticHashConstraint, contractState) /** * Adds a labelled output to the transaction. */ - @JvmOverloads - fun output(contractClassName: ContractClassName, label: String, contractState: ContractState, attachmentConstraint: AttachmentConstraint = AutomaticHashConstraint) = - _output(contractClassName, label, DUMMY_NOTARY, null, attachmentConstraint, contractState) + fun output(contractClassName: ContractClassName, label: String, encumbrance: Int, contractState: ContractState) = + output(contractClassName, label, DUMMY_NOTARY, encumbrance, AutomaticHashConstraint, contractState) + + /** + * Adds a labelled output to the transaction. + */ + fun output(contractClassName: ContractClassName, label: String, contractState: ContractState) = + output(contractClassName, label, DUMMY_NOTARY, null, AutomaticHashConstraint, contractState) /** * Adds an output to the transaction. */ - @JvmOverloads - fun output(contractClassName: ContractClassName, contractState: ContractState, attachmentConstraint: AttachmentConstraint = AutomaticHashConstraint) = - _output(contractClassName, null, DUMMY_NOTARY, null, attachmentConstraint, contractState) + fun output(contractClassName: ContractClassName, notary: Party, contractState: ContractState) = + output(contractClassName, null, notary, null, AutomaticHashConstraint, contractState) + + /** + * Adds an output to the transaction. + */ + fun output(contractClassName: ContractClassName, encumbrance: Int, contractState: ContractState) = + output(contractClassName, null, DUMMY_NOTARY, encumbrance, AutomaticHashConstraint, contractState) + + /** + * Adds an output to the transaction. + */ + fun output(contractClassName: ContractClassName, contractState: ContractState) = + output(contractClassName, null, DUMMY_NOTARY, null, AutomaticHashConstraint, contractState) /** * Adds a command to the transaction. */ - fun command(vararg signers: PublicKey, commandDataClosure: () -> CommandData) = - _command(listOf(*signers), commandDataClosure()) - - /** - * Adds a command to the transaction. - */ - fun command(signer: PublicKey, commandData: CommandData) = _command(listOf(signer), commandData) + fun command(signer: PublicKey, commandData: CommandData) = command(listOf(signer), commandData) /** * Sets the [TimeWindow] of the transaction. @@ -142,7 +144,7 @@ class TransactionDSL(val interpreter: T) : Tr timeWindow(TimeWindow.withTolerance(time, tolerance)) /** - * @see TransactionDSLInterpreter._contractAttachment + * @see TransactionDSLInterpreter._attachment */ fun attachment(contractClassName: ContractClassName) = _attachment(contractClassName) diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/messaging/SimpleMQClient.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/messaging/SimpleMQClient.kt index 705f150f89..235692b111 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/messaging/SimpleMQClient.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/messaging/SimpleMQClient.kt @@ -5,7 +5,7 @@ import net.corda.core.serialization.internal.nodeSerializationEnv import net.corda.core.utilities.NetworkHostAndPort import net.corda.nodeapi.ArtemisTcpTransport import net.corda.nodeapi.ConnectionDirection -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.testing.configureTestSSL import org.apache.activemq.artemis.api.core.client.* diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt index f7709a7ada..2626eb882d 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt @@ -3,7 +3,7 @@ package net.corda.demobench.model import com.typesafe.config.Config import net.corda.core.internal.div import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.config.parseAs +import net.corda.nodeapi.internal.config.parseAs import tornadofx.* import java.io.IOException import java.nio.file.Files diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt index 8ac6aeefdf..ae5b6deeb1 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt @@ -6,8 +6,8 @@ import net.corda.core.internal.copyToDirectory import net.corda.core.internal.createDirectories import net.corda.core.internal.div import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.User -import net.corda.nodeapi.config.toConfig +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.toConfig import java.nio.file.Path import java.nio.file.StandardCopyOption diff --git a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt index 8ebcbaf2cc..0c9caca94a 100644 --- a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt +++ b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt @@ -5,8 +5,8 @@ import com.typesafe.config.ConfigValueFactory import net.corda.core.identity.CordaX500Name import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.config.parseAsNodeConfiguration -import net.corda.nodeapi.User -import net.corda.nodeapi.config.toConfig +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.toConfig import net.corda.webserver.WebServerConfig import org.assertj.core.api.Assertions.assertThat import org.junit.Test diff --git a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt index 21899794d8..18db310a5b 100644 --- a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt +++ b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt @@ -2,7 +2,7 @@ package net.corda.demobench.model import net.corda.core.identity.CordaX500Name import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import org.junit.Test import java.nio.file.Path import java.nio.file.Paths diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/ExplorerSimulation.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/ExplorerSimulation.kt index ee1495ebd6..b92dfd144b 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/ExplorerSimulation.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/ExplorerSimulation.kt @@ -21,7 +21,7 @@ import net.corda.finance.flows.* import net.corda.finance.flows.CashExitFlow.ExitRequest import net.corda.finance.flows.CashIssueAndPaymentFlow.IssueAndPaymentRequest import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.ALICE import net.corda.testing.BOB import net.corda.testing.driver.NodeHandle diff --git a/tools/loadtest/src/main/kotlin/net/corda/loadtest/LoadTestConfiguration.kt b/tools/loadtest/src/main/kotlin/net/corda/loadtest/LoadTestConfiguration.kt index 8e4a962002..9343605434 100644 --- a/tools/loadtest/src/main/kotlin/net/corda/loadtest/LoadTestConfiguration.kt +++ b/tools/loadtest/src/main/kotlin/net/corda/loadtest/LoadTestConfiguration.kt @@ -1,6 +1,6 @@ package net.corda.loadtest -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import java.nio.file.Path import java.util.concurrent.ForkJoinPool diff --git a/tools/loadtest/src/main/kotlin/net/corda/loadtest/Main.kt b/tools/loadtest/src/main/kotlin/net/corda/loadtest/Main.kt index 0bd12ae78d..eb4e103c73 100644 --- a/tools/loadtest/src/main/kotlin/net/corda/loadtest/Main.kt +++ b/tools/loadtest/src/main/kotlin/net/corda/loadtest/Main.kt @@ -5,7 +5,7 @@ import com.typesafe.config.ConfigParseOptions import net.corda.loadtest.tests.StabilityTest import net.corda.loadtest.tests.crossCashTest import net.corda.loadtest.tests.selfIssueTest -import net.corda.nodeapi.config.parseAs +import net.corda.nodeapi.internal.config.parseAs import java.io.File /** diff --git a/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt b/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt index 61b80faa6b..ad93ad819f 100644 --- a/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt +++ b/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt @@ -19,8 +19,8 @@ import net.corda.node.services.config.configureDevKeyAndTrustStores import net.corda.nodeapi.ArtemisTcpTransport import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.VerifierApi -import net.corda.nodeapi.config.NodeSSLConfiguration -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.NodeSSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER import net.corda.testing.driver.* import net.corda.testing.internal.ProcessUtilities diff --git a/verifier/src/main/kotlin/net/corda/verifier/Verifier.kt b/verifier/src/main/kotlin/net/corda/verifier/Verifier.kt index 7c04bf1ce9..5db494cad1 100644 --- a/verifier/src/main/kotlin/net/corda/verifier/Verifier.kt +++ b/verifier/src/main/kotlin/net/corda/verifier/Verifier.kt @@ -12,8 +12,8 @@ import net.corda.nodeapi.ArtemisTcpTransport.Companion.tcpTransport import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.VerifierApi import net.corda.nodeapi.VerifierApi.VERIFICATION_REQUESTS_QUEUE_NAME -import net.corda.nodeapi.config.NodeSSLConfiguration -import net.corda.nodeapi.config.getValue +import net.corda.nodeapi.internal.config.NodeSSLConfiguration +import net.corda.nodeapi.internal.config.getValue import net.corda.nodeapi.internal.addShutdownHook import net.corda.nodeapi.internal.serialization.* import net.corda.nodeapi.internal.serialization.amqp.AbstractAMQPSerializationScheme diff --git a/webserver/src/main/kotlin/net/corda/webserver/WebServerConfig.kt b/webserver/src/main/kotlin/net/corda/webserver/WebServerConfig.kt index 53522b8399..b3be74b11b 100644 --- a/webserver/src/main/kotlin/net/corda/webserver/WebServerConfig.kt +++ b/webserver/src/main/kotlin/net/corda/webserver/WebServerConfig.kt @@ -2,9 +2,9 @@ package net.corda.webserver import com.typesafe.config.Config import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.User -import net.corda.nodeapi.config.NodeSSLConfiguration -import net.corda.nodeapi.config.getValue +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.NodeSSLConfiguration +import net.corda.nodeapi.internal.config.getValue import java.nio.file.Path /**