mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Updated Corda in preparation for the merging of the Vega cordapp. Includes
some minor changes, including gitignore rule changes. The largest change is replacing the current fresh key for each transaction with a single static identity in preparation for aimproved and more fleshed out key sharing infrastructure.
This commit is contained in:
parent
6c96517f6f
commit
43de27c4c1
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) {
|
||||
|
@ -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"),
|
||||
|
@ -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.
|
||||
|
@ -70,8 +70,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> {
|
||||
@ -93,7 +93,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 {
|
||||
@ -179,7 +182,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) {
|
||||
@ -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")
|
||||
class StateReplacementException(val error: StateReplacementRefused) : Exception("State change failed - $error")
|
||||
|
@ -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<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)
|
||||
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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…
Reference in New Issue
Block a user