From ff1a1c4848c95af18e3bcc8289b86d1819d6b8b2 Mon Sep 17 00:00:00 2001 From: jamescarlyle Date: Thu, 18 Aug 2016 19:41:17 +0100 Subject: [PATCH 01/10] Encumbrances implemented by reference to an index of an output state --- .../contracts/JavaCommercialPaper.java | 6 + .../com/r3corda/contracts/asset/Cash.kt | 8 +- .../com/r3corda/core/contracts/Structures.kt | 5 + .../core/contracts/TransactionTypes.kt | 9 ++ .../core/contracts/TransactionVerification.kt | 2 + .../contracts/TransactionEncumbranceTests.kt | 145 ++++++++++++++++++ 6 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt diff --git a/contracts/src/main/java/com/r3corda/contracts/JavaCommercialPaper.java b/contracts/src/main/java/com/r3corda/contracts/JavaCommercialPaper.java index 79289a9e10..9405f12ca8 100644 --- a/contracts/src/main/java/com/r3corda/contracts/JavaCommercialPaper.java +++ b/contracts/src/main/java/com/r3corda/contracts/JavaCommercialPaper.java @@ -120,6 +120,12 @@ public class JavaCommercialPaper implements Contract { public List getParticipants() { return ImmutableList.of(this.owner); } + + @Nullable + @Override + public Integer getEncumbrance() { + return null; + } } public interface Clause { diff --git a/contracts/src/main/kotlin/com/r3corda/contracts/asset/Cash.kt b/contracts/src/main/kotlin/com/r3corda/contracts/asset/Cash.kt index 5778afaf57..f50d54e946 100644 --- a/contracts/src/main/kotlin/com/r3corda/contracts/asset/Cash.kt +++ b/contracts/src/main/kotlin/com/r3corda/contracts/asset/Cash.kt @@ -74,12 +74,14 @@ class Cash : OnLedgerAsset() { class ConserveAmount : AbstractConserveAmount() } - /** A state representing a cash claim against some party */ + /** A state representing a cash claim against some party. */ data class State( override val amount: Amount>, - /** There must be a MoveCommand signed by this key to claim the amount */ - override val owner: PublicKey + /** There must be a MoveCommand signed by this key to claim the amount. */ + override val owner: PublicKey, + /** Cash may be encumbered by an additional state. */ + override val encumbrance: Int? = null ) : FungibleAsset { constructor(deposit: PartyAndReference, amount: Amount, owner: PublicKey) : this(Amount(amount.quantity, Issued(deposit, amount.token)), owner) diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt index a245f9071d..fcbc5ebac1 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt @@ -111,6 +111,11 @@ interface ContractState { * list should just contain the owner. */ val participants: List + + /** The encumbrance state, if present, forces additional controls over this state, since the encumbrance state contract + * will also be verified. + */ + val encumbrance: Int? get() = null } /** diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt index 078009be88..994f1e2de6 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt @@ -77,6 +77,15 @@ sealed class TransactionType { throw TransactionVerificationException.ContractRejection(tx, contract, e) } } + + // Validate that all encumbrances exist within the set of input states. + tx.inputs.filter { it.state.data.encumbrance != null }.forEach { + encumberedInput -> + if (tx.inputs.none { it.ref.txhash == encumberedInput.ref.txhash && it.ref.index == encumberedInput.state.data.encumbrance }) { + throw TransactionVerificationException.TransactionMissingEncumbranceException(tx) + } + } + } override fun getRequiredSigners(tx: LedgerTransaction) = tx.commands.flatMap { it.signers }.toSet() diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt index 44ea14f1c7..680ec59a53 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt @@ -99,5 +99,7 @@ sealed class TransactionVerificationException(val tx: LedgerTransaction, cause: class InvalidNotaryChange(tx: LedgerTransaction) : TransactionVerificationException(tx, null) class NotaryChangeInWrongTransactionType(tx: LedgerTransaction, val outputNotary: Party) : TransactionVerificationException(tx, null) { override fun toString(): String = "Found unexpected notary change in transaction. Tx notary: ${tx.notary}, found: ${outputNotary}" + class TransactionMissingEncumbranceException(tx: LedgerTransaction) : TransactionVerificationException(tx, null) } + class TransactionMissingEncumbranceException(tx: LedgerTransaction) : TransactionVerificationException(tx, null) } diff --git a/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt new file mode 100644 index 0000000000..87b6d1187b --- /dev/null +++ b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt @@ -0,0 +1,145 @@ +package com.r3corda.core.contracts + +import com.r3corda.contracts.asset.Cash +import com.r3corda.core.crypto.SecureHash +import com.r3corda.core.serialization.OpaqueBytes +import com.r3corda.core.testing.* +import org.junit.Test +import java.security.PublicKey +import java.time.Instant +import java.time.temporal.ChronoUnit +import kotlin.test.assertFailsWith + +val TEST_TIMELOCK_ID = TransactionEncumbranceTests.TestTimeLock() + +class TransactionEncumbranceTests { + val defaultRef = OpaqueBytes(ByteArray(1, {1})) + val defaultIssuer = MEGA_CORP.ref(defaultRef) + val encumberedState = Cash.State( + amount = 1000.DOLLARS `issued by` defaultIssuer, + owner = DUMMY_PUBKEY_1, + encumbrance = 1 + ) + val unencumberedState = Cash.State( + amount = 1000.DOLLARS `issued by` defaultIssuer, + owner = DUMMY_PUBKEY_1 + ) + val stateWithNewOwner = encumberedState.copy(owner = DUMMY_PUBKEY_2) + val FOUR_PM = Instant.parse("2015-04-17T16:00:00.00Z") + val FIVE_PM = FOUR_PM.plus(1, ChronoUnit.HOURS) + val FIVE_PM_TIMELOCK = TestTimeLock.State(FIVE_PM) + + + class TestTimeLock : Contract { + override val legalContractReference = SecureHash.sha256("TestTimeLock") + override fun verify(tx: TransactionForContract) { + val timestamp: Timestamp? = tx.timestamp + val timeLockCommand = tx.commands.select().first() + if (timeLockCommand.value is TestTimeLock.Commands.Exit) { + val time = timestamp?.before ?: throw IllegalArgumentException("Transactions containing time-locks must be timestamped") + requireThat { + "the time specified in the time-lock has passed" by + (time >= tx.inputs.filterIsInstance().first().validFrom) + } + } + } + data class State( + val validFrom: Instant + ) : ContractState { + override val participants: List + get() = throw UnsupportedOperationException() + override val contract: Contract = TEST_TIMELOCK_ID + } + interface Commands : CommandData { + class Issue : TypeOnlyCommandData(), Commands + class Exit : TypeOnlyCommandData(), Commands + } + } + + @Test + fun trivial() { + // A transaction containing an input state that is encumbered must fail if the encumbrance is missing. + assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { + transaction { + input { encumberedState } + output { unencumberedState } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + this.verifies() + } + } + // A transaction containing an input state that is encumbered must fail if the encumbrance is not in the correct position. + assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { + ledger { + unverifiedTransaction { + output("state encumbered by 5pm time-lock") { encumberedState } + output { unencumberedState } + output("5pm time-lock") { FIVE_PM_TIMELOCK } + } + transaction { + input("state encumbered by 5pm time-lock") + input("5pm time-lock") + output { stateWithNewOwner } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + command(DUMMY_PUBKEY_1) { TestTimeLock.Commands.Exit() } + timestamp(FIVE_PM) + this.verifies() + } + } + } + // A transaction containing an input state that is encumbered must fail if the encumbrance is not in the correct transaction. + assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { + ledger { + unverifiedTransaction { + output("state encumbered by 5pm time-lock") { encumberedState } + output { unencumberedState } + } + unverifiedTransaction { + output("5pm time-lock") { FIVE_PM_TIMELOCK } + } + transaction { + input("state encumbered by 5pm time-lock") + input("5pm time-lock") + output { stateWithNewOwner } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + command(DUMMY_PUBKEY_1) { TestTimeLock.Commands.Exit() } + timestamp(FIVE_PM) + this.verifies() + } + } + } + // A transaction with an input state that is encumbered must succeed if the rules of the encumbrance are met. + ledger { + unverifiedTransaction { + output("state encumbered by 5pm time-lock") { encumberedState } + output("5pm time-lock") { FIVE_PM_TIMELOCK } + } + // Un-encumber the output if the time of the transaction is later than the timelock. + transaction { + input("state encumbered by 5pm time-lock") + input("5pm time-lock") + output { stateWithNewOwner } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + command(DUMMY_PUBKEY_1) { TestTimeLock.Commands.Exit() } + timestamp(FIVE_PM) + this.verifies() + } + } + // A transaction with an input state that is encumbered must fail if the rules of the encumbrance are not met. + ledger { + unverifiedTransaction { + output("state encumbered by 5pm time-lock") { encumberedState } + output("5pm time-lock") { FIVE_PM_TIMELOCK } + } + // The time of the transaction is earlier than the time specified in the encumbering timelock. + transaction { + input("state encumbered by 5pm time-lock") + input("5pm time-lock") + output { stateWithNewOwner } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + command(DUMMY_PUBKEY_1) { TestTimeLock.Commands.Exit() } + timestamp(FOUR_PM) + this `fails with` "the time specified in the time-lock has passed" + } + } + } +} \ No newline at end of file From 2c7d6fc0534db879674ddff3fda76ffe9c3f270c Mon Sep 17 00:00:00 2001 From: jamescarlyle Date: Thu, 18 Aug 2016 20:39:34 +0100 Subject: [PATCH 02/10] Encumbrances implemented by reference to an index of an output state --- .../kotlin/com/r3corda/core/contracts/TransactionVerification.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt index 680ec59a53..3c7fbbbc8b 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt @@ -99,7 +99,6 @@ sealed class TransactionVerificationException(val tx: LedgerTransaction, cause: class InvalidNotaryChange(tx: LedgerTransaction) : TransactionVerificationException(tx, null) class NotaryChangeInWrongTransactionType(tx: LedgerTransaction, val outputNotary: Party) : TransactionVerificationException(tx, null) { override fun toString(): String = "Found unexpected notary change in transaction. Tx notary: ${tx.notary}, found: ${outputNotary}" - class TransactionMissingEncumbranceException(tx: LedgerTransaction) : TransactionVerificationException(tx, null) } class TransactionMissingEncumbranceException(tx: LedgerTransaction) : TransactionVerificationException(tx, null) } From b4be27080c11c23e4c51de7b371a5ea7eee6221a Mon Sep 17 00:00:00 2001 From: jamescarlyle Date: Thu, 18 Aug 2016 20:58:34 +0100 Subject: [PATCH 03/10] Encumbrances implemented by reference to an index of an output state --- .../java/com/r3corda/contracts/asset/CashTestsJava.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/src/test/java/com/r3corda/contracts/asset/CashTestsJava.java b/contracts/src/test/java/com/r3corda/contracts/asset/CashTestsJava.java index c6e1f874ef..c4136345ac 100644 --- a/contracts/src/test/java/com/r3corda/contracts/asset/CashTestsJava.java +++ b/contracts/src/test/java/com/r3corda/contracts/asset/CashTestsJava.java @@ -14,8 +14,8 @@ import static com.r3corda.core.testing.CoreTestUtils.*; public class CashTestsJava { private final OpaqueBytes defaultRef = new OpaqueBytes(new byte[]{1}); private final PartyAndReference defaultIssuer = getMEGA_CORP().ref(defaultRef); - private final Cash.State inState = new Cash.State(issuedBy(DOLLARS(1000), defaultIssuer), getDUMMY_PUBKEY_1()); - private final Cash.State outState = new Cash.State(inState.getAmount(), getDUMMY_PUBKEY_2()); + private final Cash.State inState = new Cash.State(issuedBy(DOLLARS(1000), defaultIssuer), getDUMMY_PUBKEY_1(), null); + private final Cash.State outState = new Cash.State(inState.getAmount(), getDUMMY_PUBKEY_2(), null); @Test public void trivial() { @@ -25,7 +25,7 @@ public class CashTestsJava { tx.failsWith("the amounts balance"); tx.tweak(tw -> { - tw.output(new Cash.State(issuedBy(DOLLARS(2000), defaultIssuer), getDUMMY_PUBKEY_2())); + tw.output(new Cash.State(issuedBy(DOLLARS(2000), defaultIssuer), getDUMMY_PUBKEY_2(), null)); return tw.failsWith("the amounts balance"); }); From fec2134555a70557b3a1366ce1be14b7b87a1f40 Mon Sep 17 00:00:00 2001 From: jamescarlyle Date: Fri, 19 Aug 2016 12:42:09 +0100 Subject: [PATCH 04/10] Updated comment on why the encumbrance is an index (Integer). --- .../com/r3corda/core/contracts/Structures.kt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt index fcbc5ebac1..0a5e079fe5 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt @@ -112,8 +112,18 @@ interface ContractState { */ val participants: List - /** The encumbrance state, if present, forces additional controls over this state, since the encumbrance state contract - * will also be verified. + /** + * All contract states may be _encumbered_ by up to one other state. + * + * The encumbrance state, if present, forces additional controls over this state, since the encumbrance state contract + * will also be verified during the execution of the transaction. For example, a contract state could be encumbered + * with a time-lock contract state; the state is then only processable in a transaction that verifies that the time + * specified in the encumbrance time-lock has passed. + * + * The encumbered state refers to another by index, and the referred encumbrance state + * is an output state in a particular position on the same transaction that created the encumbered state. An alternative + * would be encumber by reference to a StateRef., which would allow the specification of encumbrance by a state created + * in a prior transaction. */ val encumbrance: Int? get() = null } From 6ba301b6b825697b1157693b2541a3371975cc9e Mon Sep 17 00:00:00 2001 From: jamescarlyle Date: Fri, 19 Aug 2016 17:45:25 +0100 Subject: [PATCH 05/10] Updated based on feedback to check that the encumbered state does not refer to itself as the encumbrance. --- .../core/contracts/TransactionTypes.kt | 12 +++++++- .../contracts/TransactionEncumbranceTests.kt | 29 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt index 994f1e2de6..c7ead96939 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt @@ -81,11 +81,21 @@ sealed class TransactionType { // Validate that all encumbrances exist within the set of input states. tx.inputs.filter { it.state.data.encumbrance != null }.forEach { encumberedInput -> - if (tx.inputs.none { it.ref.txhash == encumberedInput.ref.txhash && it.ref.index == encumberedInput.state.data.encumbrance }) { + if (tx.inputs.none { it.ref.txhash == encumberedInput.ref.txhash && + it.ref.index == encumberedInput.state.data.encumbrance }) { throw TransactionVerificationException.TransactionMissingEncumbranceException(tx) } } + // Check that an encumbered state does not refer to itself as the encumbrance, and that the number of outputs + // can contain the encumbrance. + tx.outputs.forEachIndexed { i, it -> + if (it.data.encumbrance != null) { + if (it.data.encumbrance == i || it.data.encumbrance!! >= tx.outputs.size) { + throw TransactionVerificationException.TransactionMissingEncumbranceException(tx) + } + } + } } override fun getRequiredSigners(tx: LedgerTransaction) = tx.commands.flatMap { it.signers }.toSet() diff --git a/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt index 87b6d1187b..b6f1a52c9f 100644 --- a/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt +++ b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt @@ -67,6 +67,35 @@ class TransactionEncumbranceTests { this.verifies() } } + // An encumbered state must not be encumbered by itself. + assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { + transaction { + input { unencumberedState } + input { unencumberedState } + output { unencumberedState } + // The encumbered state refers to an encumbrance in position 1, so what follows is wrong. + output { encumberedState } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + this.verifies() + } + } + // An encumbered state must not reference an index greater than the size of the output states. + assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { + transaction { + input { unencumberedState } + input { unencumberedState } + output { unencumberedState } + // The encumbered state refers to an encumbrance in position 1, so what follows is wrong. + output { encumberedState } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + this.verifies() + } + } + + } + + @Test + fun testEncumbranceEffects() { // A transaction containing an input state that is encumbered must fail if the encumbrance is not in the correct position. assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { ledger { From ee65d4490b8e3e0ea1624f33c3df6e51c88ba744 Mon Sep 17 00:00:00 2001 From: jamescarlyle Date: Fri, 19 Aug 2016 17:49:53 +0100 Subject: [PATCH 06/10] Updated based on feedback to check that the encumbered state does not refer to itself as the encumbrance. --- .../r3corda/core/contracts/TransactionEncumbranceTests.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt index b6f1a52c9f..6102ad625d 100644 --- a/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt +++ b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt @@ -58,7 +58,7 @@ class TransactionEncumbranceTests { @Test fun trivial() { - // A transaction containing an input state that is encumbered must fail if the encumbrance is missing. + // A transaction containing an input state that is encumbered must fail if the encumbrance is missing on the inputs. assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { transaction { input { encumberedState } @@ -83,9 +83,7 @@ class TransactionEncumbranceTests { assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { transaction { input { unencumberedState } - input { unencumberedState } - output { unencumberedState } - // The encumbered state refers to an encumbrance in position 1, so what follows is wrong. + // The encumbered state refers to an encumbrance in position 1, so there should be at least 2 outputs. output { encumberedState } command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } this.verifies() From cdb2c3efa63ee131022da067e7ead895732d73f5 Mon Sep 17 00:00:00 2001 From: jamescarlyle Date: Tue, 6 Sep 2016 17:56:01 +0100 Subject: [PATCH 07/10] updated following review --- .../com/r3corda/core/contracts/Structures.kt | 7 +- .../core/contracts/TransactionTypes.kt | 20 +-- .../core/contracts/TransactionVerification.kt | 9 +- .../contracts/TransactionEncumbranceTests.kt | 118 ++++++++---------- docs/build/html/.buildinfo | 2 +- docs/build/html/_sources/index.txt | 4 +- .../html/_sources/protocol-state-machines.txt | 104 ++++++++++++++- .../_sources/tutorial-contract-clauses.txt | 33 +++-- .../build/html/_sources/tutorial-contract.txt | 64 ++++++++++ docs/build/html/_static/basic.css | 4 - docs/build/html/index.html | 4 +- docs/build/html/protocol-state-machines.html | 91 ++++++++++++++ docs/build/html/searchindex.js | 2 +- .../build/html/tutorial-contract-clauses.html | 33 +++-- docs/build/html/tutorial-contract.html | 53 ++++++++ docs/source/tutorial-contract.rst | 64 ++++++++++ 16 files changed, 489 insertions(+), 123 deletions(-) diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt index 0a5e079fe5..8fc83a7e72 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt @@ -122,8 +122,11 @@ interface ContractState { * * The encumbered state refers to another by index, and the referred encumbrance state * is an output state in a particular position on the same transaction that created the encumbered state. An alternative - * would be encumber by reference to a StateRef., which would allow the specification of encumbrance by a state created - * in a prior transaction. + * implementation would be encumber by reference to a StateRef., which would allow the specification of encumbrance + * by a state created in a prior transaction. + * + * Note that an encumbered state that is being consumed must have its encumbrance consumed in the same transaction, + * otherwise the transaction is not valid. */ val encumbrance: Int? get() = null } diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt index c7ead96939..68620ff439 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionTypes.kt @@ -83,17 +83,21 @@ sealed class TransactionType { encumberedInput -> if (tx.inputs.none { it.ref.txhash == encumberedInput.ref.txhash && it.ref.index == encumberedInput.state.data.encumbrance }) { - throw TransactionVerificationException.TransactionMissingEncumbranceException(tx) + throw TransactionVerificationException.TransactionMissingEncumbranceException( + tx, encumberedInput.state.data.encumbrance!!, + TransactionVerificationException.Direction.INPUT + ) } } - // Check that an encumbered state does not refer to itself as the encumbrance, and that the number of outputs - // can contain the encumbrance. - tx.outputs.forEachIndexed { i, it -> - if (it.data.encumbrance != null) { - if (it.data.encumbrance == i || it.data.encumbrance!! >= tx.outputs.size) { - throw TransactionVerificationException.TransactionMissingEncumbranceException(tx) - } + // Check that, in the outputs, an encumbered state does not refer to itself as the encumbrance, + // and that the number of outputs can contain the encumbrance. + for ((i, output) in tx.outputs.withIndex() ) { + val encumbranceIndex = output.data.encumbrance ?: continue + if (encumbranceIndex == i || encumbranceIndex >= tx.outputs.size) { + throw TransactionVerificationException.TransactionMissingEncumbranceException( + tx, encumbranceIndex, + TransactionVerificationException.Direction.OUTPUT) } } } diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt index 3c7fbbbc8b..17a1dba67e 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionVerification.kt @@ -100,5 +100,12 @@ sealed class TransactionVerificationException(val tx: LedgerTransaction, cause: class NotaryChangeInWrongTransactionType(tx: LedgerTransaction, val outputNotary: Party) : TransactionVerificationException(tx, null) { override fun toString(): String = "Found unexpected notary change in transaction. Tx notary: ${tx.notary}, found: ${outputNotary}" } - class TransactionMissingEncumbranceException(tx: LedgerTransaction) : TransactionVerificationException(tx, null) + class TransactionMissingEncumbranceException(tx: LedgerTransaction, val missing: Int, val inOut: Direction) : TransactionVerificationException(tx, null) { + override val message: String? + get() = "Missing required encumbrance ${missing} in ${inOut}" + } + enum class Direction { + INPUT, + OUTPUT + } } diff --git a/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt index 6102ad625d..9f67246a61 100644 --- a/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt +++ b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt @@ -13,8 +13,7 @@ import kotlin.test.assertFailsWith val TEST_TIMELOCK_ID = TransactionEncumbranceTests.TestTimeLock() class TransactionEncumbranceTests { - val defaultRef = OpaqueBytes(ByteArray(1, {1})) - val defaultIssuer = MEGA_CORP.ref(defaultRef) + val defaultIssuer = MEGA_CORP.ref(1) val encumberedState = Cash.State( amount = 1000.DOLLARS `issued by` defaultIssuer, owner = DUMMY_PUBKEY_1, @@ -34,13 +33,10 @@ class TransactionEncumbranceTests { override val legalContractReference = SecureHash.sha256("TestTimeLock") override fun verify(tx: TransactionForContract) { val timestamp: Timestamp? = tx.timestamp - val timeLockCommand = tx.commands.select().first() - if (timeLockCommand.value is TestTimeLock.Commands.Exit) { - val time = timestamp?.before ?: throw IllegalArgumentException("Transactions containing time-locks must be timestamped") - requireThat { - "the time specified in the time-lock has passed" by - (time >= tx.inputs.filterIsInstance().first().validFrom) - } + val time = timestamp?.before ?: throw IllegalArgumentException("Transactions containing time-locks must be timestamped") + requireThat { + "the time specified in the time-lock has passed" by + (time >= tx.inputs.filterIsInstance().single().validFrom) } } data class State( @@ -50,10 +46,6 @@ class TransactionEncumbranceTests { get() = throw UnsupportedOperationException() override val contract: Contract = TEST_TIMELOCK_ID } - interface Commands : CommandData { - class Issue : TypeOnlyCommandData(), Commands - class Exit : TypeOnlyCommandData(), Commands - } } @Test @@ -68,26 +60,22 @@ class TransactionEncumbranceTests { } } // An encumbered state must not be encumbered by itself. - assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { - transaction { - input { unencumberedState } - input { unencumberedState } - output { unencumberedState } - // The encumbered state refers to an encumbrance in position 1, so what follows is wrong. - output { encumberedState } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } - this.verifies() - } + transaction { + input { unencumberedState } + input { unencumberedState } + output { unencumberedState } + // The encumbered state refers to an encumbrance in position 1, so what follows is wrong. + output { encumberedState } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + this `fails with` "Missing required encumbrance 1 in OUTPUT" } // An encumbered state must not reference an index greater than the size of the output states. - assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { - transaction { - input { unencumberedState } - // The encumbered state refers to an encumbrance in position 1, so there should be at least 2 outputs. - output { encumberedState } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } - this.verifies() - } + transaction { + input { unencumberedState } + // The encumbered state refers to an encumbrance in position 1, so there should be at least 2 outputs. + output { encumberedState } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + this `fails with` "Missing required encumbrance 1 in OUTPUT" } } @@ -95,43 +83,37 @@ class TransactionEncumbranceTests { @Test fun testEncumbranceEffects() { // A transaction containing an input state that is encumbered must fail if the encumbrance is not in the correct position. - assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { - ledger { - unverifiedTransaction { - output("state encumbered by 5pm time-lock") { encumberedState } - output { unencumberedState } - output("5pm time-lock") { FIVE_PM_TIMELOCK } - } - transaction { - input("state encumbered by 5pm time-lock") - input("5pm time-lock") - output { stateWithNewOwner } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } - command(DUMMY_PUBKEY_1) { TestTimeLock.Commands.Exit() } - timestamp(FIVE_PM) - this.verifies() - } + ledger { + unverifiedTransaction { + output("state encumbered by 5pm time-lock") { encumberedState } + output { unencumberedState } + output("5pm time-lock") { FIVE_PM_TIMELOCK } + } + transaction { + input("state encumbered by 5pm time-lock") + input("5pm time-lock") + output { stateWithNewOwner } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + timestamp(FIVE_PM) + this `fails with` "Missing required encumbrance 1 in INPUT" } } // A transaction containing an input state that is encumbered must fail if the encumbrance is not in the correct transaction. - assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { - ledger { - unverifiedTransaction { - output("state encumbered by 5pm time-lock") { encumberedState } - output { unencumberedState } - } - unverifiedTransaction { - output("5pm time-lock") { FIVE_PM_TIMELOCK } - } - transaction { - input("state encumbered by 5pm time-lock") - input("5pm time-lock") - output { stateWithNewOwner } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } - command(DUMMY_PUBKEY_1) { TestTimeLock.Commands.Exit() } - timestamp(FIVE_PM) - this.verifies() - } + ledger { + unverifiedTransaction { + output("state encumbered by 5pm time-lock") { encumberedState } + output { unencumberedState } + } + unverifiedTransaction { + output("5pm time-lock") { FIVE_PM_TIMELOCK } + } + transaction { + input("state encumbered by 5pm time-lock") + input("5pm time-lock") + output { stateWithNewOwner } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + timestamp(FIVE_PM) + this `fails with` "Missing required encumbrance 1 in INPUT" } } // A transaction with an input state that is encumbered must succeed if the rules of the encumbrance are met. @@ -144,9 +126,8 @@ class TransactionEncumbranceTests { transaction { input("state encumbered by 5pm time-lock") input("5pm time-lock") - output { stateWithNewOwner } + output { unencumberedState } command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } - command(DUMMY_PUBKEY_1) { TestTimeLock.Commands.Exit() } timestamp(FIVE_PM) this.verifies() } @@ -161,9 +142,8 @@ class TransactionEncumbranceTests { transaction { input("state encumbered by 5pm time-lock") input("5pm time-lock") - output { stateWithNewOwner } + output { unencumberedState } command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } - command(DUMMY_PUBKEY_1) { TestTimeLock.Commands.Exit() } timestamp(FOUR_PM) this `fails with` "the time specified in the time-lock has passed" } diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo index d958f98faa..b7417346d2 100644 --- a/docs/build/html/.buildinfo +++ b/docs/build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 02da61908148262295ef57918c434b8d +config: 0e8996317ea97eb6f5837df02a05a760 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/_sources/index.txt b/docs/build/html/_sources/index.txt index 6b1aa7cd0b..46da547db0 100644 --- a/docs/build/html/_sources/index.txt +++ b/docs/build/html/_sources/index.txt @@ -1,7 +1,9 @@ Welcome to the Corda repository! ================================ -This documentation describes the prototype of a proposed architecture for distributed ledgers. +This documentation describes Corda, a proposed architecture for distributed ledgers, the vision for which is outlined in the `Corda Introductory Whitepaper`_. + +.. _`Corda Introductory Whitepaper`: _static/corda-introductory-whitepaper.pdf The goal of this prototype is to explore fundamentally better designs for distributed ledgers than what presently exists on the market, tailor made for the needs of the financial industry. We are attempting to prove or disprove the diff --git a/docs/build/html/_sources/protocol-state-machines.txt b/docs/build/html/_sources/protocol-state-machines.txt index 8667a91c80..bfcb0a9ca4 100644 --- a/docs/build/html/_sources/protocol-state-machines.txt +++ b/docs/build/html/_sources/protocol-state-machines.txt @@ -559,4 +559,106 @@ the sub-protocol to have the tracker it will use be passed in as a parameter. Th and linked ahead of time. In future, the progress tracking framework will become a vital part of how exceptions, errors, and other faults are -surfaced to human operators for investigation and resolution. \ No newline at end of file +surfaced to human operators for investigation and resolution. + +Unit testing +------------ + +A protocol can be a fairly complex thing that interacts with many services and other parties over the network. That +means unit testing one requires some infrastructure to provide lightweight mock implementations. The MockNetwork +provides this testing infrastructure layer; you can find this class in the node module + +A good example to examine for learning how to unit test protocols is the ``ResolveTransactionsProtocol`` tests. This +protocol takes care of downloading and verifying transaction graphs, with all the needed dependencies. We start +with this basic skeleton: + +.. container:: codeset + + .. sourcecode:: kotlin + + class ResolveTransactionsProtocolTest { + lateinit var net: MockNetwork + lateinit var a: MockNetwork.MockNode + lateinit var b: MockNetwork.MockNode + lateinit var notary: Party + + @Before + fun setup() { + net = MockNetwork() + val nodes = net.createSomeNodes() + a = nodes.partyNodes[0] + b = nodes.partyNodes[1] + notary = nodes.notaryNode.info.identity + net.runNetwork() + } + + @After + fun tearDown() { + net.stopNodes() + } + } + +We create a mock network in our ``@Before`` setup method and create a couple of nodes. We also record the identity +of the notary in our test network, which will come in handy later. We also tidy up when we're done. + +Next, we write a test case: + +.. container:: codeset + + .. sourcecode:: kotlin + + @Test + fun resolveFromTwoHashes() { + val (stx1, stx2) = makeTransactions() + val p = ResolveTransactionsProtocol(setOf(stx2.id), a.info.identity) + val future = b.services.startProtocol("resolve", p) + net.runNetwork() + val results = future.get() + assertEquals(listOf(stx1.id, stx2.id), results.map { it.id }) + assertEquals(stx1, b.storage.validatedTransactions.getTransaction(stx1.id)) + assertEquals(stx2, b.storage.validatedTransactions.getTransaction(stx2.id)) + } + +We'll take a look at the ``makeTransactions`` function in a moment. For now, it's enough to know that it returns two +``SignedTransaction`` objects, the second of which spends the first. Both transactions are known by node A +but not node B. + +The test logic is simple enough: we create the protocol, giving it node A's identity as the target to talk to. +Then we start it on node B and use the ``net.runNetwork()`` method to bounce messages around until things have +settled (i.e. there are no more messages waiting to be delivered). All this is done using an in memory message +routing implementation that is fast to initialise and use. Finally, we obtain the result of the protocol and do +some tests on it. We also check the contents of node B's database to see that the protocol had the intended effect +on the node's persistent state. + +Here's what ``makeTransactions`` looks like: + +.. container:: codeset + + .. sourcecode:: kotlin + + private fun makeTransactions(): Pair { + // Make a chain of custody of dummy states and insert into node A. + val dummy1: SignedTransaction = DummyContract.generateInitial(MEGA_CORP.ref(1), 0, notary).let { + it.signWith(MEGA_CORP_KEY) + it.signWith(DUMMY_NOTARY_KEY) + it.toSignedTransaction(false) + } + val dummy2: SignedTransaction = DummyContract.move(dummy1.tx.outRef(0), MINI_CORP_PUBKEY).let { + it.signWith(MEGA_CORP_KEY) + it.signWith(DUMMY_NOTARY_KEY) + it.toSignedTransaction() + } + a.services.recordTransactions(dummy1, dummy2) + return Pair(dummy1, dummy2) + } + +We're using the ``DummyContract``, a simple test smart contract which stores a single number in its states, along +with ownership and issuer information. You can issue such states, exit them and re-assign ownership (move them). +It doesn't do anything else. This code simply creates a transaction that issues a dummy state (the issuer is +``MEGA_CORP``, a pre-defined unit test identity), signs it with the test notary and MegaCorp keys and then +converts the builder to the final ``SignedTransaction``. It then does so again, but this time instead of issuing +it re-assigns ownership instead. The chain of two transactions is finally committed to node A by sending them +directly to the ``a.services.recordTransaction`` method (note that this method doesn't check the transactions are +valid). + +And that's it: you can explore the documentation for the `MockNode API `_ here. diff --git a/docs/build/html/_sources/tutorial-contract-clauses.txt b/docs/build/html/_sources/tutorial-contract-clauses.txt index db6e18a0c9..47948b0aef 100644 --- a/docs/build/html/_sources/tutorial-contract-clauses.txt +++ b/docs/build/html/_sources/tutorial-contract-clauses.txt @@ -10,7 +10,7 @@ Writing a contract using clauses This tutorial will take you through restructuring the commercial paper contract to use clauses. You should have already completed ":doc:`tutorial-contract`". -Clauses are essentially "mini-contracts" which contain verification logic, and are composed together to form +Clauses are essentially micro-contracts which contain independent verification logic, and are composed together to form a contract. With appropriate design, they can be made to be reusable, for example issuing contract state objects is generally the same for all fungible contracts, so a single issuance clause can be shared. This cuts down on scope for error, and improves consistency of behaviour. @@ -27,25 +27,24 @@ In the case of commercial paper, we have a "Grouping" outermost clause, which wi Commercial paper class ---------------------- -First we need to change the class from implementing ``Contract``, to extend ``ClauseVerifier``. This is an abstract -class which provides a verify() function for us, and requires we provide a property (``clauses``) for the clauses to test, -and a function (``extractCommands``) to extract the applicable commands from the transaction. This is important because -``ClauseVerifier`` checks that no commands applicable to the contract are left unprocessed at the end. The following -examples are trimmed to the modified class definition and added elements, for brevity: +To use the clause verification logic, the contract needs to call the ``verifyClauses()`` function, passing in the transaction, +a list of clauses to verify, and a collection of commands the clauses are expected to handle all of. This list of +commands is important because ``verifyClauses()`` checks that none of the commands are left unprocessed at the end, and +raises an error if they are. The following examples are trimmed to the modified class definition and added elements, for +brevity: .. container:: codeset .. sourcecode:: kotlin - class CommercialPaper : ClauseVerifier { - override val legalContractReference: SecureHash = SecureHash.sha256("https://en.wikipedia.org/wiki/Commercial_paper"); + class CommercialPaper : Contract { + override val legalContractReference: SecureHash = SecureHash.sha256("https://en.wikipedia.org/wiki/Commercial_paper") - override val clauses: List - get() = throw UnsupportedOperationException("not implemented") - - override fun extractCommands(tx: TransactionForContract): List> + private fun extractCommands(tx: TransactionForContract): List> = tx.commands.select() + override fun verify(tx: TransactionForContract) = verifyClauses(tx, listOf(Clauses.Group()), extractCommands(tx)) + .. sourcecode:: java public class CommercialPaper implements Contract { @@ -54,11 +53,6 @@ examples are trimmed to the modified class definition and added elements, for br return SecureHash.Companion.sha256("https://en.wikipedia.org/wiki/Commercial_paper"); } - @Override - public List getClauses() { - throw UnsupportedOperationException("not implemented"); - } - @Override public Collection> extractCommands(@NotNull TransactionForContract tx) { return tx.getCommands() @@ -67,6 +61,11 @@ examples are trimmed to the modified class definition and added elements, for br .collect(Collectors.toList()); } + @Override + public void verify(@NotNull TransactionForContract tx) throws IllegalArgumentException { + ClauseVerifier.verifyClauses(tx, Collections.singletonList(new Clause.Group()), extractCommands(tx)); + } + Clauses ------- diff --git a/docs/build/html/_sources/tutorial-contract.txt b/docs/build/html/_sources/tutorial-contract.txt index f149a8a433..21ba5951ae 100644 --- a/docs/build/html/_sources/tutorial-contract.txt +++ b/docs/build/html/_sources/tutorial-contract.txt @@ -845,6 +845,70 @@ be implemented once in a separate contract, with the controlling data being held Future versions of the prototype will explore these concepts in more depth. +Encumbrances +------------ + +All contract states may be *encumbered* by up to one other state, which we call an **encumbrance**. + +The encumbrance state, if present, forces additional controls over the encumbered state, since the encumbrance state contract +will also be verified during the execution of the transaction. For example, a contract state could be encumbered +with a time-lock contract state; the state is then only processable in a transaction that verifies that the time +specified in the encumbrance time-lock has passed. + +The encumbered state refers to its encumbrance by index, and the referred encumbrance state +is an output state in a particular position on the same transaction that created the encumbered state. Note that an +encumbered state that is being consumed must have its encumbrance consumed in the same transaction, otherwise the +transaction is not valid. + +The encumbrance reference is optional in the ``ContractState`` interface: + +.. container:: codeset + + .. sourcecode:: kotlin + + val encumbrance: Int? get() = null + + .. sourcecode:: java + + @Nullable + @Override + public Integer getEncumbrance() { + return null; + } + + +The time-lock contract mentioned above can be implemented very simply: + +.. container:: codeset + + .. sourcecode:: kotlin + + class TestTimeLock : Contract { + ... + override fun verify(tx: TransactionForContract) { + val timestamp: Timestamp? = tx.timestamp + ... + requireThat { + "the time specified in the time-lock has passed" by + (time >= tx.inputs.filterIsInstance().single().validFrom) + } + } + ... + } + +We can then set up an encumbered state: + +.. container:: codeset + + .. sourcecode:: kotlin + + val encumberedState = Cash.State(amount = 1000.DOLLARS `issued by` defaultIssuer, owner = DUMMY_PUBKEY_1, encumbrance = 1) + val fourPmTimelock = TestTimeLock.State(Instant.parse("2015-04-17T16:00:00.00Z")) + +When we construct a transaction that generates the encumbered state, we must place the encumbrance in the corresponding output +position of that transaction. And when we subsequently consume that encumbered state, the same encumbrance state must be +available somewhere within the input set of states. + Clauses ------- diff --git a/docs/build/html/_static/basic.css b/docs/build/html/_static/basic.css index 65dfd7dfda..2b513f0c96 100644 --- a/docs/build/html/_static/basic.css +++ b/docs/build/html/_static/basic.css @@ -85,10 +85,6 @@ div.sphinxsidebar #searchbox input[type="text"] { width: 170px; } -div.sphinxsidebar #searchbox input[type="submit"] { - width: 30px; -} - img { border: 0; max-width: 100%; diff --git a/docs/build/html/index.html b/docs/build/html/index.html index 92efb3d0f0..9148dd2e07 100644 --- a/docs/build/html/index.html +++ b/docs/build/html/index.html @@ -164,7 +164,7 @@

Welcome to the Corda repository!

-

This documentation describes the prototype of a proposed architecture for distributed ledgers.

+

This documentation describes Corda, a proposed architecture for distributed ledgers, the vision for which is outlined in the Corda Introductory Whitepaper.

The goal of this prototype is to explore fundamentally better designs for distributed ledgers than what presently exists on the market, tailor made for the needs of the financial industry. We are attempting to prove or disprove the following hypothesis:

@@ -275,6 +275,7 @@ following hypothesis:

  • How to test your contract
  • Adding a generation API to your contract
  • Non-asset-oriented based smart contracts
  • +
  • Encumbrances
  • Clauses
  • @@ -299,6 +300,7 @@ following hypothesis:

  • Implementing the seller
  • Implementing the buyer
  • Progress tracking
  • +
  • Unit testing
  • Writing oracle services
  • Writing oracle services
  • @@ -696,6 +697,96 @@ and linked ahead of time.

    In future, the progress tracking framework will become a vital part of how exceptions, errors, and other faults are surfaced to human operators for investigation and resolution.

    +
    +

    Unit testing

    +

    A protocol can be a fairly complex thing that interacts with many services and other parties over the network. That +means unit testing one requires some infrastructure to provide lightweight mock implementations. The MockNetwork +provides this testing infrastructure layer; you can find this class in the node module

    +

    A good example to examine for learning how to unit test protocols is the ResolveTransactionsProtocol tests. This +protocol takes care of downloading and verifying transaction graphs, with all the needed dependencies. We start +with this basic skeleton:

    +
    +
    class ResolveTransactionsProtocolTest {
    +    lateinit var net: MockNetwork
    +    lateinit var a: MockNetwork.MockNode
    +    lateinit var b: MockNetwork.MockNode
    +    lateinit var notary: Party
    +
    +    @Before
    +    fun setup() {
    +        net = MockNetwork()
    +        val nodes = net.createSomeNodes()
    +        a = nodes.partyNodes[0]
    +        b = nodes.partyNodes[1]
    +        notary = nodes.notaryNode.info.identity
    +        net.runNetwork()
    +    }
    +
    +    @After
    +    fun tearDown() {
    +        net.stopNodes()
    +    }
    +}
    +
    +
    +
    +

    We create a mock network in our @Before setup method and create a couple of nodes. We also record the identity +of the notary in our test network, which will come in handy later. We also tidy up when we’re done.

    +

    Next, we write a test case:

    +
    +
    @Test
    +fun resolveFromTwoHashes() {
    +    val (stx1, stx2) = makeTransactions()
    +    val p = ResolveTransactionsProtocol(setOf(stx2.id), a.info.identity)
    +    val future = b.services.startProtocol("resolve", p)
    +    net.runNetwork()
    +    val results = future.get()
    +    assertEquals(listOf(stx1.id, stx2.id), results.map { it.id })
    +    assertEquals(stx1, b.storage.validatedTransactions.getTransaction(stx1.id))
    +    assertEquals(stx2, b.storage.validatedTransactions.getTransaction(stx2.id))
    +}
    +
    +
    +
    +

    We’ll take a look at the makeTransactions function in a moment. For now, it’s enough to know that it returns two +SignedTransaction objects, the second of which spends the first. Both transactions are known by node A +but not node B.

    +

    The test logic is simple enough: we create the protocol, giving it node A’s identity as the target to talk to. +Then we start it on node B and use the net.runNetwork() method to bounce messages around until things have +settled (i.e. there are no more messages waiting to be delivered). All this is done using an in memory message +routing implementation that is fast to initialise and use. Finally, we obtain the result of the protocol and do +some tests on it. We also check the contents of node B’s database to see that the protocol had the intended effect +on the node’s persistent state.

    +

    Here’s what makeTransactions looks like:

    +
    +
    private fun makeTransactions(): Pair<SignedTransaction, SignedTransaction> {
    +    // Make a chain of custody of dummy states and insert into node A.
    +    val dummy1: SignedTransaction = DummyContract.generateInitial(MEGA_CORP.ref(1), 0, notary).let {
    +        it.signWith(MEGA_CORP_KEY)
    +        it.signWith(DUMMY_NOTARY_KEY)
    +        it.toSignedTransaction(false)
    +    }
    +    val dummy2: SignedTransaction = DummyContract.move(dummy1.tx.outRef(0), MINI_CORP_PUBKEY).let {
    +        it.signWith(MEGA_CORP_KEY)
    +        it.signWith(DUMMY_NOTARY_KEY)
    +        it.toSignedTransaction()
    +    }
    +    a.services.recordTransactions(dummy1, dummy2)
    +    return Pair(dummy1, dummy2)
    +}
    +
    +
    +
    +

    We’re using the DummyContract, a simple test smart contract which stores a single number in its states, along +with ownership and issuer information. You can issue such states, exit them and re-assign ownership (move them). +It doesn’t do anything else. This code simply creates a transaction that issues a dummy state (the issuer is +MEGA_CORP, a pre-defined unit test identity), signs it with the test notary and MegaCorp keys and then +converts the builder to the final SignedTransaction. It then does so again, but this time instead of issuing +it re-assigns ownership instead. The chain of two transactions is finally committed to node A by sending them +directly to the a.services.recordTransaction method (note that this method doesn’t check the transactions are +valid).

    +

    And that’s it: you can explore the documentation for the MockNode API here.

    +
    diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js index 7a26fc66ac..09ef6743f9 100644 --- a/docs/build/html/searchindex.js +++ b/docs/build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({envversion:47,filenames:["building-the-docs","codestyle","consensus","contract-catalogue","contract-irs","data-model","event-scheduling","getting-set-up","index","inthebox","messaging","node-administration","oracles","protocol-state-machines","release-notes","release-process","running-the-demos","transaction-data-types","tutorial-contract","tutorial-contract-clauses","tutorial-test-dsl","visualiser","where-to-start"],objects:{},objnames:{},objtypes:{},terms:{"0_xx":7,"1mb":13,"8u45":7,"_before_":13,"_do_":13,"_foo":1,"_is_":13,"_mbeans_":11,"abstract":[5,13,14,18,19],"boolean":[5,18],"break":[12,15,18],"byte":[1,5,9,13,20],"case":[1,2,5,10,12,13,14,17,18,19],"catch":[1,7,13],"class":[],"default":[1,3,7,9,13,14,16,18],"enum":14,"export":[11,13,22],"final":[2,4,5,7,10,13,18,19,20],"float":[3,4,6,9],"function":[],"import":[1,5,6,7,10,13,14,15,18,19,20,22],"instanceof":[18,19],"int":[1,2,18],"long":[1,3,5,6,10,13,18],"new":[1,2,4,5,7,8,9,10,11,13,14,15,17,18,19,20,22],"null":[6,12,18],"public":[1,5,9,10,11,12,13,17,18,19,20],"return":[1,2,4,6,10,11,12,13,14,18,19,20,22],"short":[6,10,15,18],"static":[5,12,13,18,20,22],"super":1,"switch":[9,13,14,18],"throw":[1,2,12,13,18,19],"transient":13,"true":[5,10,12,18,21],"try":[1,5,13,16,18,21,22],"var":18,"void":[18,20],"while":[17,18],abil:[5,10],abl:[2,5,10,12,14,16],abort:2,about:[],abov:[1,4,5,10,13,18,19,20],absolut:5,abstractnod:12,accept:[1,2,3,5,10,13,18],acceptablepric:13,access:[1,5,7,10,11,12,13,18],accid:13,accident:1,accompani:1,accord:22,accordingli:[10,19],account:[5,17],accrual:4,accur:12,accuraci:5,achiev:[2,5,10],ack:14,acknowledg:13,across:[3,5,13,14],act:[2,5,10,12,13],action:[6,18,22],activ:[4,6,16],actor:[1,5,13],actual:[4,7,10,12,13,18,20],adapt:[1,12,13],add:[1,10,11,13,17,18,19,20],addarg:18,addcommand:13,addinputst:[13,18],addit:[1,2,5,17,18],addition:[12,13,15],addmessagehandl:[10,14],addoutputst:[13,18],address:[2,5,10,13,16,18],adjust:[1,4,15,22],admin:7,administr:[],advanc:[3,4,8],advantag:5,adventur:22,advertis:12,advertisedservic:2,advic:15,affect:[7,12],affection:18,affinityexecutor:1,afraid:1,after:[2,3,4,5,6,7,9,12,13,18,19,21],again:[4,5,10,12,13,16,18],against:[4,5,6,13,18,19],agent:11,aggreg:[5,18,19],agre:[4,6,13],agreement:[4,5,17],ahead:13,aim:[1,5],albeit:14,albertsen:14,algorithm:[5,9,14,18,21],alic:[18,21],aliceaddr:10,alicegetsback:[18,21],alicenod:10,aliv:13,all:[0,1,2,3,4,5,7,10,11,12,13,14,15,16,18,19,22],allevi:2,allow:[1,2,3,4,5,6,9,12,13,17,18,20,22],allpossiblerecipi:10,almost:[13,18],along:[2,9,10,12,13,18],alreadi:[1,6,12,13,14,18,19,20],alright:13,also:[1,2,3,4,5,6,7,10,11,13,16,17,18,19,20,22],alt:18,alter:[13,18],altern:[0,1,11,17],although:[4,5,9,10,18,19,22],alwai:[1,5,6,11,13,18,19],amounnt:13,amount:[],amqp:[9,14],analysi:5,andresen:5,ani:[1,2,3,4,5,6,10,11,12,13,15,16,17,18,19,22],annot:[1,13,18],announc:15,anonym:5,anoth:[1,2,7,11,12,13,18,20],answer:[1,12],anticip:1,anybodi:5,anyon:[2,18],anyth:[2,5,10,12,13,18,19],anywher:[10,12,18],apach:[9,10],apart:2,api:[],app:[11,14,15,22],appear:18,append:11,appendix:8,appli:[1,3,4,5,18,19],applic:[5,12,19,22],applyfix:4,appoint:2,approach:[],appropri:[1,10,19],approv:[5,6,13],arbitrari:[1,5,12,13,18],arbitrarili:9,architectur:[8,12],area:[10,17],aren:[13,18,22],arg:[14,18,21],arguabl:12,argument:[1,5,10,13,18],aris:5,around:[5,10,12,13,14,15,17,18,21],arrai:[5,9,13],arrang:13,arraylist:19,arriv:[12,13],arrow:[4,7],artemi:9,articl:[2,5,6,10,12,13,22],artifact:18,ask:[1,13,18],aspect:[6,13,22],assembl:5,assemblesharedtx:13,asset:[],assetforsal:13,assetmismatchexcept:13,assettosel:13,assettypenam:13,assign:12,assist:[6,13,18,21],associ:[2,5,6,10,17,18],assum:[5,12,13,18],assumpt:13,atom:[5,12,13,16,18],attach:[],attack:2,attempt:[5,7,8,10,13],attent:13,attest:[2,12],attribut:1,audit:[5,13],authent:2,authenticatedobject:[17,18,19],author:[1,2,5,10,13,15,22],authoris:13,auto:[1,18],autom:[5,6,18,22],automat:[0,6,10,13,14,18,22],avail:[0,4,6,10,11,12,15,18],avoid:[1,5,13],awai:[5,13,16],awar:[1,13],awg:15,awkward:[1,13],axi:4,back:[1,5,12,13,17,18],backend:10,background:[1,5,10],backport:15,backtick:18,backward:[13,15],bad:[1,13,18,20],balanc:[2,3,5,18,20],banana:17,bananast:17,banco:14,band:13,bandwidth:1,bank:[4,5,14,17,22],bankrupt:18,bankruptci:[5,12],barreca:14,barrel:14,base:[],basi:[4,6,11],basic:[],bat:16,bbva:14,bear:[13,18],beauti:21,becaus:[1,5,7,10,11,12,13,17,18,19,20],becom:[1,4,5,6,13,15],been:[2,4,5,7,12,13,14,15,18],befor:[2,4,5,6,9,12,13,14,15,17,18],beforehand:16,begin:[1,5,16,18,22],behav:18,behaviour:[2,11,19,20],behind:[13,18],believ:14,below:[1,4,5,6,13,22],beneficiari:3,benefit:[2,13,18],best:[1,16,22],bet:12,better:[1,8,9,14,18,21],between:[1,4,5,6,10,12,13,14,15,16,17,18],beyond:[5,18],big:[1,5,13,14,18],bigdecim:12,bilater:[3,4,9,14],bill:18,bin:16,binari:[5,12],bind:[2,5,12],bip:5,bit:[13,18,20,21,22],bitbucket:7,bitcoinj:13,blah:1,blank:[1,18],block:[1,2,5,8,10,12,13,14,18],blockchain:[5,9,13],bloom:1,bloomfilt:1,blotter:16,blow:16,blue:[4,21],bob:18,bobaddr:10,bobnod:10,bodi:1,boil:5,bond:18,bookkeep:[9,18],boost:9,borrow:21,both:[2,3,4,5,9,10,12,13,16,18],bottom:13,bound:[12,13],bower:16,box:[9,22],branch:15,breach:5,bread:22,breadth:13,breviti:19,brief:14,briefli:[10,21],bring:5,broadcast:[5,10],broke:1,broken:18,browser:16,bug:[1,14,15],bugfix:15,bui:[13,22],builder:[14,18],built:[13,18],bulk:[5,19],bullet:1,bunch:[16,18],bundl:5,busi:[5,6,9,10,12,13,17,18,22],businesscalendar:17,butter:22,button:16,buyer:[],buyersessionid:13,bytearrai:10,bytecod:[5,13,18],cach:10,calcul:[4,6,13,17,18],calendar:[4,12,17],calibr:5,call:[1,2,4,5,9,10,11,13,14,15,18,20],callback:[1,10,13],caller:[2,18],came:13,camel:1,can:[0,1,2,3,4,5,6,7,9,10,11,12,13,14,16,17,18,19,20,21,22],cannot:[2,3,5,7,12,14,18],capabl:18,capit:1,capitan:0,captur:6,cardon:14,care:[1,5,10,12,13,20],carefulli:9,cash:[],cashkt:18,cashsigningpubkei:13,cashstat:13,caus:[1,18],center:18,certain:[1,9,14,18],certainti:2,cev:7,chain:[],chaincash:20,chaincashdoublespend:20,chaincashdoublespendfailswith:20,challeng:5,chanc:[1,13],chang:[],changenotari:2,channel:13,charact:1,charg:12,check:[],checkabl:12,checkdepend:13,checksufficientsignatur:[13,17],chf:17,child:13,children:13,childrenfor:13,choic:[1,2,5],choos:[2,7,18],chosen:[2,5],chronolog:6,chunk:[18,22],circl:21,claim:[5,9,18],clash:1,classpath:16,claus:[],clauseverifi:[18,19],clean:[13,14],cleanup:14,clear:[13,17],clearer:[10,13],clearli:1,click:[7,16,21],client:[2,11,12],clock:[6,12,16],clone:[1,7],close:[3,12],closer:2,closur:[1,20],cloud:11,cluster:2,cmd:[18,19],coars:5,code:[],codebas:[1,18],cognit:5,coin:5,collabor:14,colleagu:1,collect:[1,11,14,19],collector:[1,11,13,19],collis:1,colour:16,column:11,com:[0,7,14,16,19,20],combin:[5,8,18,19],come:[5,9,13,14,15],command:[],commanddata:[12,19],commerci:[],commercial_pap:[18,19],commercialpap:[3,9,18,19,21],commercialpaperlegaci:18,commercialpapertest:[18,21],commit:[2,13,15],commod:17,common:[4,5,13,14,17,18,20],commonleg:4,commonli:18,commun:[7,14],compani:12,companion:[13,18,19],compar:[5,10],compat:15,compel:2,complementari:6,complet:[5,6,10,13,14,16,17,18,19,20],complex:[1,3,5,17,18],complic:[13,18],compon:[6,10,14],compos:[13,14,17,18,19],compris:4,comput:[4,12,13],concept:[2,5,6,12,13,14,18],conceptu:13,concern:[5,13,18],conclus:[5,12],concurrenthashmap:1,condit:[2,12,13,20],config:11,configur:[7,11,13,16],confirm:[2,7,10],conflict:[2,5,8],confus:13,connect:[11,18],consid:[1,4,5,12,14,15,18],consist:[4,5,13,14,19],constant:[1,18],constantli:12,constraint:12,construct:[1,2,10,12,13,14,17,18,20,22],constructor:[6,12,18],consult:12,consum:[2,5,6,14],consumingtx:2,consumpt:[6,12],contact:[7,13],contain:[2,4,5,10,11,12,13,15,16,17,18,19,20,22],content:[1,2,5,6,7,10,11,12,18],context:[1,5,11,12,17],continu:[],contract:[],contractreject:20,contractst:[2,6,14,17,18,21],contractstateref:18,contrast:[5,12,13],contribut:17,control:[1,2,5,7,11,13,14,16,18,22],conveni:[1,5,18],convent:[4,13,19],convers:17,convert:[3,4,17,18],convinc:13,copi:[1,5,10,13,18,20,22],copyonwritearraylist:1,copyright:1,corda:[],cordapp:14,core:[3,10,14,17,18,19,20],corner:7,correct:[2,3,5,14,15,18,20],correctli:[5,12,14,18],correspond:18,correspondingli:1,cost:[12,18],could:[1,2,3,5,12,13,17,18],count:4,countabl:14,counter:[1,13],counterparti:[3,4],countri:[12,17],coupl:[12,13],cours:[11,12,18,22],cover:[2,3,5,12,13,17,18,22],cp_program_id:18,creat:[],createdummyir:4,createmessag:10,creation:[4,5,8,18],creator:12,credit:14,crisp:18,criteria:3,critic:[5,15],crop:5,curl:11,currenc:[3,4,9,14,17,18],current:[1,2,4,5,6,9,10,12,13,14,15,17,18,20,21],currentwallet:13,curv:4,custom:[2,11,14,16,17],customis:22,cut:[],cycl:1,dai:[4,6,11,12,15,17,18,21],daniel:14,danks:14,dashboard:11,data:[],databas:[5,9,13],dataset:4,date:[],dateoffset:14,daterollconvent:17,david:14,deadlin:17,deal:[1,12,16,17],dealstat:17,debt:3,debug:13,decd098666b9657314870e192ced0c3519c2c9d395507a238338f8d003929de9:11,decd:11,decentralis:12,decid:[7,12,18],decis:[2,5],declar:[1,10,18,20],dedic:1,defin:[1,2,5,9,10,11,12,13,14,17,18,19,20,21,22],definit:[2,13,17,18,19],delai:[4,12],delet:[1,5,13,14,18],deliber:[5,20],deliv:[3,10,17],deliveri:[9,10,13,16,18],demand:[5,17],demo:[],demonstr:[14,16,22],denial:2,denomin:9,dens:1,depend:[1,2,5,6,7,12,13,14,18,19],dependencytxid:13,deposit:[9,18,20],depth:18,deregist:10,deriv:[4,13,18],describ:[1,2,5,6,8,13,17,18],descript:1,deserv:15,design:[1,2,5,8,9,12,18,19,22],desir:[13,17,18],desktop:11,despit:[13,18],destin:10,destroi:[3,5,18],destroypaperatredempt:[18,21],destructur:18,detail:[],detect:1,determin:[3,4,6],develop:[1,5,9,10,13,14,15,16,18],devic:5,devis:5,diagram:[4,21],diamond:21,didn:[1,13,15,18],differ:[1,3,4,5,6,12,13,14,17,18,19,20],difficult:[10,13],digest:2,digit:[5,12,13,14,18],digitalsignatur:[2,12,13],direct:1,directli:[1,11,17,18],directori:[0,16,18,22],directthreadexecutor:1,dirti:18,disabl:17,disadvantag:5,discov:5,discuss:[5,10,17,18],disk:[13,14,17],disobei:12,disprov:8,disput:[2,4,18],disrupt:10,distinct:1,distinguish:18,distribut:[2,5,8,9,12,13],distrust:[2,13],divid:2,dlg:13,doc:[0,1,14,18],docker:11,docsit:[0,15],doe:[1,2,3,4,5,6,9,10,11,12,13,18,20,22],doesn:[1,2,5,7,10,11,12,13,16,18,20],dokka:0,dollar:[18,20,21],domain:[14,17,18,21],don:[1,5,7,9,10,13,15,18,19,20],done:[0,5,13,14,18],dot:4,doubl:[5,9,16,18],doubt:[1,9],down:[1,5,12,18,19],download:[],downsid:[1,5],drag:21,drive:[5,22],driven:16,driver:[14,22],drm:12,dsl:[14,18,20,21],due:[1,4,5,6,9,12,13,18,19],dummi:[3,18,20],dummy_cash_issu:20,dummy_pubkey_1:[18,20],dummy_pubkey_2:20,duplic:18,durat:[6,12,18],dure:[1,4,6,14],dynam:[14,18,22],each:[1,2,4,5,6,9,10,12,13,14,15,18,19,20,22],earli:[1,18,21,22],earliest:[4,6],eas:10,easi:[1,5,9,12,14,18],easier:[1,13,18],easiest:18,easili:[1,12,13,16],econom:4,ed25519:14,edit:7,editor:7,effect:[4,5,20],either:[1,2,3,4,5,12,13,18,19,20,22],elbonia:17,element:[1,5,19],elimin:9,els:[2,5,18,19],emb:[6,18],embed:[5,11,12],emit:18,empti:[14,18,20],emptyledg:20,enabl:18,encapsul:[1,17],enclos:1,encod:12,encount:9,encrypt:9,end:[1,4,9,12,13,15,19,22],endpoint:11,enforc:[1,5,18],enforceverifyorfail:20,engin:18,english:[1,18],enorm:13,enough:[1,7,10,13,18,22],ensur:[1,2,5,7,10,13,15,16,17,18],enter:[18,20,22],entir:[2,4,5,10,12,18],entireti:4,entiti:[2,5,12,18],entri:[4,5,13,18],enumer:4,environ:[1,12,13],envisag:18,equal:[2,13,18,19,20],equival:[1,4,17,18],especi:[17,21],essenti:[11,12,17,18,19],establish:[6,16],etc:[1,3,4,12,13,14,15,17,18],euribor:[11,12],evalu:[4,12],even:[5,9,10,12,13,14,18,20],event:[],eventu:15,ever:[1,5],everi:[2,5,12,13,14,15,18,22],everybodi:[5,12],everyon:[2,12],everyth:[2,10,18,22],evid:12,evolut:5,evolv:[18,22],exact:[12,18],exactli:[5,10,18],examin:[1,5,12,18],exampl:[],excel:12,except:[1,13,18,19],excess:1,exchang:[4,13,17,18],exclus:3,execut:[5,6,12,16,17,18],executor:[1,10],exercis:18,exhaust:14,exist:[1,2,3,4,5,6,8,14,18,20,22],exit:[3,18],expect:[1,3,6,10,13,15,18,20],expectedtypenam:13,expectfailureoftx:18,expens:1,experi:[5,15,22],experiment:[1,6,13,14],explain:[1,6,10,13,14],explan:1,explicit:[1,5,12,13],explicitli:[1,5,18,20],explor:[1,5,7,8,9,11,18,22],exploratori:10,expos:[1,6,10,11,12,13,17],exposur:[3,4],express:[4,5,9,12,13,14,18,20],extend:[1,2,9,17,18,19],extens:[1,14,17,18],extent:5,extern:[13,22],extract:[5,11,12,13,17,18,19],extractcommand:19,extractgroup:19,extrem:[5,12,18],face:[9,18,21],facevalu:18,fact:[1,2,4,5,12,13,18,20],factor:[4,5],factori:6,fail:[10,18,20],failswith:20,failur:[13,18,20],fairli:[1,13],fake:[16,18,22],fals:[1,10,12,13,17,18],familiar:[5,18],famou:14,far:[13,16,18],fashion:1,fast:[5,10,16],fault:13,featur:[1,13,14,15,18,21],feed:12,feedback:14,feel:[18,22],fetch:[10,11,12],few:[1,9,10,11,12,13,15,16,18],fiber:13,field:[1,4,12,13,14,18,19,21],file:[0,1,5,10,11,13,14,15,16,17,18,22],fill:[1,13,16,18],filter:[1,19],filterisinst:18,finalis:[4,13],financ:[13,14,22],financi:[5,6,8,13,14],find:[0,5,11,13],fine:[5,20],finish:[10,13],firm:18,first:[1,2,4,6,7,10,11,12,13,14,16,17,18,19,22],firstli:18,fit:[1,5],fix:[],fixabledealst:17,fixedleg:4,fixedlegpaymentschedul:4,fixedratepaymentev:4,fixingroledecid:6,fixingsessioninitiationhandl:6,fixof:12,flag:[11,22],flexibl:[2,5],flight:5,floatingleg:[4,6],floatinglegpaymentschedul:4,floatingratepaymentev:4,flow:[1,4,18,19],flux:22,fly:13,fold:1,folder:0,follow:[0,1,2,5,6,7,8,10,11,12,13,16,17,18,19,20,21],font:1,foo:[1,10],foobrokenexcept:1,fooutil:18,forc:[5,11,14,20],fordai:[6,12],forev:15,forget:[13,18],form:[2,5,6,13,16,18,19],formal:[10,18],format:[0,1,5,11],forth:13,forward:[10,12,13,15,16],found:[7,11,12,13,15,19,22],four:[9,18],frame:[1,13],framework:[],free:[5,12,13],freeform:18,freeli:12,frequenc:4,frequent:13,fresh:[12,18,20],freshkei:13,freshli:[17,18],from:[0,1,2,3,4,5,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22],fromcountri:17,front:18,frustrat:5,fulfil:3,full:[1,2,3,10,13,18,19],fulli:[1,5,10,13,14,17,18],fullysign:13,fun:[2,6,12,13,18,19,20],fund:5,fundament:[2,5,8,18],fungibl:[3,9,17,18,19],fungibleasset:[],funni:13,further:[4,5,9,17],futur:[2,3,5,12,13,17,18,21,22],gain:9,game:13,garbag:[1,11,13],gather:18,gavin:5,gbp:17,gcd:5,gear:15,gener:[],generateirsandfixsom:4,generateissu:18,generatemov:18,generateredeem:18,generatespend:[13,18],genuin:1,get:[],getamount:20,getbefor:18,getbloomfilters:1,getclass:18,getclaus:19,getcommand:[18,19],getdummy_cash_issu:20,getdummy_pubkey_1:20,getdummy_pubkey_2:20,getfacevalu:18,getfix:4,getifmatch:19,getifnotmatch:19,getinput:[14,18],getinst:14,getissu:18,getkei:18,getlegalcontractrefer:[18,19],getmaturityd:18,getmega_corp:20,getmega_corp_pubkei:20,getnotarysignatur:2,getoutput:[14,18],getoutst:14,getown:[18,19],getprogramref:18,getprotocoltrack:13,getrequiredcommand:19,getsign:[18,19],getter:18,gettim:18,gettimestampbi:18,getvalu:[18,19],git:[7,15],github:0,giusepp:14,give:[2,5,18],given:[2,5,10,12,13,18],givenpric:13,global:[1,5,12,14],glue:13,gnu:0,goal:[1,5,8,9,13,15],goe:16,gone:[13,14,18],good:[1,7,13,18,20,21,22],got:[11,13],gover:18,grade:17,gradl:[7,15],gradlew:[7,16],grammar:1,granular:5,graph:[5,9,11,13,18,21],graphit:11,great:14,greater:1,greatest:5,green:7,groom:5,group:[],groupclaus:19,groupclauseverifi:19,groupstat:[18,19],guarante:15,guava:1,gui:13,hack:[5,14],had:[2,14,18],hand:[6,13,18],handa:14,handl:[1,2,5,10,13,14,18,19],handler:[6,10,13],happen:[1,2,5,6,12,13,15,18,20],happi:16,hard:[1,5,13,15],harder:[5,18],hase:4,hash:[2,5,9,11,12,13,17,18],hashcod:18,hasn:7,hassl:13,hat:15,have:[1,2,3,4,5,6,7,9,10,12,13,14,15,16,18,19,20,22],haven:18,heap:13,hearn:5,heart:18,heavi:15,heavili:5,hedg:[3,4],heirarchi:1,held:18,hell:13,hello:13,help:[1,5,6,10,13],helper:[4,10,17,18],henc:[2,4,5],her:[18,21],here:[1,5,9,10,11,12,13,14,17,18,20,21,22],hierarch:13,hierarchi:13,high:[5,12,13],higher:[1,2,7,18],highlight:[14,18],histori:[2,13],hit:[5,7],hoc:14,hold:[5,10],holder:[1,5,18],holidai:[4,12,17],home:[7,16],hood:[13,20],hopefulli:22,hotspot:1,how:[],howev:[2,3,4,5,10,12,13,17,18,19,20],html:[0,1],http:[0,7,11,12,16,18,19,22],hub:13,human:[5,12,13],hundr:13,hurt:13,hypothesi:8,idea:[1,5,7,9,13,18,22],ideal:[13,18],ident:[2,5,12,13,17,18,19,20],identifi:[4,5,9,10,11,12,13,17],identityless:5,identityservic:13,ifmatch:19,ifnotmatch:19,ignor:[18,19],illeg:12,illegalargumentexcept:[1,12,13,18,20],illegalstateexcept:1,illustr:1,imagin:[1,13,18],immedi:[5,18],immut:[1,4,5,12,18],imper:1,implement:[],impli:13,implic:[2,5],implicitli:4,impos:[12,13,18],imposs:[5,12],improv:[5,14,15,18,19,21],inbackground:10,includ:[],incompat:20,incorpor:12,increas:[1,10],indent:1,independ:[2,12],index:[4,5,6,7,18],indexsourc:6,indic:[1,4,6,10,13,14,18],individu:[1,10,16,18,20],industri:[8,9,11],infer:[18,20],infix:18,influenc:11,info:13,inform:[1,2,5,13,17,18,19],infrastructur:[5,9,11],inher:5,inherit:[1,10,18],init:12,initi:[2,10,13,14,18,22],initialis:2,inmemorymessagingtest:10,inner:19,inoutgroup:[18,19],input:[2,3,5,12,13,14,17,18,19,20,21],inputcash:20,inputindex:2,insert:[1,10,11,12],insid:[5,10,13,16,18],instal:[0,6,7,16],installdist:16,instanc:[],instant:[1,6,12,13,17,18],instanti:[5,6,13,14],instat:20,instead:[1,5,6,9,14,16,18,22],instig:2,institut:[5,9],institutionrefer:18,instruct:[11,18],instrument:[3,4,6],insuffici:5,insufficientbalanceexcept:18,integ:[14,18],integr:[1,12,13,14,21],intellig:1,intend:[1,3,5,11,12,13,17,20],intent:[12,18,21],intention:1,inter:[9,14],interact:[1,5,12,13,14],interchang:17,interest:[],interestrateswap:9,interfac:[],intern:[1,9,10,17,18],internalis:1,interop:[9,18],interpret:[1,5,18],intersect:18,interv:17,intesa:14,introduc:[1,2,6,12,14,17,18],intuit:1,invalid:[2,12,13,18],invari:18,investig:13,invoc:10,invok:[1,5,6,10,11,13,14,18],involv:[2,3,5,10,12,13,17,18,22],ipsa:12,irrelev:6,irsdemo:16,irsexport:4,irstest:4,irsutil:4,irswebdemo:16,isbefor:18,isempti:18,isinst:13,isn:[1,13,18,22],issu:[2,3,5,9,10,12,14,15,17,18,19,20,21,22],issuanc:[3,13,17,18,19,21],issuedbi:20,issuer:[3,5,18,20],item:18,iter:[13,15,18],itself:[2,4,5,6,10,11,12,13,18,20],jar:[0,5,11],jarinputstream:5,java:[1,5,6,9,10,11,13,14,18,19,20,22],javaclass:13,javacommercialpap:[18,19],javadoc:1,javatesthelp:20,jdk1:7,jdk:[7,13,14,18],jetbrain:[7,9],jmx2graphit:11,jmx:11,jmxtran:11,job:22,johann:14,join:[10,18],joint:18,jolokia:11,json:[11,22],judgement:1,jump:16,junit:18,just:[1,5,7,10,11,13,14,17,18,20,22],justifi:8,jvm:[5,9,11,13,22],kafka:10,kdoc:1,keep:[5,13,18,21],kei:[1,3,5,9,10,12,13,17,18,19,20],kept:13,key_mismatch_at_issu:18,keymanagementservic:13,keypair:[13,18],keyword:[1,18,20],kick:13,kind:[5,9,10,12,13,18,22],know:[2,5,6,9,12,13,16,20],knowledg:12,known:[],kotin:18,kotlin:[],kryo:[10,13],label:[13,18,20,21],labori:18,lack:[],lambda:20,land:4,lang:20,languag:[1,5,7,8,9,14,17,18,21,22],larg:[5,12,13,14,17,18,22],larger:[1,5],last:[15,20],latenc:[2,12],later:[1,5,9,10,12,13,14,17,18,19],latest:[1,7,14],latter:[1,18],launch:6,layer:[5,10,13],layout:21,lead:[1,5,18],leak:[2,5,13],learn:[5,8,13,16,18,22],least:[12,18],leav:[1,13],ledger:[2,3,4,5,8,11,12,13,14,18,20,21],ledgertransact:17,left:[10,13,16,19,20],leg:[4,6,9],legal:[2,5,12,17,18],legalcontractrefer:[18,19],legallyidentifi:[2,12,13],legallyidentifiablenod:13,less:[13,18,21],let:[1,5,6,11,12,13,14,16,17,18,19,20],letter:1,level:[1,2,4,7,10,12,13,17,18,19,20],lib:0,liber:1,libor:[4,11,12],librari:[1,11,12,13,17,18],licens:1,life:22,lifecycl:[],lifecyl:3,lifetim:4,like:[1,2,4,5,6,7,10,11,12,13,15,17,18,19,22],likewis:18,limit:[3,5,8,18],line:[],linearst:17,liner:1,link:[1,5,12,13,17,18],linkabl:5,linux:[11,14],list:[0,5,10,12,13,14,15,16,17,18,19],listen:1,listenablefutur:13,listof:19,liter:5,littl:[1,18,20],live:4,livelock:5,load:[2,5,14,16,17,18,22],loan:[3,4,12],local:[0,5,7,11,12,13,20],locald:12,localhost:[11,16],locat:[17,18],lock:[1,3,18],log4j:14,log:[13,14,16],logger:13,logic:[2,5,6,9,10,13,14,18,19,22],longer:[1,4,12,13,14],look:[1,4,10,11,12,13,15,18,19,20,22],loop:[1,4,18],loquitur:12,loss:12,lot:[1,4,5,16,22],low:[2,13],lower:[1,12],lurch:13,mac:11,machin:[],maco:16,made:[1,4,5,8,13,14,15,19],mai:[1,5,9,10,11,12,13,14,15,18,19,20,22],mail:[15,16],main:[6,13,16,18,21,22],maintain:[2,5],maintan:12,mainten:10,major:15,make:[0,1,2,4,5,10,12,13,14,15,16,18],makenod:10,maker:9,malici:13,manag:[],mani:[1,5,6,9,10,12,13,14,17,18],manipul:17,manner:13,manual:[6,10],map:[],mappabl:18,mark:[1,3,13,18],markdown:1,marker:[13,18],market:8,master:15,match:[5,10,12,13,18,19],matchbehaviour:19,matter:18,matur:[3,4,11,12,18],maturityd:18,maven:7,maximis:5,maximum:5,maybestx:13,maybetraderequest:13,mbean:11,mean:[1,5,6,10,12,13,17],meaning:[2,3],measur:[4,18],mechan:[14,18],meet:18,mega_corp:[18,20],mega_corp_kei:18,mega_corp_pubkei:[20,21],megacorp:[18,21],member:[4,14],memori:[],menlo:1,mention:[6,13],menu:7,mere:[4,18],merg:[5,9,14,17,18],mess:13,messag:[],messagehandlerregistr:10,messagerecipi:10,messagerecipientgroup:10,messagingservic:[10,13],method:[],metric:11,middl:[1,10,13],might:[1,4,5,7,13,18],mike:5,mileston:[],mind:[1,12,13,18],mine:5,mini:19,minim:[5,13],minimis:[2,3,5,10],minimum:[4,5],minor:15,minu:18,minut:[9,12],misc:10,mismatch:20,miss:[1,13,18,20,22],missingsig:13,mission:11,mix:[1,13,18],mock:10,mockservic:17,mode:10,model:[],modest:5,modif:[17,18],modifi:[2,3,4,7,13,17,18,19],modul:[1,10,14,18],moment:[10,14],monei:[12,18],monetari:18,monitor:[],month:[4,13,15],more:[1,2,3,4,5,9,10,11,12,13,14,16,17,18],moreexecutor:1,mortensen:14,most:[1,4,5,10,11,12,13,18],mostli:18,move:[3,13,14,15,18,19,20,21],movement:[13,18],much:[1,5,9,13,14,18,22],multi:[1,9,13,18],multilater:[3,14],multipli:4,must:[1,2,3,5,6,10,11,12,13,16,17,18,19,22],mustafa:14,mutabl:[1,5,17,18],mutat:5,mutual:[2,3,13],myfil:11,mykei:17,mykeypair:13,nail:1,namedbyhash:17,namespac:13,narrow:1,nativ:13,natixi:14,natur:18,naval:[5,12],navig:16,navistar:12,neat:20,necessari:[1,2,15,16],nee:14,need:[0,1,2,4,5,6,8,10,11,13,15,16,17,18,19,20,22],negoti:[5,17],neither:[13,18],nest:13,net:[3,4,14,18,21],nettabl:9,network:[],neutral:9,never:[1,5,12,18,19],newli:[6,13],newnotari:2,newown:18,newsecurerandom:14,next:[1,4,6,7,13,14,18],nextfixingof:6,nextscheduledact:6,nice:16,nio:1,nix:16,noddi:11,node:[],nodea:16,nodeb:16,nodeinterestr:12,nodej:16,nodeservic:12,non:[],none:[6,13],nonemptyset:14,nordea:14,normal:[3,4,13,17,18,19],not_matured_at_redempt:18,notabl:1,notaris:[2,17],notarychang:14,notarychangeprotocol:2,notaryexcept:2,notaryprotocol:2,notaryservic:14,notarytous:17,notat:13,note:[],noth:[1,5,6,14,18],notic:[1,18],notif:10,notifi:10,notion:[4,5,18],notnul:[18,19],now:[1,5,7,10,12,13,14,16,17,18,20,21,22],npm:16,nugget:18,nullpublickei:18,number:[1,3,4,5,10,12,13,15,16,17,18],numer:5,obj:18,object:[1,3,4,5,6,9,10,11,12,13,14,17,18,19,21,22],oblig:[],obligor:3,observ:[4,5,6,12,13],observatori:[5,12],obsolet:6,obtain:[],obviou:[1,2,5,12],obvious:[4,18],occasion:[],occur:[2,6,12,13,18],occurr:12,odd:[13,18],off:[10,13,18,21],offer:13,offlin:10,offset:4,often:[1,3,4,5,12,13,18],oftenor:12,oil:[14,20],old:2,omit:6,onc:[0,1,2,4,6,9,10,12,13,15,17,18,22],onli:[1,2,4,5,9,10,11,12,13,14,18,19,21,22],onto:[1,13,18,21],opaqu:[9,10],opaquebyt:18,open:[2,5,7,12,13,16,21],openjdk:7,oper:[4,6,10,11,12,13,18],optim:1,option:[0,1,4,6,10,12,13,18,19,22],oracl:[],orchestr:[8,9,14,22],ordain:4,order:[0,1,2,3,4,5,9,10,13,17,18,19,21],ordinari:[5,13,18],org:[0,7,16,18,19],orient:[],origin:[17,18],originalst:2,otc:9,other:[1,2,3,4,5,6,9,10,12,13,16,17,18,20],othersid:13,otherwis:[1,6,13,18,19],our:[1,2,5,6,13,14,15,18,20],ourselv:[13,18,22],oursignatur:13,out:[1,2,3,5,6,7,9,11,12,13,15,18,19],outag:10,outcom:13,outer:19,outermost:19,outlin:[5,13],outpoint:5,output:[2,3,5,12,13,14,16,17,18,19,20,21],outsid:[5,10,12,13,18,22],outstand:3,outstat:18,over:[1,2,4,5,10,11,12,13,17,18],overal:[2,6,10,20],overdu:6,overflow:1,overload:13,overnight:17,overrid:[6,13,18,19],overwhelm:5,own:[1,2,3,10,11,12,13,14,15,18,20,21,22],ownablest:[13,17],owned_bi:18,owner:[13,17,18,19,20],ownership:[13,18],owningkei:[13,18],ozturk:14,p2p:[13,14],pack:18,packag:14,packet:5,page:[7,12,16,18],pai:[3,12,13,18,21],paid:[3,4,5],pair:[5,13,18],paper:[],paper_1:[18,21],parallel:[5,10,13],parallelis:5,paramet:[1,6,13,16,18,19],parameteris:5,parent:13,pars:[12,22],part:[1,2,3,5,6,12,13,14,17,18,19,22],parti:[],partial:[2,13,18,20],partialtx:13,particip:[2,5,14,18,22],particular:[1,2,5,11,13,14],partyandrefer:1,partyrefer:[1,18],pascal:1,pass:[2,10,13,18,19,21],past:[1,12,16,18,22],patch:1,path:[1,6,11,14,18],pattern:[1,5,18],paye:5,payer:[4,5],payment:[3,4,5,6,12,13,16,18,21],pdf:12,peer:[9,10,12,13],penni:18,peopl:[1,5,9,18],per:[1,5,6,22],perform:[1,2,4,5,6,12,13,16,18],perhap:[1,5,6,18],period:4,perman:18,persist:[9,10,13,14],perspect:[5,13,18],phrase:12,physic:[2,12,14],pick:[10,13,14,15,18,22],piec:[1,2,5,10,13,18,20],ping:10,pip:0,pki:[5,14],place:[0,1,4,5,6,9,10,12,13,14,15,17,18,22],plai:13,plan:[10,16],platform:[],pleas:[1,5,7,14,16,18],pluggabl:14,plugin:[7,11],point:[1,2,3,5,6,11,12,13,15,18],pointer:[2,13,17],pointless:1,pong:10,pool:[1,5,13],poor:5,pop:[7,10],popular:9,popup:7,port:[14,15,16],posess:13,posit:[1,2,5,13],possess:2,possibl:[5,10,12,13,18],post:19,potenti:[1,2,9,13,18],pound:18,power:[5,8],practic:[5,18],pre:[0,4,5,13,18,20,22],preced:18,precis:[5,9,12],precondit:1,prefer:[1,5],prefix:[1,13],preliminari:10,prepar:[5,18],present:[2,3,4,8,12,17,18,19],preserv:[2,5],press:18,pretend:[11,17],pretti:[5,13,18],prevent:18,previou:[5,14,17,20],previous:[4,6,12,14],price:[5,12,13],primari:[9,12],primarili:3,primit:[18,20],print:16,priv:13,privaci:[1,2,5,13,14,18],privat:[1,5,13,18,22],privatefoo:1,probabl:[7,12,18,22],problem:[2,5,12,13],proce:13,procedur:13,process:[],processor:5,produc:[0,6,18,20,21],product:[1,6,8,9,15,17,18],profit:[18,21],profound:5,program:[1,5,10,11,13,14,16,17,18,22],programref:18,progress:[],progresstrack:13,project:[7,14,16],prolif:14,promis:14,proof:[5,8],propag:[8,11,18,19],properli:13,propos:[8,13],prose:[12,17],protect:13,protocol:[],protocollog:[6,13],protocollogicref:6,protocollogicreffactori:6,protocolstatemachin:13,protocoltrack:13,prototyp:[1,5,8,9,12,18],prove:[2,5,8,18],provid:[0,1,2,3,4,5,10,11,12,13,14,17,18,19,22],provision:17,pseudo:12,ptx:13,pubkei:20,publicfoo:1,publickei:[],publicli:[],pull:7,pump:10,punish:12,purchas:[13,16],pure:[3,5,12],purpos:[3,9,13,18],push:15,put:[1,13,15,18,22],python:0,qualiti:8,quantiti:[5,9,18],quasar:13,queri:[4,6,12],question:[1,2,6,7,12],queu:10,queue:[1,10,13],quick:12,quickli:[5,10,18],quit:[1,12,13,18],r3corda:[14,16,19,20],r3dlg:15,r3prototyp:[0,7,16],r3repositori:7,rais:2,random63bitvalu:13,random:[5,6,13,14],rang:12,rapid:[1,9,15],rate:[],ratefixprotocol:12,rather:[1,5,13,14,18],raw:[11,13],reach:[2,4,5,6,12],reachabl:13,read:[1,5,8,9,11,12,13,18,22],readabl:[9,13],reader:18,readi:[15,18],readili:17,readm:1,real:[1,10,12,14,17,18,22],realis:13,realism:10,realist:17,realiti:4,realli:[1,2,5,13,18],reason:[1,4,5,13,17,18],reassign:18,recal:4,receiv:[3,4,5,10,12,13,15,18,21],receiveandcheckproposedtransact:13,receiveandvalidatetraderequest:13,recent:14,recipi:[3,5,10,18],recognis:[5,12,18],recommend:[1,10,22],record:[2,6,10],recordtransact:6,recov:10,recreat:13,red:[4,7],redeem:[3,9,18,19,21],redempt:[18,21],redemptiontim:[18,21],redesign:14,reduc:1,redund:1,ref:[13,18,20],refactor:14,refer:[1,2,3,4,5,6,9,12,13,14,17,18,20],referenc:2,refin:9,reflect:[18,19],refus:7,regard:2,regardless:13,regener:[4,15],regist:[1,10,11,13,22],registr:10,regular:[11,13,18],reissuanc:[5,18],reject:18,rel:[5,10,19],relabelablestep:13,relat:[4,18],relationship:18,releas:[],relev:[5,14,17,19],reli:5,reliabl:10,relianc:5,relic:11,religi:1,remain:[6,18,21],remeb:7,rememb:[1,6,7,13,18],remind:13,remot:7,remov:[10,13,18],renam:14,render:[1,13,21],repeat:[1,4,10,13],replac:[2,4,7,11,14,15,17,18],replic:5,repoint:2,report:[10,19],repositori:[],repres:[1,3,4,5,10,12,13,17,18],represent:4,request:[2,5,10,12,13,14],requestingparti:2,requiredcommand:19,requiresinglecommand:[18,19],requirethat:[18,19],research:14,resel:12,reserv:13,reset:4,reshap:5,resolut:[2,5,8,13],resolv:[1,13,17],resolvetransactionsprotocol:13,resourc:[13,16],respect:[1,5,13,16,18],respend:5,respons:[2,5,6,10,12,13],rest:[2,5,9,10,11,13,14,22],restart:[7,13],restor:13,restrict:1,restructur:19,restructuredtext:0,result:[1,2,4,5,12,13,18,19],resultfutur:13,resum:[13,14],resurrect:13,retain:10,retri:[9,10,13],retriev:[2,4],retrieveoutput:20,reus:[5,13,20],reusabl:[12,14,18,19],reveal:[2,5,13,18],revers:13,revert:3,review:[1,14,15],revis:4,rewrit:13,right:[1,7,10,11,13,15,22],rigid:5,rigidli:1,risk:13,robert:14,robust:14,role:[6,16,22],roll:[4,13,16],rollov:[17,18],root:[15,16,18,21],rotat:14,roughli:[12,15],rout:13,router:10,rui:14,ruin:20,rule:[1,12,13,14,18],run:[],runbuy:13,runnetwork:10,runsel:13,runtim:[1,13],safe:[1,5,13,18],safeti:1,sai:[1,2,5,18],sale:[16,18],same:[1,2,3,4,5,6,9,10,12,13,16,18,19,20,21],sandbox:[5,6,9,18],saniti:13,santiago:14,satisfi:18,save:[1,14,18],scala:[9,18],scalabl:[1,5],scale:4,scenario:[5,22],scene:[13,18],schedulablest:6,scheduledact:6,scope:[5,18,19],scotiabank:14,scrape:11,scratch:[17,22],screen:[1,7],script:[0,5,18],scroll:16,scrub:13,seamless:9,search:[7,13,18],second:[4,13,16,17,18],secondari:13,secp256r1:14,section:[5,15,18],secur:[5,6,10,13],securehash:[2,18,19],securerandom:14,see:[0,1,2,3,4,6,9,10,12,13,16,17,18,19,22],seed:13,seek:5,seem:5,seen:[1,4,12,13,18,21],select:[2,7,14,18,19],self:14,sell:[13,18,22],seller:[],sellerownerkei:13,sellersig:13,sellertradeinfo:13,semi:[5,12],send:[1,5,10,11,12,13,15,18,20],sendandrec:13,sender:5,sendsignatur:13,sens:[4,12,13,18],sensit:6,sent:[6,10,13,18],separ:[2,5,11,12,13,16,17,18],sequenc:[5,10],sequenti:[10,13],seri:13,serial:[9,10,18],serialis:[1,5,9,10,13,18],serializablewithkryo:18,serializeablewithkryo:18,seriou:[5,15],serious:22,server:[11,12,22],servicehub:[6,13],session:[6,10,13],sessionid:[6,13],set:[],setof:[13,19],setter:18,settim:[13,17],settl:[3,10,12,17],settlement:[3,13],setup:6,setupa:16,setupb:16,sever:[5,13,18,20,22],sha256:[18,19],sha256sum:11,sha:[5,11],shape:5,share:[4,5,12,13,14,18,19,22],shasum:11,she:18,shortcut:9,shorthand:[18,20],shot:10,should:[1,2,3,5,6,7,9,10,13,14,16,17,18,19,20,22],shoulder:1,shouldn:[13,18],show:[5,7,9,16,18,21],shown:[13,18],shutdown:13,side:[12,13],sig:18,sign:[2,4,5,9,10,12,13,14,17,18,19,20],signatureexcept:13,signaturesfromsel:13,signedtransact:[13,17,18],signer:[12,18,19],signific:[5,14],significantli:4,signoff:12,signwith:[13,17,18],signwithecdsa:13,signwithourkei:13,silver:1,similar:[1,5,10,12,14,18,19],simpl:[1,3,4,5,9,10,11,13,18,19,21],simplecash:20,simplecashdoesntcompil:20,simplecashfailswith:20,simplecashsuccess:20,simplecashtweaksuccess:20,simplecashtweaksuccesstopleveltransact:20,simplenotaryservic:2,simpler:[5,9],simplest:[5,13,18,22],simpli:[1,2,5,10,13,17,18,20],simplif:14,simplifi:[1,3,5,10,17,18,22],simultan:[5,10,13,18],singl:[],singleclaus:19,singlemessagerecipi:[10,13],singleton:[13,18,19],singletonlist:19,sit:10,site:[1,15],situat:[1,5],size:[1,4,5,13,18,19],skip:[13,17],slight:18,slightli:18,slip:15,slow:[1,5],slowest:5,small:[5,6,12,13,16,18,21],smaller:14,smart:[],smm:13,smooth:18,snake:20,snapshot:[5,14,15],snide:0,snippet:[2,13,18],softwar:[13,15,22],sofu:14,sold:[13,18,21],solv:[5,12,13],solvenc:12,some:[1,2,3,5,6,9,10,11,12,13,14,16,17,18,19,20,21,22],somed:18,someon:[2,5,10,18],someprofit:[18,21],someth:[1,4,5,7,16,17,18,19,22],sometim:[5,10,11,12,13,18],somewhat:[5,13,14],somewher:[18,21],sophist:5,sort:[12,13],sound:[1,13,18,21],sourc:[4,6,7,12,13],sparingli:1,special:[2,5,20],specialis:[13,19],specif:[2,5,6,10,11,12,13,14,17,18,19,21],specifi:[0,1,2,3,5,9,10,12,13,14,18,19,20,22],speed:[5,13],spend:[5,9,13,18],spent:[5,20],sphinx:0,sphinx_rtd_them:0,spirit:14,split:[5,9,14,17,18],spread:[2,10,13],spreadsheet:12,squar:21,src:[16,18,21,22],ssl:[9,14],stabilis:15,stabl:15,stack:13,stage:[1,13,18,22],stai:[5,18],stake:5,standalon:12,standard:[1,8,11,13,17,18,19],standardis:[5,17,18],start:[],state:[],stateandref:[2,13,17,18],statehistori:2,stateless:5,statemachinemanag:13,statement:[1,5,12,13,18],stateref:[2,5,6,17],statesoftyp:13,statist:11,status:5,step:[],still:[2,5,6,13,14,18,22],stock:[5,12],stop:[1,10,13],storag:5,store:[2,13,14,17,18],stori:[1,14],straightforward:[13,18],stream:[13,19],stress:1,strictli:[4,5],string:[10,12,13,18],strong:9,structur:[1,5,7,9,12,13,18],studi:18,stuff:[1,13],stx:[13,17],sub:[1,13],subclass:[13,17],subclaus:19,subgroup:5,submiss:12,submit:[1,2,10,13,16],subprotocol:[2,13],subscrib:10,subsequ:20,subset:3,subtask:13,subtl:[1,5],successor:[2,6,9],succinct:1,sudo:[0,16],suffer:5,suffic:12,suffici:[5,8,10,12,15,17],suffix:18,suggest:[10,18],suggestinterestrateannouncementtimewindow:6,suit:14,suitabl:[6,10,15],sukrit:14,sum:[18,20],sumcashbi:[13,18],sumcashornul:18,summari:[],summaris:5,sun:1,superclass:[13,14,17],superior:1,supersed:5,supertyp:18,suppli:[3,16],support:[],suppos:[13,18],suppress:[1,14],suppresswarn:1,sure:[2,14,15,16,18,22],surfac:13,surround:[1,18],surviv:13,suspend:[],swap:[],swapsignatureswithsel:13,symbol:7,synchronis:[1,5,12],syntax:[9,18],system:[2,5,9,11,12,13,14,16,18],tab:[1,7],tackl:[14,19],tag:[1,15],tailor:8,take:[1,4,6,9,13,15,17,18,19,20,21],tamper:13,target:[0,1,5,9,11],targetrecipi:10,task:[5,6,13],team:7,technic:[],techniqu:[1,5,12,18],tell:[0,10,13],templat:17,tempor:12,temporari:5,temporarili:[13,15],tempt:18,temptat:13,ten:18,tenor:[4,11,12,17],term:[3,5,6,17,18,19],termin:[4,11,13,16],terminolog:5,test:[],test_tx_tim:18,testutil:18,testwithinmemorynetwork:10,text:[1,7,11,20],than:[1,2,5,8,11,13,14,18,21],thank:14,thedao:14,thei:[1,3,4,5,6,9,10,11,12,13,15,16,17,18,19],theirsessionid:13,them:[1,4,5,6,7,9,10,11,13,14,15,16,17,18,20,22],themselv:[10,12,13,17,18],theori:[],therefor:[5,7,9,13,15,18],thi:[0,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22],thing:[1,5,6,9,12,13,14,16,17,18,22],think:[1,5,7,13,18],third:[5,16,18],thisstateref:6,those:[5,6,10,11,12,13,16,17,18],though:[10,11,13,18],thought:[5,9],thousand:20,threadsaf:1,three:[16,17,18],threshold:18,through:[4,5,6,11,13,14,18,19,20,22],throughput:[2,5],throwifsignaturesaremiss:13,thrown:[18,19],thu:[1,5,6,11,12,17,18],tighten:18,tightli:13,time:[1,2,3,4,5,6,9,11,12,13,14,16,17,18,21],timelin:18,timestamp:[],timestampauthoritysig:13,timestampcommand:[12,18],timestampercli:18,timestamperservic:12,timestampingauthor:13,timestampingprotocol:13,titl:7,todo:[1,13,18],togeth:[3,5,13,14,18,19],token:[17,19],told:1,toledgertransact:[13,17],toler:[2,6,12],tolist:19,too:[1,13,18,21],took:13,tool:[9,11],toolbar:7,top:[1,5,7,13,16,18,19],topic:[10,13,22],topicsess:14,toplevel:20,topriv:13,toset:13,tosignedtransact:[13,17,18],tostr:[1,13,18],total:[5,18],toward:[14,15],towiretransact:17,trace:13,track:[],tracker:13,trade1:16,trade:[],trade_top:13,tradeoff:[],trader:[],traderdemo:22,traderequest:13,tradit:[5,18],traffic:[5,13],transact:[],transactionbuild:[13,14,17,18],transactionforcontract:19,transactionforverif:18,transactiongroup:18,transactiongroupdsl:21,transactiongroupfor:21,transactiongroupfortest:18,transactionst:[2,14,17],transactiontyp:14,transactionverificationexcept:20,transfer:[18,20],transit:[8,18,22],treat:18,tree:13,tri:[5,18],tricki:[5,13],trigger:[3,6,12,16,19],trim:19,trivial:[1,5],trust:[3,5,13],truth:13,tsa:[5,13],tsasig:13,tupl:1,ture:5,turn:[5,13,17,18,19,20,22],tutori:[3,8,9,12,13,14,18,19,20,22],tweak:20,twice:[9,20],two:[],twopartydealprotocol:6,twopartytradeprotocol:13,txb:17,txbit:13,txhash:[5,13,18],txt:11,type:[],typenam:13,typetobui:13,typic:[5,6,10,11,13,17,18,22],unacceptablepriceexcept:13,under:[0,13,15,18,20,22],underli:[3,4,5,13,17],underscor:[1,18],understand:[5,10,11,18,21,22],unexecut:18,unexpect:13,unfinish:13,unfortun:[13,18],unguess:13,unicredit:14,unifi:[14,22],uniform:6,unindex:7,uniqu:[2,5,12,13,14],unit:[2,5,7,9,10,13,14,17,18,19,20,21,22],unix:[11,16],unknow:12,unless:[1,12,13,15,18,22],unlik:[3,7,18],unmatch:19,unnatur:5,unnecessari:18,unpack:[13,18],unprocess:19,unqiu:6,unread:13,unrecognis:18,unrel:18,unreleas:[],unschedul:6,unserialis:13,unset:4,unspent:5,unstart:13,unsupportedoperationexcept:[18,19],until:[2,4,5,6,10,13,15,19,20,22],untrustworthydata:13,unus:10,unusu:18,unverifiedtransact:20,upcom:[6,14],updat:[5,7,10,13,14,15,18],upgrad:[7,8,14],upload:[],upon:[4,13,18],upward:15,url:[7,16],usabl:[9,14,15],usag:[1,12,13,18],usd:17,useless:18,user:[0,1,5,7,9,10,12,13,14],usr:0,usual:[1,5,15],utc:6,util:[10,14,18],vagu:1,val:[1,2,6,10,12,13,17,18,19,20,21],validatingnotaryservic:2,valu:[1,3,4,5,9,12,18,19,20,21],valuabl:12,valuat:4,vanilla:[3,4,9],vari:[],variabl:[1,4,5,13,18],variant:18,variou:[1,5,9,11,13,18],vehicl:5,vendor:[9,11],verbos:18,veri:[1,3,5,9,12,20,21,22],verif:[3,5,9,19,20],verifi:[],verifytransact:13,versa:[3,4,13,17],version:[4,7,10,13,14,15,17,18],versu:13,vertic:1,via:[0,1,4,5,6,11,12,13,16,18,22],vice:[3,4,13,17],view:[1,4,16],virtual:[5,8],visibl:[2,5],visualis:[],vital:13,wai:[1,5,6,9,11,12,13,14,18,19,20,22],wait:[6,7,10,13,16],wake:14,wallet:[5,6,13,14,18],walletservic:13,want:[1,5,7,10,11,12,13,14,18,20,22],weak:12,wear:15,web:[8,11,12,14],websit:18,weekend:4,well:[0,1,4,5,6,9,11,12,13,17,18,19],went:1,were:[1,5,12,13,18],what:[],whatev:[1,13,17],when:[1,2,3,4,5,6,10,11,12,13,14,17,18,20],whenev:1,where:[],wherea:4,wherev:11,whether:[2,3,10,12,13,19],which:[0,1,2,3,4,5,6,9,10,11,12,13,14,15,16,17,18,19,20,22],whilst:[5,12,13,16,18],whitelist:[3,6],who:[1,5,9,10,13,14,18],whole:[2,18,20],whom:[3,5,10],whose:[11,17],why:[1,5,9,18],wide:[1,10,18],widescreen:1,widespread:1,width:1,wiki:[5,18,19],wikipedia:[18,19],window:[5,7,13,16,21],wire:22,wirecommand:18,wiretransact:[2,12,13,17],wish:[5,10,12,13,14,18,22],within:[0,1,2,5,11,16,20],withitem:17,withkei:13,withnewown:13,without:[],withoutown:[18,19],won:[10,12,13,16,18,20],word:[1,2],work:[1,2,4,5,6,7,8,9,10,11,12,13,14,16,17,18],worker:1,world:[5,12,13,18,20],worn:18,worri:[1,9,13],worst:5,worth:[1,18],worthless:12,would:[1,3,4,5,9,10,11,12,13,17,18,22],wouldn:[12,18],wrap:[1,11,13,14,17,18,19,22],wrapper:[1,2,13],write:[],written:[0,4,5,9,14,18],wrong:[1,13,16,20],wrote:5,wtx:[2,12,13],www:[0,7],year:4,yet:[1,4,5,9,13,14,17,18],yield:[5,13],you:[0,1,5,6,7,9,10,11,12,13,14,16,17,18,19,20,21,22],your:[],your_usernam:7,yourself:5,zero:[5,18],zip:[5,11],zone:6,zoneddatetim:6},titles:["Building the documentation","Code style guide","Consensus model","Platform contracts","Interest Rate Swaps","Data model","Event scheduling","Getting set up","Welcome to the Corda repository!","What’s included?","Networking and messaging","Node administration","Writing oracle services","Protocol state machines","Release notes","Release process","Running the demos","Data types","Writing a contract","Writing a contract using clauses","Writing a contract test","Using the visualiser","Where to start"],titleterms:{"class":[18,19],"function":18,about:7,administr:11,adopt:5,amount:17,api:18,approach:12,assert:[1,12],asset:18,attach:11,base:18,basic:12,bitcoin:5,build:0,buyer:13,cash:[3,17],chain:20,chang:2,check:18,claus:[18,19],code:1,command:18,comment:1,commerci:[3,18,19],comparison:5,compil:1,complain:7,con:5,consensu:2,continu:12,contract:[3,9,18,19,20],corda:8,creat:4,cut:15,data:[5,12,17],date:17,demo:[16,22],detail:4,document:0,download:11,error:1,ethereum:5,event:6,exampl:6,fix:11,framework:12,fungibleasset:17,gener:[1,18],get:7,group:[18,19],guid:1,how:[6,18],implement:[6,10,12,13],includ:9,instanc:4,intellij:7,interest:[3,4,11],interfac:10,introduct:[6,12,13],known:12,kotlin:9,lack:7,length:1,lifecycl:[4,17],line:1,machin:13,manag:13,map:10,memori:10,messag:10,method:13,mileston:14,model:[2,5],monitor:11,multipl:2,name:1,network:10,node:11,non:18,notari:2,note:14,oblig:3,obtain:2,occasion:12,oracl:12,orient:18,overview:5,paper:[3,18,19],parti:[13,17],platform:3,pro:5,process:15,progress:13,properti:1,protocol:13,publickei:17,publicli:12,rate:[3,4,11],rational:5,releas:[14,15],repositori:8,requir:[0,18],run:[2,16],schedul:6,sdk:7,seller:13,servic:[2,10,12],set:7,signatur:2,singl:20,smart:18,space:1,start:[18,22],state:[13,17,18],step:15,style:[1,5],summari:19,support:17,suspend:13,swap:[3,4],technic:4,test:[18,20],theori:13,thread:1,timestamp:2,track:13,trade:13,tradeoff:5,trader:[16,22],transact:[17,20],two:[12,13],type:17,unreleas:[],upload:11,utxo:5,valid:2,vari:12,verifi:18,visualis:21,warn:1,web:16,welcom:8,what:9,where:22,without:7,write:[12,18,19,20],your:[11,18]}}) \ No newline at end of file +Search.setIndex({envversion:49,filenames:["building-the-docs","codestyle","consensus","contract-catalogue","contract-irs","data-model","event-scheduling","getting-set-up","index","inthebox","messaging","node-administration","oracles","protocol-state-machines","release-notes","release-process","running-the-demos","transaction-data-types","tutorial-contract","tutorial-contract-clauses","tutorial-test-dsl","visualiser","where-to-start"],objects:{},objnames:{},objtypes:{},terms:{"00z":18,"0_xx":7,"17t16":18,"1mb":13,"8u45":7,"_before_":13,"_do_":13,"_foo":1,"_is_":13,"_mbeans_":11,"abstract":[5,13,14,18],"boolean":[5,18],"break":[12,15,18],"byte":[1,5,9,13,20],"case":[1,2,5,10,12,13,14,17,18,19],"catch":[1,7,13],"class":[1,2,4,6,8,10,12,13,14,17],"continue":19,"default":[1,3,7,9,13,14,16,18],"enum":14,"export":[11,13,22],"final":[2,4,5,7,10,13,18,19,20],"float":[3,4,6,9],"function":[1,3,4,5,8,10,12,13,14,16,17],"import":[1,5,6,7,10,13,14,18,19,20,22],"instanceof":[18,19],"int":[1,2,18],"long":[1,3,5,6,10,13,18],"new":[1,2,4,5,7,8,9,10,11,13,14,15,17,18,19,20,22],"null":[6,12,18],"public":[1,5,9,10,11,12,13,17,18,19,20],"return":[1,2,4,6,10,11,12,13,14,18,19,20,22],"short":[6,10,15,18],"static":[5,12,13,18,20,22],"super":1,"switch":[9,13,14,18],"throw":[1,2,12,13,18,19],"transient":13,"true":[5,10,12,18,21],"try":[1,5,13,16,18,21,22],"var":[13,18],"void":[18,19,20],"while":[17,18],abil:5,abiliti:10,abl:[2,5,10,12,14,16],abort:2,about:[1,2,5],abov:[1,4,5,10,13,18,19,20],absolut:5,abstractnod:12,accept:[1,2,3,5,10,13,18],acceptablepric:13,access:[1,5,7,10,11,12,13,18],accid:13,accident:1,accompani:1,accord:22,accordingli:[10,19],account:[5,17],accrual:4,accur:12,accuraci:5,achiev:[2,5,10],ack:14,acknowledg:13,across:[3,5,13,14],act:[2,5,10,12,13],action:[6,18,22],activ:[4,6,16],actor:[1,5,13],actual:[4,7,10,12,13,18,20],adapt:[1,12,13],add:[1,10,11,13,17,18,19,20],addarg:18,addcommand:13,adding:[8,10],addinputst:[13,18],addit:[1,2,5,17,18],addition:[12,13,15],addmessagehandl:[10,14],addoutputst:[13,18],address:[2,5,10,13,16,18],adjust:[1,4,15,22],admin:7,administr:[8,9],advanc:[3,4,8],advantag:5,adventur:22,advertis:12,advertisedservic:2,advic:15,affect:[7,12],affection:18,affinityexecutor:1,afraid:1,after:[2,3,4,5,6,7,9,12,13,18,19,21],again:[4,5,10,12,13,16,18],against:[4,5,6,13,18,19],agent:11,aggreg:[5,18,19],agre:[4,6,13],agree:4,agreement:[4,5,17],ahead:13,aim:[1,5],albeit:14,albertsen:14,algorithm:[5,9,14,18,21],alic:[18,21],alice:[18,21],aliceaddr:10,alicegetsback:[18,21],alicenod:10,aliv:13,all:[0,1,2,3,4,5,7,10,11,12,13,14,15,16,18,19,22],allevi:2,allow:[1,2,3,4,5,6,9,12,13,17,18,20,22],allpossiblerecipi:10,almost:[13,18],along:[2,9,10,12,13,18],alreadi:[1,6,12,13,14,18,19,20],alright:13,also:[1,2,3,4,5,6,7,10,11,13,16,17,18,19,20,22],alt:18,alter:[13,18],altern:[0,1,11,17],although:[4,5,9,10,18,19,22],alwai:[1,5,6,11,13,18,19],amounnt:13,amount:[3,4,5,8,13,14],amqp:[9,14],analysi:5,andresen:5,ani:[1,2,3,4,5,6,10,11,12,13,15,16,17,18,19,22],annot:[1,13,18],announc:15,anonym:5,anoth:[1,2,7,11,12,13,18,20],answer:[1,12],anticip:1,any:[3,6],anybodi:5,anyon:[2,18],anyth:[2,5,10,12,13,18,19],anywher:[10,12,18],apach:[9,10],apart:2,api:[0,1,8,9,11,12,13,14,15,16],app:[11,14,15,22],appear:18,append:11,appendix:8,appli:[1,3,4,5,18,19],applic:[5,12,22],applyfix:4,appoint:2,approach:[5,6,8],appropri:[1,10,19],approv:[5,6,13],arbitrari:[1,5,12,13,18],arbitrarili:9,architectur:[8,12],area:[10,17],aren:[13,18,22],arg:[14,18,21],arguabl:12,argument:[1,5,10,13,18],aris:5,around:[5,10,12,13,14,15,17,18,21],arrai:[5,9,13],arrang:13,arraylist:19,arriv:[12,13],arrow:[4,7],artemi:9,articl:[2,5,6,10,12,13,22],artifact:18,ask:[1,13,18],aspect:[6,13,22],assembl:5,assemblesharedtx:13,assert:[1,8],assertequ:13,asset:[3,8,9,13,14,17],assetforsal:13,assetmismatchexcept:13,assettosel:13,assettypenam:13,assign:[12,13],assist:[6,13,18,21],associ:[2,5,6,10,17,18],assum:[5,12,13,18],assume:13,assumpt:13,atom:[5,12,13,16,18],attach:[5,8],attachment:[5,11],attack:2,attempt:[5,7,8,10,13],attent:13,attest:[2,12],attribut:1,audit:[5,13],authent:2,authenticatedobject:[17,18,19],author:[1,2,5,10,13,15,22],authoris:13,auto:[1,18],autom:[5,6,18,22],automat:[0,6,10,13,14,18,22],avail:[0,4,6,10,11,12,15,18],avoid:[1,5,13],awai:[5,13,16],awar:[1,13],awg:15,awkward:[1,13],axi:4,back:[1,5,12,13,17,18],backend:10,background:[1,5,10],backport:15,backtick:18,backward:[13,15],bad:[1,13,18,20],balanc:[2,3,5,18,20],banana:17,bananast:17,banco:14,band:13,bandwidth:1,bank:[4,5,14,17,22],bankrupt:18,bankruptci:[5,12],barreca:14,barrel:14,base:[1,2,4,5,6,8,10,14,17],basi:[4,6,11],basic:[1,2,5,8,10],bat:16,bbva:14,bear:[13,18],beauti:21,becaus:[1,5,7,10,11,12,13,17,18,19,20],becom:[1,4,5,6,13,15],been:[2,4,5,7,12,13,14,15,18],befor:[2,4,5,6,9,12,13,14,15,17,18],beforehand:16,begin:[1,5,16,18,22],behav:18,behaviour:[2,11,19,20],behind:[13,18],believ:14,below:[1,4,5,6,13,22],beneficiari:3,benefit:[2,13,18],best:[1,16,22],bet:12,better:[1,8,9,14,18,21],between:[1,4,5,6,10,12,13,14,15,16,17,18],beyond:[5,18],big:[1,5,13,14,18],bigdecim:12,bilater:[3,4,9,14],bill:18,bin:16,binari:[5,12],bind:[2,5,12],bip:5,bit:[13,18,20,21,22],bitbucket:7,bitcoinj:13,blah:1,blank:[1,18],block:[1,2,5,8,10,12,13,14,18],blockchain:[5,9,13],bloom:1,bloomfilt:1,blotter:16,blow:16,blue:[4,21],bob:18,bobaddr:10,bobnod:10,bodi:1,boil:5,bond:18,bookkeep:[9,18],boost:9,borrow:21,both:[2,3,4,5,9,10,12,13,16,18],bottom:13,bounc:13,bound:[12,13],bower:16,box:[9,22],branch:15,breach:5,bread:22,breadth:13,breviti:19,brief:14,briefli:[10,21],bring:5,broadcast:[5,10],broke:1,broken:18,browser:16,bug:[1,14,15],bugfix:15,bui:[13,22],builder:[13,14,18],built:[13,18],bulk:[5,19],bullet:1,bunch:[16,18],bundl:5,busi:[5,6,9,10,12,13,17,18,22],businesscalendar:17,butter:22,button:16,buyer:8,buyersessionid:13,bytearrai:10,bytecod:[5,13,18],cach:10,calcul:[4,6,13,17,18],calendar:[4,12,17],calibr:5,call:[1,2,4,5,9,10,11,13,14,15,18,19,20],callback:[1,10,13],caller:[2,18],came:13,camel:1,can:[0,1,2,3,4,5,6,7,9,10,11,12,13,14,16,17,18,19,20,21,22],cannot:[2,3,5,7,12,14,18],capabl:18,capit:1,capitan:0,captur:6,cardon:14,care:[1,5,10,12,13,20],carefulli:9,cashkt:18,cashsigningpubkei:13,cashstat:13,caus:[1,18],center:18,certain:[1,9,14,18],certainti:2,cev:7,chain:[5,8,12,13,14,18],chaincash:20,chaincashdoublespend:20,chaincashdoublespendfailswith:20,challeng:5,chanc:[1,13],chang:[0,1],changenotari:2,channel:13,charact:1,charg:12,check:[1,2,6,7,8,12,13,14,17],checkabl:12,checkdepend:13,checksufficientsignatur:[13,17],chf:17,child:13,children:13,childrenfor:13,choic:[1,2,5],choos:[2,7,18],chosen:[2,5],chronolog:6,chunk:[18,22],circl:21,claim:[5,9,18],clash:1,classpath:16,claus:[8,14],clauseverifi:[18,19],clean:[13,14],cleanup:14,clear:[13,17],clearer:[10,13],clearli:1,click:[7,16,21],client:[2,11,12],clock:[6,12,16],clone:[1,7],close:[3,12],closer:2,closur:[1,20],cloud:11,cluster:2,cmd:[18,19],coars:5,code:0,codebas:[1,18],cognit:5,coin:5,collabor:14,colleagu:1,collect:[1,11,14,19],collector:[1,11,13,19],collis:1,colour:16,column:11,com:[0,7,14,16,19,20],combin:[5,8,18,19],come:[5,9,13,14,15],command:[0,2,3,4,5,7,8,11,12,13,14,16,17],commanddata:[12,19],commercial_pap:[18,19],commercialpap:[3,9,18,19,21],commercialpaperlegaci:18,commercialpapertest:[18,21],commit:[2,13,15],commod:17,common:[4,5,13,14,17,18,20],commonleg:4,commonli:18,commun:[7,14],compani:12,companion:[13,18,19],compar:[5,10],compat:15,compel:2,complementari:6,complet:[5,6,10,13,14,16,17,18,19,20],complex:[1,3,5,13,17,18],complic:[13,18],compon:[6,10,14],compos:[13,14,17,18,19],compris:4,comput:[4,12,13],concept:[2,5,6,12,13,14,18],conceptu:13,concern:[5,13,18],conclus:[5,12],concurrenthashmap:1,condit:[2,12,13,20],config:11,configur:[7,11,13,16],confirm:[2,7,10],conflict:[2,5,8],confus:13,connect:[11,18],consid:[1,4,5,12,14,15,18],consist:[4,5,13,14,19],constant:[1,18],constantli:12,constraint:12,construct:[1,2,10,12,13,14,17,18,20,22],constructor:[6,12,18],consult:12,consum:[2,5,6,14,18],consumingtx:2,consumpt:[6,12],contact:[7,13],contain:[2,4,5,10,11,12,13,15,16,17,18,19,20,22],content:[1,2,5,6,7,10,11,12,13,18],context:[1,5,11,12,17],continu:[4,8],contract:2,contractreject:20,contractst:[2,6,14,17,18,21],contractstateref:18,contrast:[5,12,13],contribut:17,control:[1,2,5,7,11,13,14,16,18,22],conveni:[1,5,18],convent:[4,13,19],convers:17,convert:[3,4,13,17,18],convinc:13,copi:[1,5,10,13,18,20,22],copyonwritearraylist:1,copyright:1,corda:[2,3,5,7],cordapp:14,core:[3,10,14,17,18,19,20],corner:7,correct:[2,3,5,14,15,18,20],correctli:[5,12,14,18],correspond:18,correspondingli:1,cost:[12,18],could:[1,2,3,5,12,13,17,18],count:4,countabl:14,counter:[1,13],counterparti:[3,4],countri:[12,17],coupl:[12,13],cours:[11,12,18,22],cover:[2,3,5,12,13,17,18,22],cp_program_id:18,creat:[1,2],createdummyirs:4,createmessag:10,createsomenod:13,creation:[4,5,8,18],creator:12,credit:14,crisp:18,criteria:3,critic:[5,15],crop:5,curl:11,currenc:[3,4,9,14,17,18],current:[1,2,4,5,6,9,10,12,13,14,15,17,18,20,21],currentwallet:13,curv:4,custodi:13,custom:[2,11,14,16,17],customis:22,cut:8,cycl:1,dai:[4,6,11,12,15,17,18,21],daniel:14,danks:14,dashboard:11,data:[0,1,2,4],databas:[5,9,13],dataset:4,date:[3,4,6,8,11,12,15,16],dateoffset:14,daterollconvent:17,david:14,deadlin:17,deal:[1,12,16,17],dealstat:17,debt:3,debug:13,decd098666b9657314870e192ced0c3519c2c9d395507a238338f8d003929de9:11,decd:11,decentralis:12,decid:[7,12,18],decis:[2,5],declar:[1,10,18,20],dedic:1,defaultissu:18,defin:[1,2,5,9,10,11,12,13,14,17,18,19,20,21,22],definit:[2,13,17,18,19],delai:[4,12],delet:[1,5,13,14,18],deliber:[5,20],deliv:[3,10,13,17],deliveri:[9,10,13,16,18],demand:[5,17],demo:[8,14,15],demonstr:[14,16,22],denial:2,denomin:9,dens:1,depend:[1,2,5,6,7,12,13,14,18,19],dependencytxid:13,deposit:[9,18,20],depth:18,deregist:10,deriv:[4,13,18],describ:[1,2,5,6,8,13,17,18],descript:1,deserv:15,design:[1,2,5,8,9,12,18,19,22],desir:[13,17,18],desktop:11,despit:[13,18],destin:10,destroi:[3,5,18],destroypaperatredempt:[18,21],destructur:18,detail:[1,2,3],detect:1,determin:[3,4,6],develop:[1,5,9,10,13,14,15,16,18],devic:5,devis:5,diagram:[4,21],diamond:21,didn:[1,13,15,18],differ:[1,3,4,5,6,12,13,14,17,18,19,20],difficult:[10,13],digest:2,digit:[5,12,13,14,18],digitalsignatur:[2,12,13],direct:1,directli:[1,11,13,17,18],directori:[0,16,18,22],directthreadexecutor:1,dirti:18,disabl:17,disadvantag:5,discov:5,discuss:[5,10,17,18],disk:[13,14,17],disobei:12,disprov:8,disput:[2,4,18],disrupt:10,distinct:1,distinguish:18,distribut:[2,5,8,9,12,13],distrust:[2,13],divid:2,dlg:13,dns:[10,13],doc:[0,1,14,18],docker:11,docsit:[0,15],doe:[1,2,3,4,5,6,9,10,11,12,13,18,20,22],doesn:[1,2,5,7,10,11,12,13,16,18,20],dokka:0,dollar:[18,20],dollars:[18,20,21],domain:[14,17,18,21],don:[1,5,7,9,10,13,15,18,19,20],done:[0,5,13,14,18],dot:4,doubl:[5,9,16,18],doubt:[1,9],down:[1,5,12,18,19],download:[7,8],downsid:[1,5],drag:21,drive:[5,22],driven:16,driver:[14,22],drm:12,dsl:[14,18,20,21],due:[1,4,5,6,9,12,13,18,19],dummi:[3,13,18,20],dummy1:13,dummy2:13,dummy_cash_issuer:20,dummy_notary_key:13,dummy_pubkey_1:[18,20],dummy_pubkey_2:20,dummycontract:13,duplic:18,durat:[6,12,18],dure:[1,4,6,14,18],dynam:[14,18,22],each:[1,2,4,5,6,9,10,12,13,14,15,18,19,20,22],earli:[1,18,21,22],earliest:[4,6],eas:10,easi:[1,5,9,12,14,18],easier:[1,13,18],easiest:18,easili:[1,12,13,16],econom:4,ed25519:14,edition:7,editor:7,effect:[4,5,13,20],either:[1,2,3,4,5,12,13,18,19,20,22],elbonia:17,element:[1,5,19],elimin:9,els:[2,5,13,18,19],emb:[6,18],embed:[5,11,12],emit:18,empti:[14,18,20],emptyledg:20,enabl:18,encapsul:[1,17],enclos:1,encod:12,encount:9,encrypt:9,encumb:18,encumberedst:18,encumbr:18,encumbranc:8,end:[1,4,9,12,13,15,19,22],endpoint:11,enforc:[1,5,18],enforceverifyorfail:20,engin:18,english:[1,18],enorm:13,enough:[1,7,10,13,18,22],ensur:[1,2,5,7,10,13,15,16,17,18],ensure:[2,7],enter:[18,20,22],entir:[2,4,5,10,12,18],entireti:4,entiti:[2,5,12,18],entri:[4,5,13,18],enumer:4,environ:[1,12,13],envisag:18,equal:[2,13,18,19,20],equival:[1,4,17,18],especi:[17,21],essenti:[11,12,17,18,19],establish:[6,16],etc:[1,3,4,12,13,14,15,17,18],euribor:[11,12],evalu:[4,12],even:[5,9,10,12,13,14,18,20],event:[1,2,4,5],eventual:15,ever:[1,5],everi:[2,5,12,13,14,15,18,22],everybodi:[5,12],everyon:[2,12],everyth:[2,10,18,22],evid:12,evolut:5,evolv:[18,22],exact:[12,18],exactli:[5,10,18],examin:[1,5,12,13,18],exampl:[0,1,2,3,4,5],excel:12,except:[1,13,18,19],exception:[1,13],excess:1,exchang:[4,13,17,18],exclus:3,execut:[5,6,12,16,17,18],executor:[1,10],exercis:18,exhaust:14,exist:[1,2,3,4,5,6,8,14,18,20,22],exit:[3,13,18],expect:[1,3,6,10,13,15,18,19,20],expectedtypenam:13,expectfailureoftx:18,expens:1,experi:[15,22],experienc:5,experiment:[1,6,13,14],explain:[1,6,10,13,14],explan:1,explicit:[1,5,12,13],explicitli:[1,5,18,20],explor:[1,5,7,8,9,11,13,18,22],exploratori:10,expos:[1,6,10,11,12,13,17],expose:17,exposur:[3,4],express:[4,5,9,12,13,14,18,20],extend:[1,2,9,17,18,19],extens:[1,14,17,18],extent:5,extern:[13,22],extract:[5,11,12,13,17,18],extractcommand:19,extractgroup:19,extrem:[5,12,18],face:[9,18,21],facevalu:18,fact:[1,2,4,5,12,13,18,20],factor:[4,5],factori:6,fail:[10,18,20],failswith:20,failur:[13,18,20],fairli:[1,13],fake:[16,18,22],fals:[1,10,12,13,17,18],familiar:[5,18],famou:14,far:[13,16,18],fashion:1,fast:[5,10,13,16],fault:13,featur:[1,13,14,15,18,21],feed:12,feedback:14,feel:[18,22],fetch:[10,11,12],few:[1,9,10,11,12,13,15,16,18],fiber:13,field:[1,4,12,13,14,18,19,21],file:[0,1,5,10,11,13,14,15,16,17,18,22],fill:[1,13,16,18],filter:[1,19],filterisinst:18,finalis:[4,13],financ:[13,14,22],financi:[5,6,8,13,14],find:[0,5,11,13],fine:[5,20],finish:[10,13],firm:18,first:[1,2,4,6,7,10,11,12,13,14,16,17,18,19,22],firstli:18,fit:[1,5],fix:[1,3,4,5,6,8,9,10],fixabledealst:17,fixedleg:4,fixedlegpaymentschedul:4,fixedratepaymentev:4,fixingroledecid:6,fixingsessioninitiationhandl:6,fixof:12,flag:[11,22],flexibl:[2,5],flight:5,floatingleg:[4,6],floatinglegpaymentschedul:4,floatingratepaymentev:4,flow:[1,4,18,19],flux:22,fly:13,fold:1,folder:0,follow:[0,1,2,5,6,7,8,10,11,12,13,16,17,18,19,20,21],font:1,foo:[1,10],foobrokenexcept:1,fooutil:18,forc:[5,11,14,18,20],fordai:[6,12],forev:15,forget:[13,18],form:[2,5,6,13,16,18,19],formal:[10,18],format:[0,1,5,11],forth:13,forward:[10,12,13,15,16],found:[7,11,12,13,15,19,22],four:[9,18],fourpmtimelock:18,frame:[1,13],framework:[5,8,9],free:[5,12,13],freeform:18,freeli:12,frequenc:4,frequent:13,fresh:[12,18,20],freshkei:13,freshli:[17,18],from:[0,1,2,3,4,5,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22],fromcountri:17,front:18,frustrat:5,fulfil:3,full:[1,2,3,10,13,18,19],fulli:[1,5,10,13,14,17,18],fullysign:13,fun:[2,6,12,13,18,19,20],fund:5,fundament:[2,5,8,18],fungibl:[3,9,17,18,19],fungibleasset:[3,8,14],funni:13,further:[4,5,9,17],futur:[2,3,5,12,13,17,18,21,22],gain:9,game:13,garbag:[1,11,13],gather:18,gavin:5,gbp:17,gcd:5,gear:15,gener:0,generateiniti:13,generateirsandfixsom:4,generateissu:18,generatemov:18,generateredeem:18,generatespend:[13,18],genuin:1,get:[1,2,5],getamount:20,getbefor:18,getbloomfilters:1,getclass:18,getclaus:19,getcommand:[18,19],getdummy_cash_issuer:20,getdummy_pubkey_1:20,getdummy_pubkey_2:20,getencumbr:18,getfacevalu:18,getfix:4,getifmatch:19,getifnotmatch:19,getinput:[14,18],getinstat:14,getissuanc:18,getkei:18,getlegalcontractrefer:[18,19],getmaturityd:18,getmega_corp:20,getmega_corp_pubkey:20,getnotarysignatur:2,getoutput:[14,18],getoutst:14,getowner:[18,19],getprogramref:18,getprotocoltrack:13,getrequiredcommand:19,getsign:[18,19],getter:18,gettim:18,gettimestampbi:18,gettransact:13,getvalu:[18,19],git:[7,15],github:0,giusepp:14,give:[2,5,13,18],given:[2,5,10,12,13,18],givenpric:13,global:[1,5,12,14],glue:13,gnu:0,goal:[1,5,8,9,13,15],goe:16,gone:[13,14,18],good:[1,7,13,18,20,21,22],got:[11,13],gover:18,gps:[5,12],grade:17,gradl:[7,15],gradlew:[7,16],grammar:1,granular:5,graph:[5,9,11,13,18,21],graphit:11,great:14,greater:1,greatest:5,green:7,groom:5,group:[3,5,8,10],groupclaus:19,groupclauseverifi:19,groupstat:[18,19],guarante:15,guava:1,gui:13,hack:[5,14],had:[2,13,14,18],hand:[6,13,18],handa:14,handi:13,handl:[1,2,5,10,13,14,18,19],handler:[6,10,13],happen:[1,2,5,6,12,13,15,18,20],happi:16,hard:[1,5,13,15],harder:[5,18],hase:4,hash:[2,5,9,11,12,13,17,18],hashcod:18,hasn:7,hassl:13,hat:15,have:[1,2,3,4,5,6,7,9,10,12,13,14,15,16,18,19,20,22],haven:18,heap:13,hearn:5,heart:18,heavi:15,heavili:5,hedg:[3,4],heirarchi:1,held:18,hell:13,hello:13,help:[1,5,6,10,13],helper:[4,10,17,18],henc:[2,4,5],her:[18,21],here:[1,5,9,10,11,12,13,14,17,18,20,21,22],hierarch:13,hierarchi:13,high:[5,12,13],higher:[1,2,7,18],highlight:[14,18],histori:[2,13],hit:[5,7],hoc:14,hold:[5,10],holder:[1,5,18],holidai:[4,12,17],home:[7,16],hood:[13,20],hopefulli:22,hotspot:1,how:[1,3,5],howev:[2,3,4,5,10,12,13,17,18,19,20],html:[0,1],http:[0,7,11,12,16,18,19,22],hub:13,human:[5,12,13],hundr:13,hurt:13,hypothesi:8,ide:[7,9],idea:[1,5,7,9,13,18,22],ideal:[13,18],ident:[2,5,12,13,17,18,19,20],identifi:[4,5,9,10,11,12,13,17],identiti:[2,17],identityless:5,identityservic:13,ifmatch:19,ifnotmatch:19,ignor:[18,19],illeg:12,illegalargumentexcept:[1,12,13,18,19,20],illegalstateexcept:1,illustrat:1,imagin:[1,13,18],immedi:[5,18],immut:[1,4,5,12,18],immutabl:[1,5],imper:1,implement:[1,2,3,4,5],impli:13,implic:[2,5],implicitli:4,important:15,impos:[12,13,18],imposs:[5,12],improv:[14,15,18,19,21],improve:5,improvement:14,inbackground:10,includ:[1,2,3,5,7,8],incompat:20,incorpor:12,increas:[1,10],indent:1,independ:[2,12,19],index:[4,5,6,7,18],indexsourc:6,indic:[1,4,6,10,13,14,18],individu:[1,10,16,18,20],industri:[8,9,11],infer:[18,20],infix:18,influenc:11,info:13,inform:[1,2,5,13,17,18,19],infrastructur:[5,9,11,13],inher:5,inherit:[1,10,18],init:12,initi:[2,10,13,14,18,22],initialis:[2,13],inmemorymessagingtest:10,inner:19,inoutgroup:[18,19],input:[2,3,5,12,13,14,17,18,19,20,21],inputcash:20,inputindex:2,insert:[1,10,11,12,13],insid:[5,10,13,16,18],inside:18,instal:[0,6,7,16],install:[7,16],installdist:16,instanc:1,instance:[18,19,20],instant:[1,6,12,13,17,18],instanti:[5,6,13,14],instat:20,instead:[1,5,6,9,13,14,16,18,22],instigat:2,institut:[5,9],institutionrefer:18,instruct:[11,18],instrument:[3,4,6],insuffici:5,insufficientbalanceexcept:18,integ:[14,18],integer:18,integr:[1,12,13,14,21],intellig:1,intend:[1,3,5,11,12,13,17,20],intent:[12,18,21],intention:1,inter:[9,14],interact:[1,5,12,13,14],interchang:17,interestrateswap:9,interfac:[1,3,6,8,9],intern:[1,9,10,17,18],internalis:1,interop:[9,18],interpret:[1,5,18],intersect:18,interv:17,intesa:14,introduc:[1,2,6,12,14,17,18],introductori:8,intuit:1,invalid:[2,12,13,18],invari:18,investig:13,invoc:10,invok:[1,5,6,10,11,13,14,18],involv:[2,3,5,10,12,13,17,18,22],ipsa:12,irrelev:6,irs:[3,4,8,14],irsdemo:16,irsexport:4,irstest:4,irsutil:4,irswebdemo:16,isbefor:18,isempti:18,isinstanc:13,isn:[1,13,18,22],issu:[2,3,5,9,10,12,13,14,15,17,18,19,20,21,22],issuanc:[3,13,17,18,19,21],issue:[3,18,19,21],issuedbi:20,issuer:[3,5,13,18,20],item:18,iter:[13,15,18],itself:[2,4,5,6,10,11,12,13,18,20],jar:[0,5,11],jarinputstream:5,java:[1,5,6,9,10,11,13,14,18,19,20,22],javaclass:13,javacommercialpap:[18,19],javadoc:1,javatesthelp:20,jdk1:7,jdk:[7,13,14,18],jetbrain:[7,9],jmx2graphit:11,jmx:11,jmxtran:11,job:22,johann:14,join:[10,18],joint:18,jolokia:11,json:[11,22],judgement:1,jump:16,junit:18,just:[1,5,7,10,11,13,14,17,18,20,22],justifi:8,jvm:[5,9,11,13,22],kafka:10,kdoc:1,keep:[5,13,18,21],kei:[1,3,5,9,10,12,13,17,18,19,20],kept:13,key_mismatch_at_issu:18,keymanagementservic:13,keypair:[13,18],keyword:[1,18,20],kick:13,kind:[5,9,10,12,13,18,22],know:[2,5,6,9,12,13,16,20],knowledg:12,known:[4,5,8],kotin:18,kotlin:[0,1,7,8],kryo:[10,13],label:[13,18,20,21],labori:18,lack:5,lambda:20,land:4,lang:20,languag:[1,5,7,8,9,14,17,18,21,22],larg:[5,12,13,14,17,18,22],larger:[1,5],last:[15,20],lateinit:13,latenc:[2,12],later:[1,5,9,10,12,13,14,17,18,19],latest:[1,7,14],latter:[1,18],launch:6,layer:[5,10,13],layout:21,lead:[1,5,18],leak:[2,5,13],learn:[5,8,13,16,18,22],least:[12,18],leav:[1,13],ledger:[2,3,4,5,8,11,12,13,14,18,20,21],ledgertransact:17,left:[10,13,16,19,20],leg:[4,6,9],legal:[2,5,12,17,18],legalcontractrefer:[18,19],legallyidentifi:[2,12,13],legallyidentifiablenod:13,less:[13,18,21],let:[1,5,6,11,12,13,14,16,17,18,19,20],letter:1,level:[1,2,4,7,10,12,13,17,18,19,20],lib:0,liber:1,libor:[4,11,12],librari:[1,11,12,13,17,18],licens:1,life:22,lifecycl:3,lifecyl:3,lifetim:4,lightweight:13,like:[1,2,4,5,6,7,10,11,12,13,15,17,18,19,22],likewis:18,limit:[3,5,8,18],line:0,linearst:17,liner:1,link:[1,5,12,13,17,18],linkabl:5,linux:[11,14],list:[0,5,10,12,13,14,15,16,17,18,19],listen:1,listenablefutur:13,listof:[13,19],liter:5,littl:[1,18,20],live:4,livelock:5,load:[2,5,14,16,17,18,22],loan:[3,4,12],local:[0,5,7,11,12,13,20],locald:12,localhost:[11,16],locat:[17,18],lock:[1,3,18],log4j:14,log:[13,14,16],logger:13,logic:[2,5,6,9,10,13,14,18,19,22],longer:[1,4,12,13,14],look:[1,4,10,11,12,13,15,18,19,20,22],loop:[1,4,18],loquitur:12,loss:12,lot:[1,4,5,16,22],low:[2,13],lower:[1,12],lurch:13,mac:11,machin:[5,6,8,10,12],macos:16,made:[1,4,5,8,13,14,15,19],mai:[1,5,9,10,11,12,13,14,15,18,19,20,22],mail:[15,16],main:[6,13,16,18,21,22],maintain:[2,5],maintan:12,mainten:10,major:15,make:[0,1,2,4,5,10,12,13,14,15,16,18],makenod:10,maker:9,maketransact:13,malici:13,manag:[5,8,11],mani:[1,5,6,9,10,12,13,14,17,18],manipul:17,manner:13,manual:[6,10],map:[1,2,4,8],mappabl:18,mark:[1,3,13,18],markdown:1,marker:[13,18],market:8,master:15,match:[5,10,12,13,18,19],matchbehaviour:19,matter:18,matur:[3,4,11,12,18],maturityd:18,maven:7,maximis:5,maximum:5,maybestx:13,maybetraderequest:13,mbean:11,mean:[1,5,6,10,12,13,17],meaning:[2,3],measur:[4,18],mechan:[14,18],meet:18,mega_corp:[13,18,20],mega_corp_key:[13,18],mega_corp_pubkey:[20,21],megacorp:[13,18,21],member:[4,14],memori:[2,8],menlo:1,mention:[6,13,18],menu:7,mere:[4,18],merg:[5,9,14,17,18],mess:13,messag:[1,5,8,9],messagehandlerregistr:10,messagerecipi:10,messagerecipientgroup:10,messagingservic:[10,13],method:[1,6,8,10,11],metric:11,micro:19,middl:[1,10,13],might:[1,4,5,7,13,18],mike:5,mileston:8,mind:[1,12,13,18],mine:5,mini_corp_pubkey:13,minim:[5,13],minimis:[2,3,5,10],minimum:[4,5],minor:15,minu:18,minut:[9,12],misc:10,mismatch:20,miss:[1,13,18,20,22],missingsig:13,mission:11,mix:[1,13,18],mock:[10,13],mocknetwork:13,mocknod:13,mockservic:17,mode:10,model:1,modest:5,modif:[17,18],modifi:[2,3,4,7,13,17,18,19],modul:[1,10,13,14,18],moment:[10,13,14],monei:[12,18],monetari:18,monitor:[1,8],month:[4,13,15],more:[1,2,3,4,5,9,10,11,12,13,14,16,17,18],moreexecutor:1,mortensen:14,most:[1,4,5,10,11,12,13,18],mostli:18,move:[3,13,14,15,18,19,20,21],movement:[13,18],much:[1,5,9,13,14,18,22],multi:[1,9,13,18],multilater:[3,14],multipli:4,must:[1,2,3,5,6,10,11,12,13,16,17,18,19,22],mustafa:14,mutabl:[1,5,17,18],mutat:5,mutual:[2,3,13],myfil:11,mykei:17,mykeypair:13,nail:1,namedbyhash:17,namespac:13,narrow:1,nativ:13,natixi:14,natur:18,naval:[5,12],navig:16,navistar:12,neat:20,necessari:[1,2,15,16],nee:14,need:[0,1,2,4,5,6,8,10,11,13,15,16,17,18,19,20,22],negoti:[5,17],neither:[13,18],nest:13,net:[3,4,13,14,18,21],nettabl:9,network:[2,5,6,8,9],neutral:9,never:[1,5,12,18,19],newli:[6,13],newnotari:2,newowner:18,newsecurerandom:14,next:[1,4,6,7,13,14,18],nextfixingof:6,nextscheduledact:6,nice:16,nio:1,nix:16,noddi:11,node:[2,3,5,6,8,9,10],nodea:16,nodeb:16,nodeinterestr:12,nodej:16,nodeservic:12,non:[0,1,2,5,8,13,14,16,17],none:[6,13,19],nonemptyset:14,nordea:14,normal:[3,4,13,17,18,19],not_matured_at_redempt:18,notabl:1,notaris:[2,17],notarychang:14,notarychangeprotocol:2,notaryexcept:2,notarynod:13,notaryprotocol:2,notaryservic:14,notarytous:17,notat:13,note:[0,1,3,4,5,8,13],noth:[1,5,6,14,18],notic:[1,18],notif:10,notifi:10,notion:[4,5,18],notnul:[18,19],now:[1,5,7,10,12,13,14,16,17,18,20,21,22],npm:16,nugget:18,nullabl:18,nullpublickei:18,number:[1,3,4,5,10,12,13,15,16,17,18],numer:5,obj:18,object:[1,3,4,5,6,9,10,11,12,13,14,17,18,19,21,22],oblig:[3,4,9,14,17],obligor:3,observ:[4,5,6,12,13],observatori:[5,12],obsolet:6,obtain:1,obviou:[1,2,5,12],obvious:4,obviousli:18,occasion:8,occur:[2,6,12,13,18],occurr:12,odd:[13,18],off:[10,13,18,21],offer:13,offlin:10,offset:4,often:[1,3,4,5,12,13,18],oftenor:12,oil:[14,20],old:2,omit:6,onc:[1,2,9,10,12,13,15,17,18],once:[0,4,6,13,17,18,22],one:2,onli:[1,2,4,5,9,10,11,12,13,14,18,19,21,22],only:13,onto:[1,13,18,21],opaqu:[9,10],opaquebyt:18,open:[2,5,7,12,13,16,21],openjdk:7,oper:[4,6,10,11,12,13,18],optim:1,option:[0,1,4,6,10,12,13,18,19,22],oracl:[4,5,7,8,10,11],orchestr:[8,9,14,22],ordain:4,order:[0,1,2,3,4,5,9,10,13,17,18,19,21],ordinari:[5,13,18],org:[0,7,16,18,19],orient:8,origin:[17,18],originalst:2,otc:9,other:[1,2,3,4,5,6,9,10,12,13,16,17,18,20],othersid:13,otherwis:[1,6,13,18,19],our:[1,2,5,6,13,14,15,18,20],ourselv:[13,18,22],oursignatur:13,out:[1,2,3,5,6,7,9,11,12,13,15,18,19],outag:10,outcom:13,outer:19,outermost:19,outlin:[5,8,13],outpoint:5,output:[2,3,5,12,13,14,16,17,18,19,20,21],outref:13,outsid:[5,10,12,13,18,22],outstand:3,outstat:18,over:[1,2,4,5,10,11,12,13,17,18],overal:[2,6,10,20],overdu:6,overflow:1,overload:13,overnight:17,overrid:[6,13,18,19],overwhelm:5,own:[1,2,3,10,11,12,13,14,15,18,20,21,22],ownablest:[13,17],owned_bi:18,owner:[13,17,18,19,20],ownership:[13,18],owningkei:[13,18],ozturk:14,p2p:[13,14],pack:18,packag:14,packet:5,page:[7,12,16,18],pai:[3,12,13,18,21],paid:[3,4,5],pair:[5,13,18],paper_1:[18,21],parallel:[5,10,13],parallelis:5,paramet:[1,6,13,16,18,19],parameteris:5,parent:13,pars:[12,18,22],part:[1,2,3,5,6,12,13,14,17,18,19,22],parti:[1,2,3,4,5,6,8,9,10,12],partial:[2,13,18,20],partialtx:13,particip:[2,5,14,18,22],particular:[1,2,5,11,13,14,18],partyandrefer:1,partynod:13,partyrefer:[1,18],pascal:1,pass:[2,10,13,18,19,21],past:[1,12,16,18,22],patch:1,path:[1,6,11,14,18],pattern:[1,5,18],paye:5,payer:[4,5],payment:[3,4,5,6,12,13,16,18,21],pdf:12,peer:[9,10,12,13],penni:18,peopl:[1,5,9,18],per:[1,5,6,22],perform:[1,2,4,5,6,12,13,16,18],perhap:[1,5,6,18],period:4,perman:18,persist:[9,10,13,14],perspect:[5,13,18],phrase:12,physic:[2,12,14],pick:[10,13,14,15,18,22],piec:[1,2,5,10,13,18,20],ping:10,pip:0,pki:[5,14],place:[0,1,4,5,6,9,10,12,13,14,15,17,18,22],plai:13,plan:[10,16],platform:2,pleas:[1,5,7,14,16,18],pluggabl:14,plugin:[7,11],point:[1,2,3,5,6,11,12,13,15,18],pointer:[2,13,17],pointless:1,pong:10,pool:[1,5,13],poor:5,pop:[7,10],popular:9,popup:7,port:[14,15,16],posess:13,posit:[1,2,5,13,18],possess:2,possibl:[5,10,12,13,18],post:19,potenti:[1,2,9,13,18],pound:18,pounds:18,power:[5,8],practic:[5,18],pre:[0,4,5,13,18,20,22],preced:18,precis:[5,9,12],precondit:1,prefer:[1,5],prefix:[1,13],preliminari:10,prepar:[5,18],present:[2,3,4,8,12,17,18,19],preserv:[2,5],press:18,pretend:[11,17],pretti:[5,13,18],prevent:18,previou:[5,14,17,20],previous:[4,6,12,14],price:[5,12,13],primari:[9,12],primarili:3,primit:[18,20],print:16,priv:13,privaci:[1,2,5,13,14,18],privat:[1,5,13,18,19,22],privatefoo:1,probabl:[7,12,18,22],problem:[2,5,12,13],proce:13,procedur:13,process:[2,4,5,6,8,9,10,11],processor:5,produc:[0,6,18,20,21],product:[1,6,8,9,15,17,18],profit:[18,21],profound:5,program:[1,5,10,11,13,14,16,17,18,22],programref:18,progress:[2,4,8],progresstrack:13,project:[7,14,16],prolif:14,promis:14,proof:[5,8],propag:[8,11,18,19],properli:13,propos:[8,13],prose:[12,17],protect:13,protocol:[2,5,6,8,9,10,11,12],protocollog:[6,13],protocollogicref:6,protocollogicreffactori:6,protocolstatemachin:13,protocoltrack:13,prototyp:[1,5,8,9,12,18],prove:[2,5,8,18],provid:[0,1,2,3,4,5,10,11,12,13,14,17,18,22],provision:17,pseudo:12,ptx:13,pubkei:20,publicfoo:1,publickei:[8,13],publicli:8,pull:7,pump:10,punish:12,purchas:[13,16],pure:[3,5,12],purpos:[3,9,13,18],push:15,put:[1,13,15,18,22],python:0,qualiti:8,quantiti:[5,9,18],quasar:13,queri:[4,6,12],question:[1,2,6,7,12],queu:10,queue:[1,10,13],quick:12,quickli:[5,10,18],quit:[1,12,13,18],r3corda:[14,16,19,20],r3dlg:15,r3prototyp:[0,7,16],r3repositori:7,rais:[2,19],random63bitvalu:13,random:[5,6,13,14],rang:12,rapid:[1,9,15],rate:1,ratefixprotocol:12,rather:[1,5,13,14,18],raw:[11,13],reach:[2,4,5,6,12],reachabl:13,read:[1,5,8,9,11,12,13,18,22],readabl:[9,13],reader:18,readi:[15,18],readili:17,readme:1,real:[1,10,12,14,17,18,22],realis:13,realism:10,realist:17,realiti:4,realli:[1,2,5,13,18],reason:[1,4,5,13,17,18],reassign:18,recal:4,receiv:[3,4,5,10,12,13,15,18,21],receiveandcheckproposedtransact:13,receiveandvalidatetraderequest:13,recent:14,recipi:[3,5,10,18],recognis:[5,12,18],recommend:[1,10,22],record:[2,6,10,13],recordtransact:[6,13],recov:10,recreat:13,red:[4,7],redeem:[3,9,18,19,21],redempt:[18,21],redemptiontim:[18,21],redesign:14,reduc:1,redund:1,ref:[13,18,20],refactor:14,refer:[1,2,3,4,5,6,9,12,13,14,17,18,20],referenc:2,refin:9,reflect:[18,19],refus:7,regard:2,regardless:13,regener:[4,15],regist:[1,10,11,13,22],registr:10,regular:[11,13,18],reissuanc:[5,18],reject:18,rel:[5,10,19],relabelablestep:13,relat:[4,18],relationship:18,releas:8,relev:[5,14,17,19],reli:5,reliabl:10,relianc:5,relic:11,religi:1,remain:[6,18,21],remeb:7,rememb:[1,6,7,13,18],remind:13,remot:7,remov:[10,13,18],renam:14,render:[1,13,21],repeat:[1,4,10,13],replac:[2,4,7,11,14,15,17,18],replic:5,repoint:2,report:[10,19],repositori:[1,7],repres:[1,3,4,5,10,12,13,17,18],represent:4,request:[2,5,10,12,13,14],requestingparti:2,requiredcommand:19,requiresinglecommand:[18,19],requirethat:[18,19],research:14,resel:12,reserv:13,reset:4,reshap:5,resolut:[2,5,8,13],resolv:[1,13,17],resolvefromtwohash:13,resolvetransactionsprotocol:13,resolvetransactionsprotocoltest:13,resourc:[13,16],respect:[1,5,13,16,18],respend:5,respons:[2,5,6,10,12,13],rest:[2,5,9,10,11,13,14,22],restart:[7,13],restor:13,restrict:1,restructur:19,restructuredtext:0,result:[1,2,4,5,12,13,18,19],resultfutur:13,resum:[13,14],resurrect:13,retain:10,retri:[9,10,13],retriev:[2,4],retrieveoutput:20,reus:[5,13,20],reusabl:[12,14,18,19],reveal:[2,5,13,18],revers:13,revert:3,review:[1,14,15],revis:4,rewrit:13,right:[1,7,10,11,13,15,22],rigid:5,rigidli:1,risk:13,robert:14,robust:14,role:[6,16,22],roll:[4,13,16],rollov:[17,18],root:[15,16,18,21],rotat:14,roughli:[12,15],rout:13,router:10,rui:14,ruin:20,rule:[1,12,13,14,18],run:[0,1],runbuy:13,runnetwork:[10,13],runsel:13,runtim:[1,13],safe:[1,5,13,18],safeti:1,sai:[1,2,5,18],sale:[16,18],same:[1,2,3,4,5,6,9,10,12,13,16,18,19,20,21],sandbox:[5,6,9,18],saniti:13,santiago:14,satisfi:18,save:[1,14,18],scala:[9,18],scalabl:[1,5],scale:4,scenario:[5,22],scene:[13,18],schedul:4,schedulablest:6,scheduledact:6,scope:[5,18,19],scotiabank:14,scrape:11,scratch:[17,22],screen:[1,7],script:[0,5,18],scroll:16,scrub:13,seamless:9,search:[7,13,18],second:[4,13,16,17,18],secondari:13,secp256r1:14,section:[5,15,18],secur:[5,6,10,13],securehash:[2,18,19],securerandom:14,see:[0,1,2,3,4,6,9,10,12,13,16,17,18,19,22],seed:13,seek:5,seem:5,seen:[1,4,12,13,18,21],select:[2,7,14,18,19],self:14,sell:[13,18,22],seller:8,sellerownerkei:13,sellersig:13,sellertradeinfo:13,semi:[5,12],send:[1,5,10,11,12,13,15,18,20],sendandrec:13,sender:5,sendsignatur:13,sens:[4,12,13,18],sensit:6,sent:[6,10,13,18],separ:[2,5,11,12,13,16,17,18],sequenc:[5,10],sequenti:[10,13],seri:13,serial:[9,10,18],serialis:[1,5,9,10,13,18],serializablewithkryo:18,serializeablewithkryo:18,seriou:[5,15],serious:22,server:[11,12,22],servicehub:[6,13],session:[6,10,13],sessionid:[6,13],set:[2,4,5,6],setof:[13,19],setter:18,settim:[13,17],settl:[3,10,12,13,17],settlement:[3,13],setup:[6,13],setupa:16,setupb:16,sever:[5,13,18,20,22],sha256:[18,19],sha256sum:11,sha:[5,11],shape:5,share:[4,5,12,13,14,18,19,22],shasum:11,she:18,shortcut:9,shorthand:[18,20],shot:10,should:[1,2,3,5,6,7,9,10,13,14,16,17,18,19,20,22],shoulder:1,shouldn:[13,18],show:[5,7,9,16,18,21],shown:[13,18],shutdown:13,side:[12,13],sig:18,sign:[2,4,5,9,10,12,13,14,17,18,19,20],signatureexcept:13,signaturesfromsel:13,signedtransact:[13,17,18],signer:[12,18,19],signific:[5,14],significantli:4,signoff:12,signwith:[13,17,18],signwithecdsa:13,signwithourkei:13,silver:1,similar:[1,5,10,12,14,18,19],simpl:[1,3,4,5,9,10,11,13,18,19,21],simplecash:20,simplecashdoesntcompil:20,simplecashfailswith:20,simplecashsuccess:20,simplecashtweaksuccess:20,simplecashtweaksuccesstopleveltransact:20,simplenotaryservic:2,simpler:[5,9],simplest:[5,13,18,22],simpli:[1,2,5,10,13,17,18,20],simplif:14,simplifi:[1,3,5,10,17,18,22],simultan:[5,10,13,18],sinc:18,singl:[1,3,5,8,11,12,13,18,19],singleclaus:19,singlemessagerecipi:[10,13],singleton:[13,18,19],singletonlist:19,sit:10,site:[1,15],situat:[1,5],size:[1,4,5,13,18,19],skeleton:13,skip:[13,17],slight:18,slightli:18,slip:15,slow:[1,5],slowest:5,small:[5,6,12,13,16,18,21],smaller:14,smart:[8,9,12,13,14],smm:13,smooth:18,snake:20,snapshot:[5,14,15],snide:0,snippet:[2,13,18],softwar:[13,15,22],sofu:14,sold:[13,18,21],solv:[5,12,13],solvenc:12,some:[1,2,3,5,6,9,10,11,12,13,14,16,17,18,19,20,21,22],somed:18,someon:[2,5,10,18],someprofit:[18,21],someth:[1,4,5,7,16,17,18,19,22],sometim:[5,10,11,12,13,18],somewhat:[5,13,14],somewher:[18,21],sophist:5,sort:[12,13],sound:[1,13,18,21],sourc:[4,6,7,12,13],sparingli:1,special:[2,5,20],specialis:[13,19],specif:[2,5,6,10,11,12,13,14,17,18,19,21],specifi:[0,1,2,3,5,9,10,12,13,14,18,19,20,22],speed:[5,13],spend:[5,9,13,18],spent:[5,20],sphinx:0,sphinx_rtd_them:0,spirit:14,split:[5,9,14,17,18],spread:[2,10,13],spreadsheet:12,squar:21,src:[16,18,21,22],ssl:[9,14],stabilis:15,stabl:15,stack:13,stage:[1,13,18,22],stai:[5,18],stake:5,standalon:12,standard:[1,8,11,13,17,18,19],standardis:[5,17,18],start:[1,4,5,6,8,10,11,13,16],startprotocol:13,state:[2,3,4,5,6,8,9,10,12],stateandref:[2,13,17,18],statehistori:2,stateless:5,statemachinemanag:13,statement:[1,5,12,13,18],stateref:[2,5,6,17],statesoftyp:13,statist:11,status:5,step:[6,8,12,13],still:[2,5,6,13,14,18,22],stock:[5,12],stop:[1,10,13],stopnod:13,storag:[5,13],store:[2,13,14,17,18],stori:[1,14],straightforward:[13,18],stream:[13,19],stress:1,strictli:[4,5],string:[10,12,13,18],strong:9,structur:[1,5,7,9,12,13,18],studi:18,stuff:[1,13],stx1:13,stx2:13,stx:[13,17],sub:[1,13],subclass:[13,17],subclaus:19,subgroup:5,submiss:12,submit:[1,2,10,13,16],subprotocol:[2,13],subscrib:10,subsequ:[18,20],subset:3,subtask:13,subtl:[1,5],successor:[2,6,9],succinct:1,sudo:[0,16],suffer:5,suffic:12,suffici:[5,8,10,12,15,17],suffix:18,suggest:[10,18],suggestinterestrateannouncementtimewindow:6,suit:14,suitabl:[6,10,15],sukrit:14,sum:[18,20],sumcashbi:[13,18],sumcashornul:18,summari:[8,14,15],summaris:5,sun:1,superclass:[13,14,17],superior:1,supersed:5,supertyp:18,suppli:[3,16],support:[1,2,3,4,5,8,9,10,12,13,14],suppos:[13,18],suppress:[1,14],suppresswarn:1,sure:[2,14,15,16,18,22],surfac:13,surround:[1,18],surviv:13,suspend:8,swapsignatureswithsel:13,symbol:7,synchronis:[1,5,12],syntax:[9,18],system:[2,5,9,11,12,13,14,16,18],tab:[1,7],tackl:[14,19],tag:[1,15],tailor:8,take:[1,4,6,9,13,15,17,18,19,20,21],talk:13,tamper:13,target:[0,1,5,9,11,13],targetrecipi:10,task:[5,6,13],team:7,teardown:13,techniqu:[1,5,12,18],tell:[0,10,13],templat:17,tempor:12,temporari:5,temporarili:[13,15],tempt:18,temptat:13,ten:18,tenor:[4,11,12,17],term:[3,5,6,17,18,19],termin:[4,11,13,16],terminolog:5,test:[0,3,7,8,9,10],test_tx_time:18,testtimelock:18,testutil:18,testwithinmemorynetwork:10,text:[1,7,11,20],than:[1,2,5,8,11,13,14,18,21],thank:14,thedao:14,thei:[1,3,4,5,6,9,10,11,12,13,15,16,17,18,19],theirsessionid:13,them:[1,4,5,6,7,9,10,11,13,14,15,16,17,18,20,22],themselv:[10,12,13,17,18],theori:[8,12],therefor:[5,7,9,13,15,18],thi:[0,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22],thing:[1,5,6,9,12,13,14,16,17,18,22],think:[1,5,7,13,18],third:[5,16,18],thisstateref:6,those:[5,6,10,11,12,13,16,17,18],though:[10,11,13,18],thought:[5,9],thousand:20,threadsaf:1,three:[16,17,18],threshold:18,through:[4,5,6,11,13,14,18,19,20,22],throughput:[2,5],throwifsignaturesaremiss:13,thrown:[18,19],thu:[1,5,6,11,12,17,18],tidi:13,tighten:18,tightli:13,time:[1,2,3,4,5,6,9,11,12,13,14,16,17,18,21],timelin:18,timestamp:1,timestampauthoritysig:13,timestampcommand:[12,18],timestampercli:18,timestamperservic:12,timestampingauthor:13,timestampingprotocol:13,titl:7,tls:14,todo:[1,13,18],togeth:[3,5,13,14,18,19],token:[17,19],told:1,toledgertransact:[13,17],toler:[2,6,12],tolist:19,too:[1,13,18,21],took:13,tool:[9,11],toolbar:7,top:[1,5,7,13,16,18,19],topic:[10,13,22],topicsess:14,toplevel:20,topriv:13,toset:13,tosignedtransact:[13,17,18],tostr:[1,13,18],total:[5,18],toward:[14,15],towiretransact:17,trace:13,track:[5,6,8,10],tracker:13,trade1:16,trade:[4,8,9,12],trade_topic:13,tradeoff:1,trader:8,traderdemo:22,traderequest:13,tradit:[5,18],traffic:[5,13],transact:[2,3,5,6,8,11,12,13,14],transactionbuild:[13,14,17,18],transactionforcontract:[18,19],transactionforverif:18,transactiongroup:18,transactiongroupdsl:21,transactiongroupfor:21,transactiongroupfortest:18,transactionst:[2,14,17],transactiontyp:14,transactionverificationexcept:20,transfer:[18,20],transit:[8,18,22],treat:18,tree:13,tri:[5,18],tricki:[5,13],trigger:[3,6,12,16,19],trim:19,trivial:[1,5],trust:[3,5,13],truth:13,tsa:[5,13],tsasig:13,tupl:1,ture:5,turn:[5,13,17,18,19,20,22],tutori:[3,8,9,12,13,14,18,19,20,22],tweak:20,twice:[9,20],two:[1,2,3,4,5,6,8,10],twopartydealprotocol:6,twopartytradeprotocol:13,txb:17,txbit:13,txhash:[5,13,18],txt:11,type:[1,2,4,5,6,8,12,13,14],typenam:13,typetobui:13,typic:[5,6,10,11,13,17,18,22],unacceptablepriceexcept:13,under:[0,13,15,18,20,22],underli:[3,4,5,13,17],underscor:[1,18],understand:[5,10,11,18,21,22],unexecut:18,unexpect:13,unfinish:13,unfortun:[13,18],unguess:13,unicredit:14,unifi:[14,22],uniform:6,unindex:7,uniqu:[2,5,12,13,14],unit:[2,5,7,8,9,10],unix:[11,16],unknow:12,unless:[1,12,13,15,18,22],unlik:18,unlike:[3,7],unmatch:19,unnatur:5,unnecessari:18,unpack:[13,18],unprocess:19,unqiu:6,unread:13,unrecognis:18,unrel:18,unschedul:6,unserialis:13,unset:4,unspent:5,unstarted:13,unsupportedoperationexcept:18,until:[2,4,5,6,10,13,15,19,20,22],untrustworthydata:13,unus:10,unusu:18,unverifiedtransact:20,upcom:[6,14],updat:[5,10,13,14,15,18],update:7,upgrad:[7,8],upgrade:[7,14],upload:8,upon:[4,13,18],upward:15,url:[7,16],usabl:[9,14,15],usag:[1,12,13,18],usd:17,use:[1,3,5],useless:18,user:[0,1,5,7,9,10,12,13,14],using:[8,12],usr:0,usual:[1,5],usualli:15,utc:6,util:[10,14,18],vagu:1,val:[1,2,6,10,12,13,17,18,19,20,21],validatedtransact:13,validatingnotaryservic:2,validfrom:18,valu:[1,3,4,5,9,12,18,19,20,21],valuabl:12,valuat:4,vanilla:[3,4,9],vari:8,variabl:[1,4,5,13,18],variant:18,variou:[1,5,9,11,13,18],vcs:7,vehicl:5,vendor:[9,11],verbos:18,veri:[1,3,5,9,12,18,20,21,22],verif:[3,5,9,19,20],verifi:[2,5,8,9,10,12,13,14,17],verifyclaus:19,verifytransact:13,versa:[3,4,13,17],version:[4,7,10,13,14,15,17,18],versu:13,vertic:1,via:[0,1,4,5,6,11,12,13,16,18,22],vice:[3,4,13,17],view:[1,4,16],virtual:[5,8],visibl:[2,5],vision:8,visualis:8,vital:13,wai:[1,5,6,9,11,12,13,14,18,19,20,22],wait:[6,7,10,13,16],wake:14,wallet:[5,6,13,14,18],walletservic:13,want:[1,5,7,10,11,12,13,14,18,20,22],weak:12,wear:15,web:[8,11,12,14],websit:18,weekend:4,well:[0,1,4,5,6,9,11,12,13,17,18,19],went:1,were:[1,5,12,13,18],what:[1,3,4,5,6,7,8],whatev:[1,13,17],when:[1,2,3,4,5,6,10,11,12,13,14,17,18,20],whenev:1,where:[1,2,5,8,10,11,12,13,14,15,17,20],wherea:4,wherev:11,whether:[2,3,10,12,13,19],which:[0,1,2,3,4,5,6,8,9,10,11,12,13,14,15,16,17,18,19,20,22],whilst:[5,12,13,16,18],whitelist:[3,6],whitepap:8,who:[1,5,9,10,13,14,18],whole:[2,18,20],whom:[3,5,10],whose:[11,17],why:[1,5,9,18],wide:[1,10,18],widescreen:1,widespread:1,width:1,wiki:[5,18,19],wikipedia:[18,19],window:[5,7,13,16,21],wire:22,wirecommand:18,wiretransact:[2,12,13,17],wish:[5,10,12,13,14,18,22],within:[0,1,2,5,11,16,18,20],withitem:17,withkei:13,withnewown:13,without:[1,2],withoutown:[18,19],won:[10,12,13,16,18,20],word:[1,2],work:[1,2,4,5,6,7,8,9,10,11,12,13,14,16,17,18],worker:1,world:[5,12,13,18,20],worn:18,worri:[1,9,13],worst:5,worth:[1,18],worthless:12,would:[1,3,4,5,9,10,11,12,13,17,18,22],wouldn:[12,18],wrap:[1,11,13,14,17,18,19,22],wrapper:[1,2,13],write:[1,2,8,9,11],written:[0,4,5,9,14,18],wrong:[1,13,16,20],wrote:5,wtx:[2,12,13],www:[0,7],year:4,yet:[1,4,5,9,13,14,17,18],yield:[5,13],you:[0,1,5,6,7,9,10,11,12,13,14,16,17,18,19,20,21,22],your:[1,5,6,7,8,10],your_usernam:7,yourself:5,zero:[5,18],zip:[5,11],zone:6,zoneddatetim:6},titles:["Building the documentation","Code style guide","Consensus model","Platform contracts","Interest Rate Swaps","Data model","Event scheduling","Getting set up","Welcome to the Corda repository!","What’s included?","Networking and messaging","Node administration","Writing oracle services","Protocol state machines","Release notes","Release process","Running the demos","Data types","Writing a contract","Writing a contract using clauses","Writing a contract test","Using the visualiser","Where to start"],titleterms:{"class":[18,19],"function":18,about:7,adding:18,administr:11,adopt:5,amount:17,api:18,approach:12,assert:12,assertion:1,asset:18,attach:11,base:18,basic:12,bitcoin:5,build:0,buyer:13,cash:[3,17],chain:20,chang:2,check:18,claus:[18,19],code:1,command:18,comment:1,commerci:[3,18,19],comparison:5,compil:1,complain:7,con:5,consensu:2,continu:12,contract:[3,9,18,19,20],corda:8,creat:4,cut:15,data:[5,12,17],date:17,demo:[16,22],detail:4,document:0,download:11,encumbranc:18,error:1,ethereum:5,event:6,exampl:6,fix:11,framework:12,fungibleasset:17,gener:[1,18],get:7,group:[18,19],guid:1,how:[6,18],implement:[6,10,12,13],includ:9,instanc:4,intellij:7,interest:[3,4,11],interfac:10,introduct:[6,12,13],irs:16,known:12,kotlin:9,lack:7,length:1,lifecycl:[4,17],line:1,machin:13,manag:13,map:10,memori:10,messag:10,method:13,mileston:14,model:[2,5],monitor:11,multipl:2,name:1,network:10,node:11,non:18,notari:2,note:14,obligat:3,obtain:2,occasion:12,oracl:12,orient:18,overview:5,paper:[3,18,19],parti:[13,17],platform:3,pro:5,process:15,progress:13,properti:1,protocol:13,publickei:17,publicli:12,rate:[3,4,11],rational:5,releas:[14,15],repositori:8,requir:[0,18],run:[2,16],schedul:6,sdk:7,seller:13,servic:[2,10,12],set:7,signatur:2,singl:20,smart:18,space:1,start:[18,22],state:[13,17,18],step:15,style:[1,5],summari:19,support:17,suspend:13,swap:[3,4],technic:4,test:[13,18,20],theori:13,thread:1,timestamp:2,track:13,trade:13,tradeoff:5,trader:[16,22],transact:[17,20],two:[12,13],type:17,unit:13,upload:11,using:[18,21],utxo:5,valid:2,vari:12,verifi:18,visualis:21,warn:1,web:16,welcom:8,what:9,where:22,without:7,write:[12,18,19,20],your:[11,18]}}) \ No newline at end of file diff --git a/docs/build/html/tutorial-contract-clauses.html b/docs/build/html/tutorial-contract-clauses.html index bc3b0576fb..da48f14919 100644 --- a/docs/build/html/tutorial-contract-clauses.html +++ b/docs/build/html/tutorial-contract-clauses.html @@ -174,7 +174,7 @@

    Writing a contract using clauses

    This tutorial will take you through restructuring the commercial paper contract to use clauses. You should have already completed “Writing a contract”.

    -

    Clauses are essentially “mini-contracts” which contain verification logic, and are composed together to form +

    Clauses are essentially micro-contracts which contain independent verification logic, and are composed together to form a contract. With appropriate design, they can be made to be reusable, for example issuing contract state objects is generally the same for all fungible contracts, so a single issuance clause can be shared. This cuts down on scope for error, and improves consistency of behaviour.

    @@ -197,20 +197,19 @@ In the case of commercial paper, we have a “Grouping” outermost clau

    Commercial paper class

    -

    First we need to change the class from implementing Contract, to extend ClauseVerifier. This is an abstract -class which provides a verify() function for us, and requires we provide a property (clauses) for the clauses to test, -and a function (extractCommands) to extract the applicable commands from the transaction. This is important because -ClauseVerifier checks that no commands applicable to the contract are left unprocessed at the end. The following -examples are trimmed to the modified class definition and added elements, for brevity:

    +

    To use the clause verification logic, the contract needs to call the verifyClauses() function, passing in the transaction, +a list of clauses to verify, and a collection of commands the clauses are expected to handle all of. This list of +commands is important because verifyClauses() checks that none of the commands are left unprocessed at the end, and +raises an error if they are. The following examples are trimmed to the modified class definition and added elements, for +brevity:

    -
    class CommercialPaper : ClauseVerifier {
    -    override val legalContractReference: SecureHash = SecureHash.sha256("https://en.wikipedia.org/wiki/Commercial_paper");
    +
    class CommercialPaper : Contract {
    +    override val legalContractReference: SecureHash = SecureHash.sha256("https://en.wikipedia.org/wiki/Commercial_paper")
     
    -    override val clauses: List<SingleClause>
    -        get() = throw UnsupportedOperationException("not implemented")
    -
    -    override fun extractCommands(tx: TransactionForContract): List<AuthenticatedObject<CommandData>>
    +    private fun extractCommands(tx: TransactionForContract): List<AuthenticatedObject<CommandData>>
             = tx.commands.select<Commands>()
    +
    +    override fun verify(tx: TransactionForContract) = verifyClauses(tx, listOf(Clauses.Group()), extractCommands(tx))
     
    public class CommercialPaper implements Contract {
    @@ -219,11 +218,6 @@ examples are trimmed to the modified class definition and added elements, for br
             return SecureHash.Companion.sha256("https://en.wikipedia.org/wiki/Commercial_paper");
         }
     
    -    @Override
    -    public List<SingleClause> getClauses() {
    -        throw UnsupportedOperationException("not implemented");
    -    }
    -
         @Override
         public Collection<AuthenticatedObject<CommandData>> extractCommands(@NotNull TransactionForContract tx) {
             return tx.getCommands()
    @@ -231,6 +225,11 @@ examples are trimmed to the modified class definition and added elements, for br
                     .filter((AuthenticatedObject<CommandData> command) -> { return command.getValue() instanceof Commands; })
                     .collect(Collectors.toList());
         }
    +
    +    @Override
    +    public void verify(@NotNull TransactionForContract tx) throws IllegalArgumentException {
    +        ClauseVerifier.verifyClauses(tx, Collections.singletonList(new Clause.Group()), extractCommands(tx));
    +    }
     
    diff --git a/docs/build/html/tutorial-contract.html b/docs/build/html/tutorial-contract.html index cafd38b5a0..5e1802bd89 100644 --- a/docs/build/html/tutorial-contract.html +++ b/docs/build/html/tutorial-contract.html @@ -114,6 +114,7 @@
  • How to test your contract
  • Adding a generation API to your contract
  • Non-asset-oriented based smart contracts
  • +
  • Encumbrances
  • Clauses
  • @@ -924,6 +925,58 @@ The logic that implements measurement of the threshold, different signing combin be implemented once in a separate contract, with the controlling data being held in the named state.

    Future versions of the prototype will explore these concepts in more depth.

    +
    +

    Encumbrances

    +

    All contract states may be encumbered by up to one other state, which we call an encumbrance.

    +

    The encumbrance state, if present, forces additional controls over the encumbered state, since the encumbrance state contract +will also be verified during the execution of the transaction. For example, a contract state could be encumbered +with a time-lock contract state; the state is then only processable in a transaction that verifies that the time +specified in the encumbrance time-lock has passed.

    +

    The encumbered state refers to its encumbrance by index, and the referred encumbrance state +is an output state in a particular position on the same transaction that created the encumbered state. Note that an +encumbered state that is being consumed must have its encumbrance consumed in the same transaction, otherwise the +transaction is not valid.

    +

    The encumbrance reference is optional in the ContractState interface:

    +
    +
    val encumbrance: Int? get() = null
    +
    +
    +
    @Nullable
    +@Override
    +public Integer getEncumbrance() {
    +    return null;
    +}
    +
    +
    +
    +

    The time-lock contract mentioned above can be implemented very simply:

    +
    +
    class TestTimeLock : Contract {
    +    ...
    +    override fun verify(tx: TransactionForContract) {
    +        val timestamp: Timestamp? = tx.timestamp
    +        ...
    +        requireThat {
    +            "the time specified in the time-lock has passed" by
    +                    (time >= tx.inputs.filterIsInstance<TestTimeLock.State>().single().validFrom)
    +        }
    +    }
    +    ...
    +}
    +
    +
    +
    +

    We can then set up an encumbered state:

    +
    +
    val encumberedState = Cash.State(amount = 1000.DOLLARS `issued by` defaultIssuer, owner = DUMMY_PUBKEY_1, encumbrance = 1)
    +val fourPmTimelock = TestTimeLock.State(Instant.parse("2015-04-17T16:00:00.00Z"))
    +
    +
    +
    +

    When we construct a transaction that generates the encumbered state, we must place the encumbrance in the corresponding output +position of that transaction. And when we subsequently consume that encumbered state, the same encumbrance state must be +available somewhere within the input set of states.

    +

    Clauses

    Instead of structuring contracts as a single entity, they can be broken down into reusable chunks known as clauses. diff --git a/docs/source/tutorial-contract.rst b/docs/source/tutorial-contract.rst index f149a8a433..21ba5951ae 100644 --- a/docs/source/tutorial-contract.rst +++ b/docs/source/tutorial-contract.rst @@ -845,6 +845,70 @@ be implemented once in a separate contract, with the controlling data being held Future versions of the prototype will explore these concepts in more depth. +Encumbrances +------------ + +All contract states may be *encumbered* by up to one other state, which we call an **encumbrance**. + +The encumbrance state, if present, forces additional controls over the encumbered state, since the encumbrance state contract +will also be verified during the execution of the transaction. For example, a contract state could be encumbered +with a time-lock contract state; the state is then only processable in a transaction that verifies that the time +specified in the encumbrance time-lock has passed. + +The encumbered state refers to its encumbrance by index, and the referred encumbrance state +is an output state in a particular position on the same transaction that created the encumbered state. Note that an +encumbered state that is being consumed must have its encumbrance consumed in the same transaction, otherwise the +transaction is not valid. + +The encumbrance reference is optional in the ``ContractState`` interface: + +.. container:: codeset + + .. sourcecode:: kotlin + + val encumbrance: Int? get() = null + + .. sourcecode:: java + + @Nullable + @Override + public Integer getEncumbrance() { + return null; + } + + +The time-lock contract mentioned above can be implemented very simply: + +.. container:: codeset + + .. sourcecode:: kotlin + + class TestTimeLock : Contract { + ... + override fun verify(tx: TransactionForContract) { + val timestamp: Timestamp? = tx.timestamp + ... + requireThat { + "the time specified in the time-lock has passed" by + (time >= tx.inputs.filterIsInstance().single().validFrom) + } + } + ... + } + +We can then set up an encumbered state: + +.. container:: codeset + + .. sourcecode:: kotlin + + val encumberedState = Cash.State(amount = 1000.DOLLARS `issued by` defaultIssuer, owner = DUMMY_PUBKEY_1, encumbrance = 1) + val fourPmTimelock = TestTimeLock.State(Instant.parse("2015-04-17T16:00:00.00Z")) + +When we construct a transaction that generates the encumbered state, we must place the encumbrance in the corresponding output +position of that transaction. And when we subsequently consume that encumbered state, the same encumbrance state must be +available somewhere within the input set of states. + Clauses ------- From e187c4d91d1c49bbe65d5193266b4910c88dfb28 Mon Sep 17 00:00:00 2001 From: jamescarlyle Date: Thu, 8 Sep 2016 22:49:24 +0100 Subject: [PATCH 08/10] Further tweaks based on feedback - simplified the embedded timelock contract --- .../com/r3corda/contracts/asset/Cash.kt | 1 - .../com/r3corda/core/contracts/Structures.kt | 9 +++-- .../contracts/TransactionEncumbranceTests.kt | 37 ++++++++++--------- docs/source/tutorial-contract.rst | 10 +++++ 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/contracts/src/main/kotlin/com/r3corda/contracts/asset/Cash.kt b/contracts/src/main/kotlin/com/r3corda/contracts/asset/Cash.kt index f50d54e946..aa33b1e5cc 100644 --- a/contracts/src/main/kotlin/com/r3corda/contracts/asset/Cash.kt +++ b/contracts/src/main/kotlin/com/r3corda/contracts/asset/Cash.kt @@ -80,7 +80,6 @@ class Cash : OnLedgerAsset() { /** There must be a MoveCommand signed by this key to claim the amount. */ override val owner: PublicKey, - /** Cash may be encumbered by an additional state. */ override val encumbrance: Int? = null ) : FungibleAsset { constructor(deposit: PartyAndReference, amount: Amount, owner: PublicKey) diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt index 8fc83a7e72..d8ccf21a42 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt @@ -115,10 +115,11 @@ interface ContractState { /** * All contract states may be _encumbered_ by up to one other state. * - * The encumbrance state, if present, forces additional controls over this state, since the encumbrance state contract - * will also be verified during the execution of the transaction. For example, a contract state could be encumbered - * with a time-lock contract state; the state is then only processable in a transaction that verifies that the time - * specified in the encumbrance time-lock has passed. + * The encumbrance state, if present, forces additional controls over the encumbered state, since the platform checks + * that the encumbrance state is present as an input in the same transaction that consumes the encumbered state, and + * the contract code and rules of the encumbrance state will also be verified during the execution of the transaction. + * For example, a cash contract state could be encumbered with a time-lock contract state; the cash state is then only + * processable in a transaction that verifies that the time specified in the encumbrance time-lock has passed. * * The encumbered state refers to another by index, and the referred encumbrance state * is an output state in a particular position on the same transaction that created the encumbered state. An alternative diff --git a/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt index 9f67246a61..f41de2521b 100644 --- a/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt +++ b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionEncumbranceTests.kt @@ -2,13 +2,11 @@ package com.r3corda.core.contracts import com.r3corda.contracts.asset.Cash import com.r3corda.core.crypto.SecureHash -import com.r3corda.core.serialization.OpaqueBytes import com.r3corda.core.testing.* import org.junit.Test import java.security.PublicKey import java.time.Instant import java.time.temporal.ChronoUnit -import kotlin.test.assertFailsWith val TEST_TIMELOCK_ID = TransactionEncumbranceTests.TestTimeLock() @@ -32,32 +30,30 @@ class TransactionEncumbranceTests { class TestTimeLock : Contract { override val legalContractReference = SecureHash.sha256("TestTimeLock") override fun verify(tx: TransactionForContract) { - val timestamp: Timestamp? = tx.timestamp - val time = timestamp?.before ?: throw IllegalArgumentException("Transactions containing time-locks must be timestamped") + val time = tx.timestamp?.before ?: throw IllegalArgumentException("Transactions containing time-locks must be timestamped") requireThat { "the time specified in the time-lock has passed" by (time >= tx.inputs.filterIsInstance().single().validFrom) } } + data class State( val validFrom: Instant ) : ContractState { - override val participants: List - get() = throw UnsupportedOperationException() + override val participants: List = emptyList() override val contract: Contract = TEST_TIMELOCK_ID } } @Test fun trivial() { - // A transaction containing an input state that is encumbered must fail if the encumbrance is missing on the inputs. - assertFailsWith(TransactionVerificationException.TransactionMissingEncumbranceException::class) { - transaction { - input { encumberedState } - output { unencumberedState } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } - this.verifies() - } + // A transaction containing an input state that is encumbered must fail if the encumbrance has not been presented + // on the input states. + transaction { + input { encumberedState } + output { unencumberedState } + command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + this `fails with` "Missing required encumbrance 1 in INPUT" } // An encumbered state must not be encumbered by itself. transaction { @@ -70,6 +66,7 @@ class TransactionEncumbranceTests { this `fails with` "Missing required encumbrance 1 in OUTPUT" } // An encumbered state must not reference an index greater than the size of the output states. + // In this test, the output encumbered state refers to an encumbrance in position 1, but there is only one output. transaction { input { unencumberedState } // The encumbered state refers to an encumbrance in position 1, so there should be at least 2 outputs. @@ -82,8 +79,10 @@ class TransactionEncumbranceTests { @Test fun testEncumbranceEffects() { - // A transaction containing an input state that is encumbered must fail if the encumbrance is not in the correct position. - ledger { + // This test fails because the encumbered state is pointing to the ordinary cash state as the encumbrance, + // instead of the timelock by mistake, so when we try and use it the transaction fails as we didn't include the + // encumbrance cash state. + ledger { unverifiedTransaction { output("state encumbered by 5pm time-lock") { encumberedState } output { unencumberedState } @@ -98,7 +97,10 @@ class TransactionEncumbranceTests { this `fails with` "Missing required encumbrance 1 in INPUT" } } - // A transaction containing an input state that is encumbered must fail if the encumbrance is not in the correct transaction. + // A transaction containing an input state that is encumbered must fail if the encumbrance is not in the correct + // transaction. In this test, the intended encumbrance is presented alongside the encumbered state for consumption, + // although the encumbered state always refers to the encumbrance produced in the same transaction, and the in this case + // the encumbrance was created in a separate transaction. ledger { unverifiedTransaction { output("state encumbered by 5pm time-lock") { encumberedState } @@ -133,6 +135,7 @@ class TransactionEncumbranceTests { } } // A transaction with an input state that is encumbered must fail if the rules of the encumbrance are not met. + // In this test, the time-lock encumbrance is being processed in a transaction before the time allowed. ledger { unverifiedTransaction { output("state encumbered by 5pm time-lock") { encumberedState } diff --git a/docs/source/tutorial-contract.rst b/docs/source/tutorial-contract.rst index 21ba5951ae..a923fe5fad 100644 --- a/docs/source/tutorial-contract.rst +++ b/docs/source/tutorial-contract.rst @@ -909,6 +909,16 @@ When we construct a transaction that generates the encumbered state, we must pla position of that transaction. And when we subsequently consume that encumbered state, the same encumbrance state must be available somewhere within the input set of states. +In future, we will consider the concept of a *covenant*. This is where the encumbrance travels alongside each iteration of +the encumbered state. For example, a cash state may be encumbered with a *domicile* encumbrance, which checks the domicile of +the identity of the owner that the cash state is being moved to, in order to uphold sanction screening regulations, and prevent +cash being paid to parties domiciled in e.g. North Korea. In this case, the encumbrance should be permanently attached to +the all future cash states stemmimg from this one. + +We will also consider marking states that are capable of being encumbrances as such. This will prevent states being used +as encumbrances inadvertently. For example, the time-lock above would be usable as an encumbrance, but it makes no sense to +be able to encumber a cash state with another one. + Clauses ------- From 455a0ac9c9e999e05bffb6a352a83adb6e5032fa Mon Sep 17 00:00:00 2001 From: jamescarlyle Date: Thu, 8 Sep 2016 23:02:01 +0100 Subject: [PATCH 09/10] Tidied document code example --- docs/source/tutorial-contract.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial-contract.rst b/docs/source/tutorial-contract.rst index a923fe5fad..ed4e52ebf2 100644 --- a/docs/source/tutorial-contract.rst +++ b/docs/source/tutorial-contract.rst @@ -886,7 +886,7 @@ The time-lock contract mentioned above can be implemented very simply: class TestTimeLock : Contract { ... override fun verify(tx: TransactionForContract) { - val timestamp: Timestamp? = tx.timestamp + val time = tx.timestamp.before ?: throw IllegalStateException(...) ... requireThat { "the time specified in the time-lock has passed" by From 53967e26aec3750b580b6be10bba5833764b6b1d Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Fri, 9 Sep 2016 09:31:52 +0000 Subject: [PATCH 10/10] Minor type fix in the encumbrances doc section --- docs/source/tutorial-contract.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial-contract.rst b/docs/source/tutorial-contract.rst index a36a77d180..2ee0c4b4a7 100644 --- a/docs/source/tutorial-contract.rst +++ b/docs/source/tutorial-contract.rst @@ -787,7 +787,7 @@ In future, we will consider the concept of a *covenant*. This is where the encum the encumbered state. For example, a cash state may be encumbered with a *domicile* encumbrance, which checks the domicile of the identity of the owner that the cash state is being moved to, in order to uphold sanction screening regulations, and prevent cash being paid to parties domiciled in e.g. North Korea. In this case, the encumbrance should be permanently attached to -the all future cash states stemmimg from this one. +the all future cash states stemming from this one. We will also consider marking states that are capable of being encumbrances as such. This will prevent states being used as encumbrances inadvertently. For example, the time-lock above would be usable as an encumbrance, but it makes no sense to