mirror of
https://github.com/corda/corda.git
synced 2025-06-01 15:10:54 +00:00
Merged in clint-vegacorechanges (pull request #380)
Corda Changes required for Vega
This commit is contained in:
commit
7afb034b8c
26
.gitignore
vendored
26
.gitignore
vendored
@ -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/
|
||||
|
@ -201,7 +201,7 @@ class InterestRateSwap() : Contract {
|
||||
val threshold: Amount<Currency>,
|
||||
val minimumTransferAmount: Amount<Currency>,
|
||||
val rounding: Amount<Currency>,
|
||||
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) {
|
||||
|
@ -7,11 +7,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
|
||||
@ -93,7 +90,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"),
|
||||
@ -183,7 +180,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"),
|
||||
|
@ -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")
|
||||
|
||||
|
@ -279,9 +279,6 @@ interface DealState : LinearState {
|
||||
/** Exposes the Parties involved in a generic way */
|
||||
val parties: List<Party>
|
||||
|
||||
// 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.
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -150,6 +150,10 @@ interface VaultService {
|
||||
}
|
||||
|
||||
inline fun <reified T : LinearState> VaultService.linearHeadsOfType() = linearHeadsOfType_(T::class.java)
|
||||
inline fun <reified T : DealState> VaultService.dealsWith(party: Party) = linearHeadsOfType<T>().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,
|
||||
|
@ -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<T>] implements a protocol flow using direct, straight line blocking code. Thus you
|
||||
@ -108,6 +112,11 @@ abstract class ProtocolLogic<out T> {
|
||||
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.
|
||||
|
@ -71,8 +71,8 @@ abstract class AbstractStateReplacementProtocol<T> {
|
||||
return finalTx.tx.outRef(0)
|
||||
}
|
||||
|
||||
abstract internal fun assembleProposal(stateRef: StateRef, modification: T, stx: SignedTransaction): Proposal<T>
|
||||
abstract internal fun assembleTx(): Pair<SignedTransaction, List<PublicKey>>
|
||||
abstract protected fun assembleProposal(stateRef: StateRef, modification: T, stx: SignedTransaction): Proposal<T>
|
||||
abstract protected fun assembleTx(): Pair<SignedTransaction, List<PublicKey>>
|
||||
|
||||
@Suspendable
|
||||
private fun collectSignatures(participants: List<PublicKey>, stx: SignedTransaction): List<DigitalSignature.WithKey> {
|
||||
@ -94,7 +94,10 @@ abstract class AbstractStateReplacementProtocol<T> {
|
||||
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<Result>(party, proposal)
|
||||
val participantSignature = response.unwrap {
|
||||
@ -180,7 +183,7 @@ abstract class AbstractStateReplacementProtocol<T> {
|
||||
* 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<T>>): Proposal<T>
|
||||
abstract protected fun verifyProposal(maybeProposal: UntrustworthyData<Proposal<T>>): Proposal<T>
|
||||
|
||||
@Suspendable
|
||||
private fun verifyTx(stx: SignedTransaction) {
|
||||
|
@ -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.recordTransactions
|
||||
import com.r3corda.core.node.services.ServiceType
|
||||
@ -286,22 +287,11 @@ object TwoPartyDealProtocol {
|
||||
override fun validateHandshake(handshake: Handshake<T>): Handshake<T> {
|
||||
// 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)
|
||||
|
||||
}
|
||||
|
||||
|
@ -262,7 +262,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)
|
||||
|
@ -84,7 +84,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)
|
||||
@ -122,7 +122,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
|
||||
@ -142,7 +142,7 @@ class VaultWithCashTest {
|
||||
@Test
|
||||
fun `sequencing LinearStates works`() {
|
||||
databaseTransaction(database) {
|
||||
val freshKey = services.keyManagementService.freshKey()
|
||||
val freshKey = services.storageService.myLegalIdentityKey
|
||||
|
||||
val linearId = UniqueIdentifier()
|
||||
|
||||
|
@ -85,7 +85,7 @@ fun main(args: Array<String>) {
|
||||
|
||||
// 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()
|
||||
|
@ -202,7 +202,7 @@ private fun runBuyer(node: Node, amount: Amount<Currency>) {
|
||||
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
|
||||
|
@ -107,7 +107,7 @@ object AutoOfferProtocol {
|
||||
otherParty,
|
||||
notary,
|
||||
dealToBeOffered,
|
||||
serviceHub.keyManagementService.freshKey(),
|
||||
serviceHub.storageService.myLegalIdentityKey,
|
||||
progressTracker.getChildProgressTracker(DEALING)!!
|
||||
)
|
||||
val stx = subProtocol(instigator, inheritParentSessions = true)
|
||||
|
@ -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<Unit> {
|
||||
val future = SettableFuture.create<Unit>()
|
||||
|
||||
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)
|
||||
|
||||
|
@ -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<SimulatedNode> = bankLocations.
|
||||
map { network.createNode(networkMap.info.address, start = false, nodeFactory = this) as SimulatedNode }
|
||||
fun createAll(): List<SimulatedNode> {
|
||||
return bankLocations.map {
|
||||
network.createNode(networkMap.info.address, start = false, nodeFactory = this, keyPair = generateKeyPair()) as SimulatedNode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val bankFactory = BankFactory()
|
||||
|
@ -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": {
|
||||
|
@ -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: {
|
||||
|
@ -23,7 +23,7 @@
|
||||
</tr>
|
||||
<tr class="center aligned">
|
||||
<td>Valuation Date</td>
|
||||
<td>{{deal.common.valuationDate}}</td>
|
||||
<td>{{deal.common.valuationDateDescription}}</td>
|
||||
</tr>
|
||||
<tr class="center aligned">
|
||||
<td>Legal Document Hash</td>
|
||||
|
@ -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": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user