mirror of
https://github.com/corda/corda.git
synced 2025-02-01 08:48:09 +00:00
Merged in mike-ledgertx-refactoring-part-1 (pull request #251)
Small changes and tweaks in preparation for a later refactoring
This commit is contained in:
commit
a26adb1291
@ -344,7 +344,7 @@ public class JavaCommercialPaper extends ClauseVerifier {
|
||||
}
|
||||
|
||||
public void generateRedeem(TransactionBuilder tx, StateAndRef<State> paper, List<StateAndRef<Cash.State>> wallet) throws InsufficientBalanceException {
|
||||
new Cash().generateSpend(tx, paper.getState().getData().getFaceValue(), paper.getState().getData().getOwner(), wallet);
|
||||
new Cash().generateSpend(tx, StructuresKt.withoutIssuer(paper.getState().getData().getFaceValue()), paper.getState().getData().getOwner(), wallet, null);
|
||||
tx.addInputState(paper);
|
||||
tx.addCommand(new Command(new Commands.Redeem(paper.getState().getNotary()), paper.getState().getData().getOwner()));
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import com.r3corda.core.contracts.clauses.*
|
||||
import com.r3corda.core.crypto.*
|
||||
import com.r3corda.core.node.services.Wallet
|
||||
import com.r3corda.core.utilities.Emoji
|
||||
import java.math.BigInteger
|
||||
import java.security.PublicKey
|
||||
import java.util.*
|
||||
|
||||
@ -211,16 +212,6 @@ class Cash : ClauseVerifier() {
|
||||
tx.addCommand(Cash.Commands.Issue(), at.party.owningKey)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a transaction that consumes one or more of the given input states to move money to the given pubkey.
|
||||
* Note that the wallet list is not updated: it's up to you to do that.
|
||||
*/
|
||||
@Throws(InsufficientBalanceException::class)
|
||||
fun generateSpend(tx: TransactionBuilder, amount: Amount<Issued<Currency>>, to: PublicKey,
|
||||
cashStates: List<StateAndRef<State>>): List<PublicKey> =
|
||||
generateSpend(tx, Amount(amount.quantity, amount.token.product), to, cashStates,
|
||||
setOf(amount.token.issuer.party))
|
||||
|
||||
/**
|
||||
* Generate a transaction that consumes one or more of the given input states to move money to the given pubkey.
|
||||
* Note that the wallet list is not updated: it's up to you to do that.
|
||||
@ -301,21 +292,23 @@ class Cash : ClauseVerifier() {
|
||||
/**
|
||||
* Sums the cash states in the list belonging to a single owner, throwing an exception
|
||||
* if there are none, or if any of the cash states cannot be added together (i.e. are
|
||||
* different currencies).
|
||||
* different currencies or issuers).
|
||||
*/
|
||||
fun Iterable<ContractState>.sumCashBy(owner: PublicKey) = filterIsInstance<Cash.State>().filter { it.owner == owner }.map { it.amount }.sumOrThrow()
|
||||
fun Iterable<ContractState>.sumCashBy(owner: PublicKey): Amount<Issued<Currency>> = filterIsInstance<Cash.State>().filter { it.owner == owner }.map { it.amount }.sumOrThrow()
|
||||
|
||||
/**
|
||||
* Sums the cash states in the list, throwing an exception if there are none, or if any of the cash
|
||||
* states cannot be added together (i.e. are different currencies).
|
||||
*/
|
||||
fun Iterable<ContractState>.sumCash() = filterIsInstance<Cash.State>().map { it.amount }.sumOrThrow()
|
||||
fun Iterable<ContractState>.sumCash(): Amount<Issued<Currency>> = filterIsInstance<Cash.State>().map { it.amount }.sumOrThrow()
|
||||
|
||||
/** Sums the cash states in the list, returning null if there are none. */
|
||||
fun Iterable<ContractState>.sumCashOrNull() = filterIsInstance<Cash.State>().map { it.amount }.sumOrNull()
|
||||
fun Iterable<ContractState>.sumCashOrNull(): Amount<Issued<Currency>>? = filterIsInstance<Cash.State>().map { it.amount }.sumOrNull()
|
||||
|
||||
/** Sums the cash states in the list, returning zero of the given currency if there are none. */
|
||||
fun Iterable<ContractState>.sumCashOrZero(currency: Issued<Currency>) = filterIsInstance<Cash.State>().map { it.amount }.sumOrZero<Issued<Currency>>(currency)
|
||||
/** Sums the cash states in the list, returning zero of the given currency+issuer if there are none. */
|
||||
fun Iterable<ContractState>.sumCashOrZero(currency: Issued<Currency>): Amount<Issued<Currency>> {
|
||||
return filterIsInstance<Cash.State>().map { it.amount }.sumOrZero<Issued<Currency>>(currency)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of how much cash we have in each currency, ignoring details like issuer. Note: currencies for
|
||||
@ -342,7 +335,7 @@ infix fun Cash.State.`with deposit`(deposit: PartyAndReference): Cash.State = wi
|
||||
// Unit testing helpers. These could go in a separate file but it's hardly worth it for just a few functions.
|
||||
|
||||
/** A randomly generated key. */
|
||||
val DUMMY_CASH_ISSUER_KEY by lazy { generateKeyPair() }
|
||||
val DUMMY_CASH_ISSUER_KEY by lazy { entropyToKeyPair(BigInteger.valueOf(10)) }
|
||||
/** A dummy, randomly generated issuer party by the name of "Snake Oil Issuer" */
|
||||
val DUMMY_CASH_ISSUER by lazy { Party("Snake Oil Issuer", DUMMY_CASH_ISSUER_KEY.public).ref(1) }
|
||||
/** An extension property that lets you write 100.DOLLARS.CASH */
|
||||
|
@ -4,7 +4,9 @@ import com.r3corda.core.contracts.*
|
||||
import java.security.PublicKey
|
||||
import java.util.*
|
||||
|
||||
class InsufficientBalanceException(val amountMissing: Amount<*>) : Exception()
|
||||
class InsufficientBalanceException(val amountMissing: Amount<*>) : Exception() {
|
||||
override fun toString() = "Insufficient balance, missing $amountMissing"
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for contract states representing assets which are fungible, countable and issued by a
|
||||
|
@ -47,7 +47,7 @@ object TwoPartyTradeProtocol {
|
||||
|
||||
val TOPIC = "platform.trade"
|
||||
|
||||
class UnacceptablePriceException(val givenPrice: Amount<Issued<Currency>>) : Exception()
|
||||
class UnacceptablePriceException(val givenPrice: Amount<Currency>) : Exception()
|
||||
class AssetMismatchException(val expectedTypeName: String, val typeName: String) : Exception() {
|
||||
override fun toString() = "The submitted asset didn't match the expected type: $expectedTypeName vs $typeName"
|
||||
}
|
||||
@ -55,7 +55,7 @@ object TwoPartyTradeProtocol {
|
||||
// This object is serialised to the network and is the first protocol message the seller sends to the buyer.
|
||||
class SellerTradeInfo(
|
||||
val assetForSale: StateAndRef<OwnableState>,
|
||||
val price: Amount<Issued<Currency>>,
|
||||
val price: Amount<Currency>,
|
||||
val sellerOwnerKey: PublicKey,
|
||||
val sessionID: Long
|
||||
)
|
||||
@ -66,7 +66,7 @@ object TwoPartyTradeProtocol {
|
||||
open class Seller(val otherSide: Party,
|
||||
val notaryNode: NodeInfo,
|
||||
val assetToSell: StateAndRef<OwnableState>,
|
||||
val price: Amount<Issued<Currency>>,
|
||||
val price: Amount<Currency>,
|
||||
val myKeyPair: KeyPair,
|
||||
val buyerSessionID: Long,
|
||||
override val progressTracker: ProgressTracker = Seller.tracker()) : ProtocolLogic<SignedTransaction>() {
|
||||
@ -133,7 +133,7 @@ object TwoPartyTradeProtocol {
|
||||
// This verifies that the transaction is contract-valid, even though it is missing signatures.
|
||||
serviceHub.verifyTransaction(wtx.toLedgerTransaction(serviceHub.identityService, serviceHub.storageService.attachments))
|
||||
|
||||
if (wtx.outputs.map { it.data }.sumCashBy(myKeyPair.public) != price)
|
||||
if (wtx.outputs.map { it.data }.sumCashBy(myKeyPair.public).withoutIssuer() != price)
|
||||
throw IllegalArgumentException("Transaction is not sending us the right amount of cash")
|
||||
|
||||
// There are all sorts of funny games a malicious secondary might play here, we should fix them:
|
||||
@ -178,7 +178,7 @@ object TwoPartyTradeProtocol {
|
||||
|
||||
open class Buyer(val otherSide: Party,
|
||||
val notary: Party,
|
||||
val acceptablePrice: Amount<Issued<Currency>>,
|
||||
val acceptablePrice: Amount<Currency>,
|
||||
val typeToBuy: Class<out OwnableState>,
|
||||
val sessionID: Long) : ProtocolLogic<SignedTransaction>() {
|
||||
|
||||
|
@ -31,6 +31,11 @@ val Long.bd: BigDecimal get() = BigDecimal(this)
|
||||
|
||||
fun String.abbreviate(maxWidth: Int): String = if (length <= maxWidth) this else take(maxWidth - 1) + "…"
|
||||
|
||||
/** Like the + operator but throws an exception in case of integer overflow. */
|
||||
infix fun Int.checkedAdd(b: Int) = Math.addExact(this, b)
|
||||
/** Like the + operator but throws an exception in case of integer overflow. */
|
||||
infix fun Long.checkedAdd(b: Long) = Math.addExact(this, b)
|
||||
|
||||
/**
|
||||
* Returns a random positive long generated using a secure RNG. This function sacrifies a bit of entropy in order to
|
||||
* avoid potential bugs where the value is used in a context where negative numbers are not expected.
|
||||
|
@ -61,7 +61,7 @@ data class Amount<T>(val quantity: Long, val token: T) : Comparable<Amount<T>> {
|
||||
operator fun div(other: Int): Amount<T> = Amount(quantity / other, token)
|
||||
operator fun times(other: Int): Amount<T> = Amount(Math.multiplyExact(quantity, other.toLong()), token)
|
||||
|
||||
override fun toString(): String = (BigDecimal(quantity).divide(BigDecimal(100))).setScale(2).toPlainString()
|
||||
override fun toString(): String = (BigDecimal(quantity).divide(BigDecimal(100))).setScale(2).toPlainString() + " " + token
|
||||
|
||||
override fun compareTo(other: Amount<T>): Int {
|
||||
checkCurrency(other)
|
||||
|
@ -146,10 +146,16 @@ interface IssuanceDefinition
|
||||
*
|
||||
* @param P the type of product underlying the definition, for example [Currency].
|
||||
*/
|
||||
data class Issued<out P>(
|
||||
val issuer: PartyAndReference,
|
||||
val product: P
|
||||
)
|
||||
data class Issued<out P>(val issuer: PartyAndReference, val product: P) {
|
||||
override fun toString() = "$product issued by $issuer"
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips the issuer and returns an [Amount] of the raw token directly. This is useful when you are mixing code that
|
||||
* cares about specific issuers with code that will accept any, or which is imposing issuer constraints via some
|
||||
* other mechanism and the additional type safety is not wanted.
|
||||
*/
|
||||
fun <T> Amount<Issued<T>>.withoutIssuer(): Amount<T> = Amount(quantity, token.product)
|
||||
|
||||
/**
|
||||
* A contract state that can have a single owner.
|
||||
|
@ -120,9 +120,9 @@ open class TransactionBuilder(
|
||||
fun toSignedTransaction(checkSufficientSignatures: Boolean = true): SignedTransaction {
|
||||
if (checkSufficientSignatures) {
|
||||
val gotKeys = currentSigs.map { it.by }.toSet()
|
||||
val missing = signers - gotKeys
|
||||
val missing: Set<PublicKey> = signers - gotKeys
|
||||
if (missing.isNotEmpty())
|
||||
throw IllegalStateException("Missing signatures on the transaction for the public keys: ${missing.map { it.toStringShort() }}")
|
||||
throw IllegalStateException("Missing signatures on the transaction for the public keys: ${missing.toStringsShort()}")
|
||||
}
|
||||
return SignedTransaction(toWireTransaction().serialize(), ArrayList(currentSigs))
|
||||
}
|
||||
@ -131,7 +131,6 @@ open class TransactionBuilder(
|
||||
|
||||
fun addInputState(stateRef: StateRef, notary: Party) {
|
||||
check(currentSigs.isEmpty())
|
||||
|
||||
signers.add(notary.owningKey)
|
||||
inputs.add(stateRef)
|
||||
}
|
||||
|
@ -5,10 +5,14 @@ import com.r3corda.core.serialization.OpaqueBytes
|
||||
import com.r3corda.core.serialization.SerializedBytes
|
||||
import com.r3corda.core.serialization.deserialize
|
||||
import net.i2p.crypto.eddsa.EdDSAEngine
|
||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
||||
import net.i2p.crypto.eddsa.KeyPairGenerator
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec
|
||||
import java.math.BigInteger
|
||||
import java.security.*
|
||||
import net.i2p.crypto.eddsa.KeyPairGenerator as EddsaKeyPairGenerator
|
||||
|
||||
fun newSecureRandom(): SecureRandom {
|
||||
if (System.getProperty("os.name") == "Linux") {
|
||||
@ -115,6 +119,7 @@ object NullPublicKey : PublicKey, Comparable<PublicKey> {
|
||||
override fun toString() = "NULL_KEY"
|
||||
}
|
||||
|
||||
// TODO: Clean up this duplication between Null and Dummy public key
|
||||
class DummyPublicKey(val s: String) : PublicKey, Comparable<PublicKey> {
|
||||
override fun getAlgorithm() = "DUMMY"
|
||||
override fun getEncoded() = s.toByteArray()
|
||||
@ -125,6 +130,9 @@ class DummyPublicKey(val s: String) : PublicKey, Comparable<PublicKey> {
|
||||
override fun toString() = "PUBKEY[$s]"
|
||||
}
|
||||
|
||||
/** A signature with a key and value of zero. Useful when you want a signature object that you know won't ever be used. */
|
||||
object NullSignature : DigitalSignature.WithKey(NullPublicKey, ByteArray(32))
|
||||
|
||||
/** Utility to simplify the act of signing a byte array */
|
||||
fun PrivateKey.signWithECDSA(bits: ByteArray): DigitalSignature {
|
||||
val signer = EdDSAEngine()
|
||||
@ -163,10 +171,24 @@ fun PublicKey.toStringShort(): String {
|
||||
} ?: toString()
|
||||
}
|
||||
|
||||
fun Iterable<PublicKey>.toStringsShort(): String = map { it.toStringShort() }.toString()
|
||||
|
||||
// Allow Kotlin destructuring: val (private, public) = keypair
|
||||
operator fun KeyPair.component1() = this.private
|
||||
|
||||
operator fun KeyPair.component2() = this.public
|
||||
|
||||
/** A simple wrapper that will make it easier to swap out the EC algorithm we use in future */
|
||||
fun generateKeyPair(): KeyPair = EddsaKeyPairGenerator().generateKeyPair()
|
||||
fun generateKeyPair(): KeyPair = KeyPairGenerator().generateKeyPair()
|
||||
|
||||
/**
|
||||
* Returns a keypair derived from the given private key entropy. This is useful for unit tests and other cases where
|
||||
* you want hard-coded private keys.
|
||||
*/
|
||||
fun entropyToKeyPair(entropy: BigInteger): KeyPair {
|
||||
val params = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)
|
||||
val bits = entropy.toByteArray().copyOf(params.curve.field.getb() / 8)
|
||||
val priv = EdDSAPrivateKeySpec(bits, params)
|
||||
val pub = EdDSAPublicKeySpec(priv.a, params)
|
||||
val key = KeyPair(EdDSAPublicKey(pub), EdDSAPrivateKey(priv))
|
||||
return key
|
||||
}
|
||||
|
@ -7,14 +7,12 @@ import com.google.common.net.HostAndPort
|
||||
import com.r3corda.core.contracts.Attachment
|
||||
import com.r3corda.core.contracts.StateRef
|
||||
import com.r3corda.core.contracts.TransactionBuilder
|
||||
import com.r3corda.core.crypto.DummyPublicKey
|
||||
import com.r3corda.core.crypto.Party
|
||||
import com.r3corda.core.crypto.SecureHash
|
||||
import com.r3corda.core.crypto.generateKeyPair
|
||||
import com.r3corda.core.crypto.*
|
||||
import com.r3corda.core.node.services.IdentityService
|
||||
import com.r3corda.core.node.services.StorageService
|
||||
import com.r3corda.core.node.services.testing.MockIdentityService
|
||||
import com.r3corda.core.node.services.testing.MockStorageService
|
||||
import java.math.BigInteger
|
||||
import java.net.ServerSocket
|
||||
import java.security.KeyPair
|
||||
import java.security.PublicKey
|
||||
@ -73,7 +71,7 @@ val CHARLIE: Party get() = Party("Charlie", CHARLIE_PUBKEY)
|
||||
val MEGA_CORP: Party get() = Party("MegaCorp", MEGA_CORP_PUBKEY)
|
||||
val MINI_CORP: Party get() = Party("MiniCorp", MINI_CORP_PUBKEY)
|
||||
|
||||
val DUMMY_NOTARY_KEY: KeyPair by lazy { generateKeyPair() }
|
||||
val DUMMY_NOTARY_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(20)) }
|
||||
val DUMMY_NOTARY: Party get() = Party("Notary Service", DUMMY_NOTARY_KEY.public)
|
||||
|
||||
val ALL_TEST_KEYS: List<KeyPair> get() = listOf(MEGA_CORP_KEY, MINI_CORP_KEY, ALICE_KEY, BOB_KEY, DUMMY_NOTARY_KEY)
|
||||
|
@ -53,9 +53,7 @@ interface TransactionDSLInterpreter : Verifies, OutputStateLookup {
|
||||
fun tweak(dsl: TransactionDSL<TransactionDSLInterpreter>.() -> EnforceVerifyOrFail): EnforceVerifyOrFail
|
||||
}
|
||||
|
||||
class TransactionDSL<out T : TransactionDSLInterpreter> (val interpreter: T) :
|
||||
TransactionDSLInterpreter by interpreter {
|
||||
|
||||
class TransactionDSL<out T : TransactionDSLInterpreter>(val interpreter: T) : TransactionDSLInterpreter by interpreter {
|
||||
/**
|
||||
* Looks up the output label and adds the found state as an input.
|
||||
* @param stateLabel The label of the output state specified when calling [TransactionDSLInterpreter._output] and friends.
|
||||
|
@ -8,8 +8,6 @@ import com.r3corda.contracts.testing.fillWithSomeTestCash
|
||||
import com.r3corda.core.contracts.DOLLARS
|
||||
import com.r3corda.core.contracts.SignedTransaction
|
||||
import com.r3corda.core.contracts.`issued by`
|
||||
import com.r3corda.core.crypto.Party
|
||||
import com.r3corda.core.crypto.generateKeyPair
|
||||
import com.r3corda.core.days
|
||||
import com.r3corda.core.random63BitValue
|
||||
import com.r3corda.core.seconds
|
||||
@ -43,8 +41,7 @@ class TradeSimulation(runAsync: Boolean, latencyInjector: InMemoryMessagingNetwo
|
||||
}
|
||||
seller.services.recordTransactions(issuance)
|
||||
|
||||
val cashIssuerKey = generateKeyPair()
|
||||
val amount = 1000.DOLLARS `issued by` Party("Big friendly bank", cashIssuerKey.public).ref(1)
|
||||
val amount = 1000.DOLLARS
|
||||
val sessionID = random63BitValue()
|
||||
val buyerProtocol = TwoPartyTradeProtocol.Buyer(
|
||||
seller.info.identity,
|
||||
|
@ -270,8 +270,10 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, tokenizableService
|
||||
request.payload?.let {
|
||||
psm.logger.trace { "Sending message of type ${it.javaClass.name} using queue $queueID to ${request.destination} (${it.toString().abbreviate(50)})" }
|
||||
val node = serviceHub.networkMapCache.getNodeByLegalName(request.destination!!.name)
|
||||
requireNotNull(node) { "Don't know about ${request.destination}" }
|
||||
serviceHub.networkService.send(queueID, it, node!!.address)
|
||||
if (node == null) {
|
||||
throw IllegalArgumentException("Don't know about ${request.destination} but trying to send a message of type ${it.javaClass.name} on $queueID (${it.toString().abbreviate(50)})", request.stackTraceInCaseOfProblems)
|
||||
}
|
||||
serviceHub.networkService.send(queueID, it, node.address)
|
||||
}
|
||||
if (request is FiberRequest.NotExpectingResponse) {
|
||||
// We sent a message, but don't expect a response, so re-enter the continuation to let it keep going.
|
||||
|
@ -54,14 +54,14 @@ class TwoPartyTradeProtocolTests {
|
||||
lateinit var net: MockNetwork
|
||||
|
||||
private fun runSeller(smm: StateMachineManager, notary: NodeInfo,
|
||||
otherSide: Party, assetToSell: StateAndRef<OwnableState>, price: Amount<Issued<Currency>>,
|
||||
otherSide: Party, assetToSell: StateAndRef<OwnableState>, price: Amount<Currency>,
|
||||
myKeyPair: KeyPair, buyerSessionID: Long): ListenableFuture<SignedTransaction> {
|
||||
val seller = TwoPartyTradeProtocol.Seller(otherSide, notary, assetToSell, price, myKeyPair, buyerSessionID)
|
||||
return smm.add("${TwoPartyTradeProtocol.TOPIC}.seller", seller)
|
||||
}
|
||||
|
||||
private fun runBuyer(smm: StateMachineManager, notaryNode: NodeInfo,
|
||||
otherSide: Party, acceptablePrice: Amount<Issued<Currency>>, typeToBuy: Class<out OwnableState>,
|
||||
otherSide: Party, acceptablePrice: Amount<Currency>, typeToBuy: Class<out OwnableState>,
|
||||
sessionID: Long): ListenableFuture<SignedTransaction> {
|
||||
val buyer = TwoPartyTradeProtocol.Buyer(otherSide, notaryNode.identity, acceptablePrice, typeToBuy, sessionID)
|
||||
return smm.add("${TwoPartyTradeProtocol.TOPIC}.buyer", buyer)
|
||||
@ -106,7 +106,7 @@ class TwoPartyTradeProtocolTests {
|
||||
bobNode.smm,
|
||||
notaryNode.info,
|
||||
aliceNode.info.identity,
|
||||
1000.DOLLARS `issued by` issuer,
|
||||
1000.DOLLARS,
|
||||
CommercialPaper.State::class.java,
|
||||
buyerSessionID
|
||||
)
|
||||
@ -115,7 +115,7 @@ class TwoPartyTradeProtocolTests {
|
||||
notaryNode.info,
|
||||
bobNode.info.identity,
|
||||
"alice's paper".outputStateAndRef(),
|
||||
1000.DOLLARS `issued by` issuer,
|
||||
1000.DOLLARS,
|
||||
ALICE_KEY,
|
||||
buyerSessionID
|
||||
)
|
||||
@ -158,7 +158,7 @@ class TwoPartyTradeProtocolTests {
|
||||
notaryNode.info,
|
||||
bobNode.info.identity,
|
||||
"alice's paper".outputStateAndRef(),
|
||||
1000.DOLLARS `issued by` issuer,
|
||||
1000.DOLLARS,
|
||||
ALICE_KEY,
|
||||
buyerSessionID
|
||||
)
|
||||
@ -166,7 +166,7 @@ class TwoPartyTradeProtocolTests {
|
||||
bobNode.smm,
|
||||
notaryNode.info,
|
||||
aliceNode.info.identity,
|
||||
1000.DOLLARS `issued by` issuer,
|
||||
1000.DOLLARS,
|
||||
CommercialPaper.State::class.java,
|
||||
buyerSessionID
|
||||
)
|
||||
@ -279,7 +279,7 @@ class TwoPartyTradeProtocolTests {
|
||||
notaryNode.info,
|
||||
bobNode.info.identity,
|
||||
"alice's paper".outputStateAndRef(),
|
||||
1000.DOLLARS `issued by` issuer,
|
||||
1000.DOLLARS,
|
||||
ALICE_KEY,
|
||||
buyerSessionID
|
||||
)
|
||||
@ -287,7 +287,7 @@ class TwoPartyTradeProtocolTests {
|
||||
bobNode.smm,
|
||||
notaryNode.info,
|
||||
aliceNode.info.identity,
|
||||
1000.DOLLARS `issued by` issuer,
|
||||
1000.DOLLARS,
|
||||
CommercialPaper.State::class.java,
|
||||
buyerSessionID
|
||||
)
|
||||
@ -390,7 +390,7 @@ class TwoPartyTradeProtocolTests {
|
||||
notaryNode.info,
|
||||
bobNode.info.identity,
|
||||
"alice's paper".outputStateAndRef(),
|
||||
1000.DOLLARS `issued by` issuer,
|
||||
1000.DOLLARS,
|
||||
ALICE_KEY,
|
||||
buyerSessionID
|
||||
)
|
||||
@ -398,7 +398,7 @@ class TwoPartyTradeProtocolTests {
|
||||
bobNode.smm,
|
||||
notaryNode.info,
|
||||
aliceNode.info.identity,
|
||||
1000.DOLLARS `issued by` issuer,
|
||||
1000.DOLLARS,
|
||||
CommercialPaper.State::class.java,
|
||||
buyerSessionID
|
||||
)
|
||||
|
@ -76,7 +76,7 @@ class WalletWithCashTest {
|
||||
|
||||
// A tx that spends our money.
|
||||
val spendTX = TransactionType.General.Builder().apply {
|
||||
Cash().generateSpend(this, 80.DOLLARS `issued by` MEGA_CORP.ref(1), BOB_PUBKEY, listOf(myOutput))
|
||||
Cash().generateSpend(this, 80.DOLLARS, BOB_PUBKEY, listOf(myOutput))
|
||||
signWith(freshKey)
|
||||
signWith(DUMMY_NOTARY_KEY)
|
||||
}.toSignedTransaction()
|
||||
|
@ -164,7 +164,7 @@ fun runTraderDemo(args: Array<String>): Int {
|
||||
|
||||
// What happens next depends on the role. The buyer sits around waiting for a trade to start. The seller role
|
||||
// will contact the buyer and actually make something happen.
|
||||
val amount = 1000.DOLLARS `issued by` cashIssuer.ref(0) // Note: "0" has to match the reference used in the wallet filler
|
||||
val amount = 1000.DOLLARS
|
||||
if (role == Role.BUYER) {
|
||||
runBuyer(node, amount)
|
||||
} else {
|
||||
@ -174,7 +174,7 @@ fun runTraderDemo(args: Array<String>): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
private fun runSeller(node: Node, amount: Amount<Issued<Currency>>, otherSide: Party) {
|
||||
private fun runSeller(node: Node, amount: Amount<Currency>, otherSide: Party) {
|
||||
// The seller will sell some commercial paper to the buyer, who will pay with (self issued) cash.
|
||||
//
|
||||
// The CP sale transaction comes with a prospectus PDF, which will tag along for the ride in an
|
||||
@ -202,7 +202,7 @@ private fun runSeller(node: Node, amount: Amount<Issued<Currency>>, otherSide: P
|
||||
node.stop()
|
||||
}
|
||||
|
||||
private fun runBuyer(node: Node, amount: Amount<Issued<Currency>>) {
|
||||
private fun runBuyer(node: Node, amount: Amount<Currency>) {
|
||||
// Buyer will fetch the attachment from the seller automatically when it resolves the transaction.
|
||||
// For demo purposes just extract attachment jars when saved to disk, so the user can explore them.
|
||||
val attachmentsPath = (node.storage.attachments as NodeAttachmentService).let {
|
||||
@ -236,7 +236,7 @@ val DEMO_TOPIC = "initiate.demo.trade"
|
||||
|
||||
private class TraderDemoProtocolBuyer(val otherSide: Party,
|
||||
private val attachmentsPath: Path,
|
||||
val amount: Amount<Issued<Currency>>,
|
||||
val amount: Amount<Currency>,
|
||||
override val progressTracker: ProgressTracker = ProgressTracker(STARTING_BUY)) : ProtocolLogic<Unit>() {
|
||||
|
||||
object STARTING_BUY : ProgressTracker.Step("Seller connected, purchasing commercial paper asset")
|
||||
@ -294,7 +294,7 @@ ${Emoji.renderIfSupported(cpIssuance)}""")
|
||||
}
|
||||
|
||||
private class TraderDemoProtocolSeller(val otherSide: Party,
|
||||
val amount: Amount<Issued<Currency>>,
|
||||
val amount: Amount<Currency>,
|
||||
override val progressTracker: ProgressTracker = TraderDemoProtocolSeller.tracker()) : ProtocolLogic<SignedTransaction>() {
|
||||
companion object {
|
||||
val PROSPECTUS_HASH = SecureHash.parse("decd098666b9657314870e192ced0c3519c2c9d395507a238338f8d003929de9")
|
||||
|
Loading…
x
Reference in New Issue
Block a user