diff --git a/.gitignore b/.gitignore index 7137efbf39..c2649c7542 100644 --- a/.gitignore +++ b/.gitignore @@ -5,20 +5,28 @@ tags .DS_Store *.log +*.log.gz +*.orig # Created by .ignore support plugin (hsz.mobi) .gradle -/build/ -/node/build/ -/contracts/build -/contracts/isolated/build -/core/build -/experimental/build /docs/build/doctrees -/test-utils/build -/client/build -/explorer/build + +# General build files +**/build/classes/** +**/build/install/** +**/build/kotlin-classes/** +**/build/libs/** +**/build/resources/** +**/build/tmp/** +**/build/reports/** +**/build/jacoco/*** +**/build/test-results/** +**/build/[0-9]*/** +**/build/nodes/** +**/build/scripts/** +**/build/publications/** # gradle's buildSrc build/ /buildSrc/build/ diff --git a/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt b/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt index 000910c60c..07eece75f5 100644 --- a/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt +++ b/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt @@ -201,7 +201,7 @@ class InterestRateSwap() : Contract { val threshold: Amount, val minimumTransferAmount: Amount, val rounding: Amount, - val valuationDate: String, + val valuationDateDescription: String, // This describes (in english) how regularly the swap is to be valued, e.g. "every local working day" val notificationTime: String, val resolutionTime: String, val interestRate: ReferenceRate, @@ -679,22 +679,6 @@ class InterestRateSwap() : Contract { return ScheduledActivity(protocolLogicRefFactory.create(TwoPartyDealProtocol.FixingRoleDecider::class.java, thisStateRef, duration), instant) } - // TODO: This changing of the public key violates the assumption that Party is a fixed identity key. - override fun withPublicKey(before: Party, after: PublicKey): DealState { - val newParty = Party(before.name, after) - if (before == fixedLeg.fixedRatePayer) { - val deal = copy() - deal.fixedLeg.fixedRatePayer = newParty - return deal - } else if (before == floatingLeg.floatingRatePayer) { - val deal = copy() - deal.floatingLeg.floatingRatePayer = newParty - return deal - } else { - throw IllegalArgumentException("No such party: $before") - } - } - override fun generateAgreement(notary: Party): TransactionBuilder = InterestRateSwap().generateAgreement(floatingLeg, fixedLeg, calculation, common, notary) override fun generateFix(ptx: TransactionBuilder, oldState: StateAndRef<*>, fix: Fix) { diff --git a/contracts/src/test/kotlin/com/r3corda/contracts/IRSTests.kt b/contracts/src/test/kotlin/com/r3corda/contracts/IRSTests.kt index 43d2f7f069..43c29351f4 100644 --- a/contracts/src/test/kotlin/com/r3corda/contracts/IRSTests.kt +++ b/contracts/src/test/kotlin/com/r3corda/contracts/IRSTests.kt @@ -6,11 +6,8 @@ import com.r3corda.core.transactions.SignedTransaction import com.r3corda.core.utilities.DUMMY_NOTARY import com.r3corda.core.utilities.DUMMY_NOTARY_KEY import com.r3corda.core.utilities.TEST_TX_TIME -import com.r3corda.testing.LedgerDSL -import com.r3corda.testing.TestLedgerDSLInterpreter -import com.r3corda.testing.TestTransactionDSLInterpreter -import com.r3corda.testing.node.MockServices import com.r3corda.testing.* +import com.r3corda.testing.node.MockServices import org.junit.Test import java.math.BigDecimal import java.time.LocalDate @@ -92,7 +89,7 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State { threshold = Amount(0, EUR), minimumTransferAmount = Amount(250000 * 100, EUR), rounding = Amount(10000 * 100, EUR), - valuationDate = "Every Local Business Day", + valuationDateDescription = "Every Local Business Day", notificationTime = "2:00pm London", resolutionTime = "2:00pm London time on the first LocalBusiness Day following the date on which the notice is given ", interestRate = ReferenceRate("T3270", Tenor("6M"), "EONIA"), @@ -182,7 +179,7 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State { threshold = Amount(0, EUR), minimumTransferAmount = Amount(250000 * 100, EUR), rounding = Amount(10000 * 100, EUR), - valuationDate = "Every Local Business Day", + valuationDateDescription = "Every Local Business Day", notificationTime = "2:00pm London", resolutionTime = "2:00pm London time on the first LocalBusiness Day following the date on which the notice is given ", interestRate = ReferenceRate("T3270", Tenor("6M"), "EONIA"), diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/ContractsDSL.kt b/core/src/main/kotlin/com/r3corda/core/contracts/ContractsDSL.kt index 272d50f6f7..ad05ffaffe 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/ContractsDSL.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/ContractsDSL.kt @@ -23,6 +23,7 @@ fun commodity(code: String) = Commodity.getInstance(code)!! @JvmField val USD = currency("USD") @JvmField val GBP = currency("GBP") +@JvmField val EUR = currency("EUR") @JvmField val CHF = currency("CHF") @JvmField val FCOJ = commodity("FCOJ") 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 ef692ea20d..db426ac830 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt @@ -279,9 +279,6 @@ interface DealState : LinearState { /** Exposes the Parties involved in a generic way */ val parties: List - // TODO: This works by editing the keys used by a Party which is invalid. - fun withPublicKey(before: Party, after: PublicKey): DealState - /** * Generate a partial transaction representing an agreement (command) to this deal, allowing a general * deal/agreement protocol to generate the necessary transaction for potential implementations. diff --git a/core/src/main/kotlin/com/r3corda/core/crypto/X509Utilities.kt b/core/src/main/kotlin/com/r3corda/core/crypto/X509Utilities.kt index 7d4a6c4e5f..0bfaf5abad 100644 --- a/core/src/main/kotlin/com/r3corda/core/crypto/X509Utilities.kt +++ b/core/src/main/kotlin/com/r3corda/core/crypto/X509Utilities.kt @@ -231,7 +231,7 @@ object X509Utilities { fun generateECDSAKeyPairForSSL(): KeyPair { val keyGen = KeyPairGenerator.getInstance(KEY_GENERATION_ALGORITHM, BouncyCastleProvider.PROVIDER_NAME) val ecSpec = ECGenParameterSpec(ECDSA_CURVE) // Force named curve, because TLS implementations don't support many curves - keyGen.initialize(ecSpec, SecureRandom()) + keyGen.initialize(ecSpec, newSecureRandom()) return keyGen.generateKeyPair() } diff --git a/core/src/main/kotlin/com/r3corda/core/node/services/Services.kt b/core/src/main/kotlin/com/r3corda/core/node/services/Services.kt index 60a8fc1e7e..e7b54560bd 100644 --- a/core/src/main/kotlin/com/r3corda/core/node/services/Services.kt +++ b/core/src/main/kotlin/com/r3corda/core/node/services/Services.kt @@ -150,6 +150,10 @@ interface VaultService { } inline fun VaultService.linearHeadsOfType() = linearHeadsOfType_(T::class.java) +inline fun VaultService.dealsWith(party: Party) = linearHeadsOfType().values.filter { + // TODO: Replace name comparison with full party comparison (keys are currenty not equal) + it.state.data.parties.any { it.name == party.name } +} /** * The KMS is responsible for storing and using private keys to sign things. An implementation of this may, for example, diff --git a/core/src/main/kotlin/com/r3corda/core/protocols/ProtocolLogic.kt b/core/src/main/kotlin/com/r3corda/core/protocols/ProtocolLogic.kt index bd01afe48e..91e5bfed22 100644 --- a/core/src/main/kotlin/com/r3corda/core/protocols/ProtocolLogic.kt +++ b/core/src/main/kotlin/com/r3corda/core/protocols/ProtocolLogic.kt @@ -2,8 +2,11 @@ package com.r3corda.core.protocols import co.paralleluniverse.fibers.Suspendable import com.r3corda.core.crypto.Party +import com.r3corda.core.messaging.Message +import com.r3corda.core.messaging.runOnNextMessage import com.r3corda.core.node.ServiceHub import com.r3corda.core.node.services.DEFAULT_SESSION_ID +import com.r3corda.core.serialization.deserialize import com.r3corda.core.utilities.ProgressTracker import com.r3corda.core.utilities.UntrustworthyData import com.r3corda.core.utilities.debug @@ -11,6 +14,7 @@ import com.r3corda.protocols.HandshakeMessage import org.slf4j.Logger import rx.Observable import java.util.* +import java.util.concurrent.CompletableFuture /** * A sub-class of [ProtocolLogic] implements a protocol flow using direct, straight line blocking code. Thus you @@ -108,6 +112,11 @@ abstract class ProtocolLogic { throw IllegalStateException("Session with party $otherParty hasn't been established yet") } + /** + * Check if we already have a session with this party + */ + protected fun hasSession(otherParty: Party) = sessions.containsKey(otherParty) + /** * Invokes the given subprotocol by simply passing through this [ProtocolLogic]s reference to the * [ProtocolStateMachine] and then calling the [call] method. diff --git a/core/src/main/kotlin/com/r3corda/protocols/AbstractStateReplacementProtocol.kt b/core/src/main/kotlin/com/r3corda/protocols/AbstractStateReplacementProtocol.kt index 8a86e0747b..f5dd398243 100644 --- a/core/src/main/kotlin/com/r3corda/protocols/AbstractStateReplacementProtocol.kt +++ b/core/src/main/kotlin/com/r3corda/protocols/AbstractStateReplacementProtocol.kt @@ -70,8 +70,8 @@ abstract class AbstractStateReplacementProtocol { return finalTx.tx.outRef(0) } - abstract internal fun assembleProposal(stateRef: StateRef, modification: T, stx: SignedTransaction): Proposal - abstract internal fun assembleTx(): Pair> + abstract protected fun assembleProposal(stateRef: StateRef, modification: T, stx: SignedTransaction): Proposal + abstract protected fun assembleTx(): Pair> @Suspendable private fun collectSignatures(participants: List, stx: SignedTransaction): List { @@ -93,7 +93,10 @@ abstract class AbstractStateReplacementProtocol { private fun getParticipantSignature(party: Party, stx: SignedTransaction): DigitalSignature.WithKey { val proposal = assembleProposal(originalState.ref, modification, stx) - send(party, Handshake(serviceHub.storageService.myLegalIdentity)) + // TODO: Move this into protocol logic as a func on the lines of handshake(Party, HandshakeMessage) + if (!hasSession(party)) { + send(party, Handshake(serviceHub.storageService.myLegalIdentity)) + } val response = sendAndReceive(party, proposal) val participantSignature = response.unwrap { @@ -179,7 +182,7 @@ abstract class AbstractStateReplacementProtocol { * on the change proposed, and may further depend on the node itself (for example configuration). The * proposal is returned if acceptable, otherwise an exception is thrown. */ - abstract fun verifyProposal(maybeProposal: UntrustworthyData>): Proposal + abstract protected fun verifyProposal(maybeProposal: UntrustworthyData>): Proposal @Suspendable private fun verifyTx(stx: SignedTransaction) { @@ -219,4 +222,4 @@ class StateReplacementRefused(val identity: Party, val state: StateRef, val deta override fun toString() = "A participant $identity refused to change state $state: " + (detail ?: "no reason provided") } -class StateReplacementException(val error: StateReplacementRefused) : Exception("State change failed - $error") \ No newline at end of file +class StateReplacementException(val error: StateReplacementRefused) : Exception("State change failed - $error") diff --git a/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt b/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt index 448d937d3d..7a9fb242a0 100644 --- a/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt +++ b/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt @@ -6,6 +6,7 @@ import com.r3corda.core.contracts.* import com.r3corda.core.crypto.DigitalSignature import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.signWithECDSA +import com.r3corda.core.crypto.toBase58String import com.r3corda.core.node.NodeInfo import com.r3corda.core.node.services.ServiceType import com.r3corda.core.protocols.ProtocolLogic @@ -285,22 +286,11 @@ object TwoPartyDealProtocol { override fun validateHandshake(handshake: Handshake): Handshake { // What is the seller trying to sell us? val deal: T = handshake.payload - val otherKey = handshake.publicKey logger.trace { "Got deal request for: ${handshake.payload.ref}" } check(dealToBuy == deal) - // We need to substitute in the new public keys for the Parties - val myName = serviceHub.storageService.myLegalIdentity.name - val myOldParty = deal.parties.single { it.name == myName } - val theirOldParty = deal.parties.single { it.name != myName } - - @Suppress("UNCHECKED_CAST") - val newDeal = deal. - withPublicKey(myOldParty, serviceHub.keyManagementService.freshKey().public). - withPublicKey(theirOldParty, otherKey) as T - - return handshake.copy(payload = newDeal) + return handshake.copy(payload = deal) } diff --git a/node/src/test/kotlin/com/r3corda/node/services/NodeSchedulerServiceTest.kt b/node/src/test/kotlin/com/r3corda/node/services/NodeSchedulerServiceTest.kt index 3565e42551..a7891b47f2 100644 --- a/node/src/test/kotlin/com/r3corda/node/services/NodeSchedulerServiceTest.kt +++ b/node/src/test/kotlin/com/r3corda/node/services/NodeSchedulerServiceTest.kt @@ -261,7 +261,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() { private fun scheduleTX(instant: Instant, increment: Int = 1): ScheduledStateRef? { var scheduledRef: ScheduledStateRef? = null apply { - val freshKey = services.keyManagementService.freshKey() + val freshKey = services.storageService.myLegalIdentityKey val state = TestState(factory.create(TestProtocolLogic::class.java, increment), instant) val usefulTX = TransactionType.General.Builder(null).apply { addOutputState(state, DUMMY_NOTARY) diff --git a/node/src/test/kotlin/com/r3corda/node/services/VaultWithCashTest.kt b/node/src/test/kotlin/com/r3corda/node/services/VaultWithCashTest.kt index 4e85b0dc42..e6aef58684 100644 --- a/node/src/test/kotlin/com/r3corda/node/services/VaultWithCashTest.kt +++ b/node/src/test/kotlin/com/r3corda/node/services/VaultWithCashTest.kt @@ -83,7 +83,7 @@ class VaultWithCashTest { fun `issue and spend total correctly and irrelevant ignored`() { databaseTransaction(database) { // A tx that sends us money. - val freshKey = services.keyManagementService.freshKey() + val freshKey = services.storageService.myLegalIdentityKey val usefulTX = TransactionType.General.Builder(null).apply { Cash().generateIssue(this, 100.DOLLARS `issued by` MEGA_CORP.ref(1), freshKey.public, DUMMY_NOTARY) signWith(MEGA_CORP_KEY) @@ -121,7 +121,7 @@ class VaultWithCashTest { @Test fun `branching LinearStates fails to verify`() { databaseTransaction(database) { - val freshKey = services.keyManagementService.freshKey() + val freshKey = services.storageService.myLegalIdentityKey val linearId = UniqueIdentifier() // Issue a linear state @@ -141,7 +141,7 @@ class VaultWithCashTest { @Test fun `sequencing LinearStates works`() { databaseTransaction(database) { - val freshKey = services.keyManagementService.freshKey() + val freshKey = services.storageService.myLegalIdentityKey val linearId = UniqueIdentifier() diff --git a/src/main/kotlin/com/r3corda/demos/RateFixDemo.kt b/src/main/kotlin/com/r3corda/demos/RateFixDemo.kt index 1dffdebb63..f832324e1c 100644 --- a/src/main/kotlin/com/r3corda/demos/RateFixDemo.kt +++ b/src/main/kotlin/com/r3corda/demos/RateFixDemo.kt @@ -85,7 +85,7 @@ fun main(args: Array) { // Make a garbage transaction that includes a rate fix. val tx = TransactionType.General.Builder(notaryNode.identity) - tx.addOutputState(TransactionState(Cash.State(1500.DOLLARS `issued by` node.storage.myLegalIdentity.ref(1), node.keyManagement.freshKey().public), notaryNode.identity)) + tx.addOutputState(TransactionState(Cash.State(1500.DOLLARS `issued by` node.storage.myLegalIdentity.ref(1), node.storage.myLegalIdentityKey.public), notaryNode.identity)) val protocol = RatesFixProtocol(tx, rateOracle.identity, fixOf, expectedRate, rateTolerance) node.services.startProtocol("demo.ratefix", protocol).get() node.stop() diff --git a/src/main/kotlin/com/r3corda/demos/TraderDemo.kt b/src/main/kotlin/com/r3corda/demos/TraderDemo.kt index aa53daae2e..85f7df9927 100644 --- a/src/main/kotlin/com/r3corda/demos/TraderDemo.kt +++ b/src/main/kotlin/com/r3corda/demos/TraderDemo.kt @@ -202,7 +202,7 @@ private fun runBuyer(node: Node, amount: Amount) { databaseTransaction(node.database) { node.services.fillWithSomeTestCash(300000.DOLLARS, outputNotary = node.info.identity, // In this demo, the buyer and notary are the same. - ownedBy = node.services.keyManagementService.freshKey().public) + ownedBy = node.storage.myLegalIdentityKey.public) } // Wait around until a node asks to start a trade with us. In a real system, this part would happen out of band @@ -314,7 +314,7 @@ private class TraderDemoProtocolSeller(val otherSide: Party, progressTracker.currentStep = SELF_ISSUING val notary: NodeInfo = serviceHub.networkMapCache.notaryNodes[0] - val cpOwnerKey = serviceHub.keyManagementService.freshKey() + val cpOwnerKey = serviceHub.storageService.myLegalIdentityKey val commercialPaper = selfIssueSomeCommercialPaper(cpOwnerKey.public, notary) progressTracker.currentStep = TRADING diff --git a/src/main/kotlin/com/r3corda/demos/protocols/AutoOfferProtocol.kt b/src/main/kotlin/com/r3corda/demos/protocols/AutoOfferProtocol.kt index be9ce87cde..bd50522118 100644 --- a/src/main/kotlin/com/r3corda/demos/protocols/AutoOfferProtocol.kt +++ b/src/main/kotlin/com/r3corda/demos/protocols/AutoOfferProtocol.kt @@ -107,7 +107,7 @@ object AutoOfferProtocol { otherParty, notary, dealToBeOffered, - serviceHub.keyManagementService.freshKey(), + serviceHub.storageService.myLegalIdentityKey, progressTracker.getChildProgressTracker(DEALING)!! ) val stx = subProtocol(instigator, inheritParentSessions = true) diff --git a/src/main/kotlin/com/r3corda/simulation/IRSSimulation.kt b/src/main/kotlin/com/r3corda/simulation/IRSSimulation.kt index 6c7924ace3..33c86ae13d 100644 --- a/src/main/kotlin/com/r3corda/simulation/IRSSimulation.kt +++ b/src/main/kotlin/com/r3corda/simulation/IRSSimulation.kt @@ -32,17 +32,11 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten currentDateAndTime = LocalDate.of(2016, 3, 8).atStartOfDay() } - private var nodeAKey: KeyPair? = null - private var nodeBKey: KeyPair? = null - private val executeOnNextIteration = Collections.synchronizedList(LinkedList<() -> Unit>()) override fun startMainSimulation(): ListenableFuture { val future = SettableFuture.create() - nodeAKey = banks[0].keyManagement.freshKey() - nodeBKey = banks[1].keyManagement.freshKey() - startIRSDealBetween(0, 1).success { // Next iteration is a pause. executeOnNextIteration.add {} @@ -121,7 +115,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten irs.fixedLeg.fixedRatePayer = node1.info.identity irs.floatingLeg.floatingRatePayer = node2.info.identity - val instigator = TwoPartyDealProtocol.Instigator(node2.info.identity, notary.info.identity, irs, nodeAKey!!) + val instigator = TwoPartyDealProtocol.Instigator(node2.info.identity, notary.info.identity, irs, node1.keyPair!!) val acceptor = TwoPartyDealProtocol.Acceptor(node1.info.identity, notary.info.identity, irs) connectProtocols(instigator, acceptor) diff --git a/src/main/kotlin/com/r3corda/simulation/Simulation.kt b/src/main/kotlin/com/r3corda/simulation/Simulation.kt index 60e6cdf35f..4ea21863d7 100644 --- a/src/main/kotlin/com/r3corda/simulation/Simulation.kt +++ b/src/main/kotlin/com/r3corda/simulation/Simulation.kt @@ -3,6 +3,7 @@ package com.r3corda.simulation import com.google.common.net.HostAndPort import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.ListenableFuture +import com.r3corda.core.crypto.generateKeyPair import com.r3corda.core.messaging.SingleMessageRecipient import com.r3corda.core.node.CityDatabase import com.r3corda.core.node.PhysicalLocation @@ -73,8 +74,11 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, return SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, keyPair) } - fun createAll(): List = bankLocations. - map { network.createNode(networkMap.info.address, start = false, nodeFactory = this) as SimulatedNode } + fun createAll(): List { + return bankLocations.map { + network.createNode(networkMap.info.address, start = false, nodeFactory = this, keyPair = generateKeyPair()) as SimulatedNode + } + } } val bankFactory = BankFactory() diff --git a/src/main/resources/com/r3corda/demos/example-irs-trade.json b/src/main/resources/com/r3corda/demos/example-irs-trade.json index 19cc8e8951..d0d33c09e5 100644 --- a/src/main/resources/com/r3corda/demos/example-irs-trade.json +++ b/src/main/resources/com/r3corda/demos/example-irs-trade.json @@ -82,7 +82,7 @@ "quantity": 1000000, "token": "EUR" }, - "valuationDate": "Every Local Business Day", + "valuationDateDescription": "Every Local Business Day", "notificationTime": "2:00pm London", "resolutionTime": "2:00pm London time on the first LocalBusiness Day following the date on which the notice is given ", "interestRate": { diff --git a/src/main/resources/com/r3corda/demos/irswebdemo/js/viewmodel/Common.js b/src/main/resources/com/r3corda/demos/irswebdemo/js/viewmodel/Common.js index 7128ca4333..c6e58ffbc2 100644 --- a/src/main/resources/com/r3corda/demos/irswebdemo/js/viewmodel/Common.js +++ b/src/main/resources/com/r3corda/demos/irswebdemo/js/viewmodel/Common.js @@ -18,7 +18,7 @@ define([], () => { rounding: { quantity: 1000000 }, - valuationDate: "Every Local Business Day", + valuationDateDescription: "Every Local Business Day", notificationTime: "2:00pm London", resolutionTime: "2:00pm London time on the first LocalBusiness Day following the date on which the notice is given", interestRate: { diff --git a/src/main/resources/com/r3corda/demos/irswebdemo/view/deal.html b/src/main/resources/com/r3corda/demos/irswebdemo/view/deal.html index 033ec575a5..fae30c99b7 100644 --- a/src/main/resources/com/r3corda/demos/irswebdemo/view/deal.html +++ b/src/main/resources/com/r3corda/demos/irswebdemo/view/deal.html @@ -23,7 +23,7 @@ Valuation Date - {{deal.common.valuationDate}} + {{deal.common.valuationDateDescription}} Legal Document Hash diff --git a/src/main/resources/com/r3corda/simulation/trade.json b/src/main/resources/com/r3corda/simulation/trade.json index b574174652..36c73586a4 100644 --- a/src/main/resources/com/r3corda/simulation/trade.json +++ b/src/main/resources/com/r3corda/simulation/trade.json @@ -82,7 +82,7 @@ "quantity": 1000000, "token": "EUR" }, - "valuationDate": "Every Local Business Day", + "valuationDateDescription": "Every Local Business Day", "notificationTime": "2:00pm London", "resolutionTime": "2:00pm London time on the first LocalBusiness Day following the date on which the notice is given ", "interestRate": {