Merged in clint-vegacorechanges (pull request #380)

Corda Changes required for Vega
This commit is contained in:
Clinton Alexander 2016-09-28 16:28:15 +01:00
commit 7afb034b8c
21 changed files with 64 additions and 73 deletions

26
.gitignore vendored
View File

@ -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/

View File

@ -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) {

View File

@ -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"),

View File

@ -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")

View File

@ -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.

View File

@ -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()
}

View File

@ -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,

View File

@ -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.

View File

@ -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) {

View File

@ -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)
}

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -107,7 +107,7 @@ object AutoOfferProtocol {
otherParty,
notary,
dealToBeOffered,
serviceHub.keyManagementService.freshKey(),
serviceHub.storageService.myLegalIdentityKey,
progressTracker.getChildProgressTracker(DEALING)!!
)
val stx = subProtocol(instigator, inheritParentSessions = true)

View File

@ -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)

View File

@ -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()

View File

@ -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": {

View File

@ -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: {

View File

@ -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>

View File

@ -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": {