Remove deprecated signing functions

* Remove TransactionBuilder.signWith()
* Remove TransactionBuilder.addSignatureUnchecked()
* Rename signInitialTransaction to toSignedTransaction
* Remove checkAndAddSignature()
* Require all unit tests sign transactions via services
This commit is contained in:
Ross Nicoll 2017-08-04 11:50:52 +01:00
parent 907ec9ff46
commit f0c7d7665a
21 changed files with 468 additions and 494 deletions

View File

@ -137,10 +137,7 @@ interface ServiceHub : ServicesForResolution {
// Helper method to construct an initial partially signed transaction from a [TransactionBuilder]. // Helper method to construct an initial partially signed transaction from a [TransactionBuilder].
private fun signInitialTransaction(builder: TransactionBuilder, publicKey: PublicKey, signatureMetadata: SignatureMetadata): SignedTransaction { private fun signInitialTransaction(builder: TransactionBuilder, publicKey: PublicKey, signatureMetadata: SignatureMetadata): SignedTransaction {
val signableData = SignableData(builder.toWireTransaction().id, signatureMetadata) return builder.toSignedTransaction(keyManagementService, publicKey, signatureMetadata)
val sig = keyManagementService.sign(signableData, publicKey)
builder.addSignatureUnchecked(sig)
return builder.toSignedTransaction(false)
} }
/** /**

View File

@ -1,15 +1,16 @@
package net.corda.core.transactions package net.corda.core.transactions
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.*
import net.corda.core.crypto.TransactionSignature
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.VisibleForTesting
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializedBytes import net.corda.core.serialization.SerializedBytes
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import java.security.KeyPair
import java.security.PublicKey import java.security.PublicKey
import java.security.SignatureException import java.security.SignatureException
import java.util.* import java.util.*
@ -74,6 +75,12 @@ data class SignedTransaction(val txBits: SerializedBytes<CoreTransaction>,
return descriptions return descriptions
} }
@VisibleForTesting
fun withAdditionalSignature(keyPair: KeyPair, signatureMetadata: SignatureMetadata): SignedTransaction {
val signableData = SignableData(tx.id, signatureMetadata)
return withAdditionalSignature(keyPair.sign(signableData))
}
/** Returns the same transaction but with an additional (unchecked) signature. */ /** Returns the same transaction but with an additional (unchecked) signature. */
fun withAdditionalSignature(sig: TransactionSignature) = copyWithCache(listOf(sig)) fun withAdditionalSignature(sig: TransactionSignature) = copyWithCache(listOf(sig))

View File

@ -6,9 +6,9 @@ import net.corda.core.crypto.*
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.FlowStateMachine import net.corda.core.internal.FlowStateMachine
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.node.services.KeyManagementService
import java.security.KeyPair import java.security.KeyPair
import java.security.PublicKey import java.security.PublicKey
import java.security.SignatureException
import java.time.Duration import java.time.Duration
import java.time.Instant import java.time.Instant
import java.util.* import java.util.*
@ -149,59 +149,14 @@ open class TransactionBuilder(
fun outputStates(): List<TransactionState<*>> = ArrayList(outputs) fun outputStates(): List<TransactionState<*>> = ArrayList(outputs)
fun commands(): List<Command<*>> = ArrayList(commands) fun commands(): List<Command<*>> = ArrayList(commands)
/** The signatures that have been collected so far - might be incomplete! */ /**
@Deprecated("Signatures should be gathered on a SignedTransaction instead.") * Sign the built transaction and return it. This is an internal function for use by the service hub, please use
protected val currentSigs = arrayListOf<TransactionSignature>() * [ServiceHub.signInitialTransaction] instead.
*/
@Deprecated("Use ServiceHub.signInitialTransaction() instead.") fun toSignedTransaction(keyManagementService: KeyManagementService, publicKey: PublicKey, signatureMetadata: SignatureMetadata): SignedTransaction {
fun signWith(key: KeyPair): TransactionBuilder {
val signableData = SignableData(toWireTransaction().id, SignatureMetadata(1, Crypto.findSignatureScheme(key.public).schemeNumberID)) // A dummy platformVersion.
addSignatureUnchecked(key.sign(signableData))
return this
}
/** Adds the signature directly to the transaction, without checking it for validity. */
@Deprecated("Use ServiceHub.signInitialTransaction() instead.")
fun addSignatureUnchecked(sig: TransactionSignature): TransactionBuilder {
currentSigs.add(sig)
return this
}
@Deprecated("Use ServiceHub.signInitialTransaction() instead.")
fun toSignedTransaction(checkSufficientSignatures: Boolean = true): SignedTransaction {
if (checkSufficientSignatures) {
val gotKeys = currentSigs.map { it.by }.toSet()
val requiredKeys = commands.flatMap { it.signers }.toSet()
val missing: Set<PublicKey> = requiredKeys.filter { !it.isFulfilledBy(gotKeys) }.toSet()
if (missing.isNotEmpty())
throw IllegalStateException("Missing signatures on the transaction for the public keys: ${missing.joinToString()}")
}
val wtx = toWireTransaction() val wtx = toWireTransaction()
return SignedTransaction(wtx, ArrayList(currentSigs)) val signableData = SignableData(wtx.id, signatureMetadata)
} val sig = keyManagementService.sign(signableData, publicKey)
return SignedTransaction(wtx, listOf(sig))
/**
* Checks that the given signature matches one of the commands and that it is a correct signature over the tx, then
* adds it.
*
* @throws SignatureException if the signature didn't match the transaction contents.
* @throws IllegalArgumentException if the signature key doesn't appear in any command.
*/
@Deprecated("Use WireTransaction.checkSignature() instead.")
fun checkAndAddSignature(sig: TransactionSignature) {
checkSignature(sig)
addSignatureUnchecked(sig)
}
/**
* Checks that the given signature matches one of the commands and that it is a correct signature over the tx.
*
* @throws SignatureException if the signature didn't match the transaction contents.
* @throws IllegalArgumentException if the signature key doesn't appear in any command.
*/
@Deprecated("Use WireTransaction.checkSignature() instead.")
fun checkSignature(sig: TransactionSignature) {
require(commands.any { it.signers.any { sig.by in it.keys } }) { "Signature key doesn't match any command" }
sig.verify(toWireTransaction().id)
} }
} }

View File

@ -24,7 +24,7 @@ Additional, ``ServiceHub`` exposes the following properties:
* ``ServiceHub.loadState`` and ``ServiceHub.toStateAndRef`` to resolve a ``StateRef`` into a ``TransactionState`` or * ``ServiceHub.loadState`` and ``ServiceHub.toStateAndRef`` to resolve a ``StateRef`` into a ``TransactionState`` or
a ``StateAndRef`` a ``StateAndRef``
* ``ServiceHub.signInitialTransaction`` to sign a ``TransactionBuilder`` and convert it into a ``SignedTransaction`` * ``ServiceHub.toSignedTransaction`` to sign a ``TransactionBuilder`` and convert it into a ``SignedTransaction``
* ``ServiceHub.createSignature`` and ``ServiceHub.addSignature`` to create and add signatures to a ``SignedTransaction`` * ``ServiceHub.createSignature`` and ``ServiceHub.addSignature`` to create and add signatures to a ``SignedTransaction``
Finally, ``ServiceHub`` exposes the node's legal identity key (via ``ServiceHub.legalIdentityKey``) and its notary Finally, ``ServiceHub`` exposes the node's legal identity key (via ``ServiceHub.legalIdentityKey``) and its notary

View File

@ -276,7 +276,7 @@ Milestone 12
with the ``PrivateKey`` kept internally to the service. with the ``PrivateKey`` kept internally to the service.
* Flows which used to acquire a node's ``KeyPair``, typically via ``ServiceHub.legalIdentityKey``, * Flows which used to acquire a node's ``KeyPair``, typically via ``ServiceHub.legalIdentityKey``,
should instead use the helper methods on ``ServiceHub``. In particular to freeze a ``TransactionBuilder`` and should instead use the helper methods on ``ServiceHub``. In particular to freeze a ``TransactionBuilder`` and
generate an initial partially signed ``SignedTransaction`` the flow should use ``ServiceHub.signInitialTransaction``. generate an initial partially signed ``SignedTransaction`` the flow should use ``ServiceHub.toSignedTransaction``.
Flows generating additional party signatures should use ``ServiceHub.createSignature``. Each of these methods is Flows generating additional party signatures should use ``ServiceHub.createSignature``. Each of these methods is
provided with two signatures. One version that signs with the default node key, the other which allows key selection provided with two signatures. One version that signs with the default node key, the other which allows key selection
by passing in the ``PublicKey`` partner of the desired signing key. by passing in the ``PublicKey`` partner of the desired signing key.

View File

@ -79,7 +79,7 @@ the following:
txBuilder.verify(serviceHub) txBuilder.verify(serviceHub)
// Signing the transaction. // Signing the transaction.
val signedTx = serviceHub.signInitialTransaction(txBuilder) val signedTx = serviceHub.toSignedTransaction(txBuilder)
// Finalising the transaction. // Finalising the transaction.
subFlow(FinalityFlow(signedTx)) subFlow(FinalityFlow(signedTx))
@ -141,7 +141,7 @@ the following:
txBuilder.verify(getServiceHub()); txBuilder.verify(getServiceHub());
// Signing the transaction. // Signing the transaction.
final SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder); final SignedTransaction signedTx = getServiceHub().toSignedTransaction(txBuilder);
// Finalising the transaction. // Finalising the transaction.
subFlow(new FinalityFlow(signedTx)); subFlow(new FinalityFlow(signedTx));
@ -229,7 +229,7 @@ Signing the transaction
Now that we have a valid transaction proposal, we need to sign it. Once the transaction is signed, no-one will be able Now that we have a valid transaction proposal, we need to sign it. Once the transaction is signed, no-one will be able
to modify the transaction without invalidating our signature, effectively making the transaction immutable. to modify the transaction without invalidating our signature, effectively making the transaction immutable.
The call to ``ServiceHub.signInitialTransaction`` returns a ``SignedTransaction`` - an object that pairs the The call to ``ServiceHub.toSignedTransaction`` returns a ``SignedTransaction`` - an object that pairs the
transaction itself with a list of signatures over that transaction. transaction itself with a list of signatures over that transaction.
Finalising the transaction Finalising the transaction

View File

@ -36,7 +36,7 @@ In ``IOUFlow.java``/``IOUFlow.kt``, update ``IOUFlow.call`` as follows:
txBuilder.verify(serviceHub) txBuilder.verify(serviceHub)
// Signing the transaction. // Signing the transaction.
val signedTx = serviceHub.signInitialTransaction(txBuilder) val signedTx = serviceHub.toSignedTransaction(txBuilder)
// Obtaining the counterparty's signature // Obtaining the counterparty's signature
val fullySignedTx = subFlow(CollectSignaturesFlow(signedTx)) val fullySignedTx = subFlow(CollectSignaturesFlow(signedTx))
@ -56,7 +56,7 @@ In ``IOUFlow.java``/``IOUFlow.kt``, update ``IOUFlow.call`` as follows:
txBuilder.verify(getServiceHub()); txBuilder.verify(getServiceHub());
// Signing the transaction. // Signing the transaction.
final SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder); final SignedTransaction signedTx = getServiceHub().toSignedTransaction(txBuilder);
// Obtaining the counterparty's signature // Obtaining the counterparty's signature
final SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(signedTx, null)); final SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(signedTx, null));

View File

@ -707,7 +707,7 @@ from the ledger). Finally, we add a Redeem command that should be signed by the
A ``TransactionBuilder`` is not by itself ready to be used anywhere, so first, we must convert it to something that A ``TransactionBuilder`` is not by itself ready to be used anywhere, so first, we must convert it to something that
is recognised by the network. The most important next step is for the participating entities to sign it. Typically, is recognised by the network. The most important next step is for the participating entities to sign it. Typically,
an initiating flow will create an initial partially signed ``SignedTransaction`` by calling the ``serviceHub.signInitialTransaction`` method. an initiating flow will create an initial partially signed ``SignedTransaction`` by calling the ``serviceHub.toSignedTransaction`` method.
Then the frozen ``SignedTransaction`` can be passed to other nodes by the flow, these can sign using ``serviceHub.createSignature`` and distribute. Then the frozen ``SignedTransaction`` can be passed to other nodes by the flow, these can sign using ``serviceHub.createSignature`` and distribute.
The ``CollectSignaturesFlow`` provides a generic implementation of this process that can be used as a ``subFlow`` . The ``CollectSignaturesFlow`` provides a generic implementation of this process that can be used as a ``subFlow`` .

View File

@ -64,7 +64,7 @@ We then sign the transaction, build and record it to our transaction storage:
.. sourcecode:: kotlin .. sourcecode:: kotlin
val mySigningKey: PublicKey = serviceHub.legalIdentityKey val mySigningKey: PublicKey = serviceHub.legalIdentityKey
val issueTransaction = serviceHub.signInitialTransaction(issueTransaction, mySigningKey) val issueTransaction = serviceHub.toSignedTransaction(issueTransaction, mySigningKey)
serviceHub.recordTransactions(issueTransaction) serviceHub.recordTransactions(issueTransaction)
The transaction is recorded and we now have a state (asset) in possession that we can transfer to someone else. Note The transaction is recorded and we now have a state (asset) in possession that we can transfer to someone else. Note
@ -98,7 +98,7 @@ Again we sign the transaction, and build it:
// We build it and add our default identity signature without checking if all signatures are present, // We build it and add our default identity signature without checking if all signatures are present,
// Note we know that the notary signature is missing, so thie SignedTransaction is still partial. // Note we know that the notary signature is missing, so thie SignedTransaction is still partial.
val moveTransaction = serviceHub.signInitialTransaction(moveTransactionBuilder) val moveTransaction = serviceHub.toSignedTransaction(moveTransactionBuilder)
Next we need to obtain a signature from the notary for the transaction to be valid. Prior to signing, the notary will Next we need to obtain a signature from the notary for the transaction to be valid. Prior to signing, the notary will
commit our old (input) state so it cannot be used again. commit our old (input) state so it cannot be used again.

View File

@ -4,6 +4,7 @@ import co.paralleluniverse.fibers.Suspendable
import net.corda.contracts.DealState import net.corda.contracts.DealState
import net.corda.core.contracts.requireThat import net.corda.core.contracts.requireThat
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.TransactionSignature
import net.corda.core.flows.CollectSignaturesFlow import net.corda.core.flows.CollectSignaturesFlow
import net.corda.core.flows.FinalityFlow import net.corda.core.flows.FinalityFlow
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
@ -12,11 +13,11 @@ import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.node.services.ServiceType import net.corda.core.node.services.ServiceType
import net.corda.core.utilities.seconds
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.seconds
import net.corda.core.utilities.trace import net.corda.core.utilities.trace
import net.corda.core.utilities.unwrap import net.corda.core.utilities.unwrap
import java.security.PublicKey import java.security.PublicKey
@ -92,8 +93,12 @@ object TwoPartyDealFlow {
val handshake = receiveAndValidateHandshake() val handshake = receiveAndValidateHandshake()
progressTracker.currentStep = SIGNING progressTracker.currentStep = SIGNING
val (utx, additionalSigningPubKeys) = assembleSharedTX(handshake) val (utx, additionalSigningPubKeys, additionalSignatures) = assembleSharedTX(handshake)
val ptx = signWithOurKeys(additionalSigningPubKeys, utx) val ptx = if (additionalSignatures.any()) {
serviceHub.signInitialTransaction(utx, additionalSigningPubKeys).withAdditionalSignatures(additionalSignatures)
} else {
serviceHub.signInitialTransaction(utx, additionalSigningPubKeys)
}
logger.trace { "Signed proposed transaction." } logger.trace { "Signed proposed transaction." }
@ -136,13 +141,8 @@ object TwoPartyDealFlow {
return handshake.unwrap { validateHandshake(it) } return handshake.unwrap { validateHandshake(it) }
} }
private fun signWithOurKeys(signingPubKeys: List<PublicKey>, ptx: TransactionBuilder): SignedTransaction {
// Now sign the transaction with whatever keys we need to move the cash.
return serviceHub.signInitialTransaction(ptx, signingPubKeys)
}
@Suspendable protected abstract fun validateHandshake(handshake: Handshake<U>): Handshake<U> @Suspendable protected abstract fun validateHandshake(handshake: Handshake<U>): Handshake<U>
@Suspendable protected abstract fun assembleSharedTX(handshake: Handshake<U>): Pair<TransactionBuilder, List<PublicKey>> @Suspendable protected abstract fun assembleSharedTX(handshake: Handshake<U>): Triple<TransactionBuilder, List<PublicKey>, List<TransactionSignature>>
} }
@CordaSerializable @CordaSerializable
@ -178,14 +178,14 @@ object TwoPartyDealFlow {
return handshake.copy(payload = autoOffer.copy(dealBeingOffered = deal)) return handshake.copy(payload = autoOffer.copy(dealBeingOffered = deal))
} }
override fun assembleSharedTX(handshake: Handshake<AutoOffer>): Pair<TransactionBuilder, List<PublicKey>> { override fun assembleSharedTX(handshake: Handshake<AutoOffer>): Triple<TransactionBuilder, List<PublicKey>, List<TransactionSignature>> {
val deal = handshake.payload.dealBeingOffered val deal = handshake.payload.dealBeingOffered
val ptx = deal.generateAgreement(handshake.payload.notary) val ptx = deal.generateAgreement(handshake.payload.notary)
// We set the transaction's time-window: it may be that none of the contracts need this! // We set the transaction's time-window: it may be that none of the contracts need this!
// But it can't hurt to have one. // But it can't hurt to have one.
ptx.setTimeWindow(serviceHub.clock.instant(), 30.seconds) ptx.setTimeWindow(serviceHub.clock.instant(), 30.seconds)
return Pair(ptx, arrayListOf(deal.participants.single { it == serviceHub.myInfo.legalIdentity as AbstractParty }.owningKey)) return Triple(ptx, arrayListOf(deal.participants.single { it == serviceHub.myInfo.legalIdentity as AbstractParty }.owningKey), emptyList())
} }
} }
} }

View File

@ -204,6 +204,7 @@ class CommercialPaperTestsGeneric {
private lateinit var alicesVault: Vault<ContractState> private lateinit var alicesVault: Vault<ContractState>
private val notaryServices = MockServices(DUMMY_NOTARY_KEY) private val notaryServices = MockServices(DUMMY_NOTARY_KEY)
private val issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY)
private lateinit var moveTX: SignedTransaction private lateinit var moveTX: SignedTransaction
@ -216,7 +217,7 @@ class CommercialPaperTestsGeneric {
aliceVaultService = aliceServices.vaultService aliceVaultService = aliceServices.vaultService
databaseAlice.transaction { databaseAlice.transaction {
alicesVault = aliceServices.fillWithSomeTestCash(9000.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1) alicesVault = aliceServices.fillWithSomeTestCash(9000.DOLLARS, issuerServices, atLeastThisManyStates = 1, atMostThisManyStates = 1, issuedBy = DUMMY_CASH_ISSUER)
aliceVaultService = aliceServices.vaultService aliceVaultService = aliceServices.vaultService
} }
@ -226,7 +227,7 @@ class CommercialPaperTestsGeneric {
bigCorpVaultService = bigCorpServices.vaultService bigCorpVaultService = bigCorpServices.vaultService
databaseBigCorp.transaction { databaseBigCorp.transaction {
bigCorpVault = bigCorpServices.fillWithSomeTestCash(13000.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1) bigCorpVault = bigCorpServices.fillWithSomeTestCash(13000.DOLLARS, issuerServices, atLeastThisManyStates = 1, atMostThisManyStates = 1, issuedBy = DUMMY_CASH_ISSUER)
bigCorpVaultService = bigCorpServices.vaultService bigCorpVaultService = bigCorpServices.vaultService
} }

View File

@ -6,17 +6,11 @@ import net.corda.core.crypto.generateKeyPair
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.node.services.IdentityService
import net.corda.core.node.services.VaultQueryService
import net.corda.core.node.services.VaultService import net.corda.core.node.services.VaultService
import net.corda.core.node.services.queryBy import net.corda.core.node.services.queryBy
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.transactions.WireTransaction import net.corda.core.transactions.WireTransaction
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.node.services.database.HibernateConfiguration
import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.services.vault.HibernateVaultQueryImpl
import net.corda.node.services.vault.NodeVaultService import net.corda.node.services.vault.NodeVaultService
import net.corda.node.utilities.CordaPersistence import net.corda.node.utilities.CordaPersistence
import net.corda.testing.* import net.corda.testing.*
@ -47,6 +41,7 @@ class CashTests : TestDependencyInjectionBase() {
) )
lateinit var miniCorpServices: MockServices lateinit var miniCorpServices: MockServices
lateinit var megaCorpServices: MockServices
val vault: VaultService get() = miniCorpServices.vaultService val vault: VaultService get() = miniCorpServices.vaultService
lateinit var database: CordaPersistence lateinit var database: CordaPersistence
lateinit var vaultStatesUnconsumed: List<StateAndRef<Cash.State>> lateinit var vaultStatesUnconsumed: List<StateAndRef<Cash.State>>
@ -54,19 +49,20 @@ class CashTests : TestDependencyInjectionBase() {
@Before @Before
fun setUp() { fun setUp() {
LogHelper.setLevel(NodeVaultService::class) LogHelper.setLevel(NodeVaultService::class)
megaCorpServices = MockServices(MEGA_CORP_KEY)
val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(MINI_CORP_KEY, MEGA_CORP_KEY, OUR_KEY)) val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(MINI_CORP_KEY, MEGA_CORP_KEY, OUR_KEY))
database = databaseAndServices.first database = databaseAndServices.first
miniCorpServices = databaseAndServices.second miniCorpServices = databaseAndServices.second
database.transaction { database.transaction {
miniCorpServices.fillWithSomeTestCash(howMuch = 100.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1, miniCorpServices.fillWithSomeTestCash(howMuch = 100.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1,
issuedBy = MEGA_CORP.ref(1), issuerKey = MEGA_CORP_KEY, ownedBy = OUR_IDENTITY_1) ownedBy = OUR_IDENTITY_1, issuedBy = MEGA_CORP.ref(1), issuerServices = megaCorpServices)
miniCorpServices.fillWithSomeTestCash(howMuch = 400.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1, miniCorpServices.fillWithSomeTestCash(howMuch = 400.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1,
issuedBy = MEGA_CORP.ref(1), issuerKey = MEGA_CORP_KEY, ownedBy = OUR_IDENTITY_1) ownedBy = OUR_IDENTITY_1, issuedBy = MEGA_CORP.ref(1), issuerServices = megaCorpServices)
miniCorpServices.fillWithSomeTestCash(howMuch = 80.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1, miniCorpServices.fillWithSomeTestCash(howMuch = 80.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1,
issuedBy = MINI_CORP.ref(1), issuerKey = MINI_CORP_KEY, ownedBy = OUR_IDENTITY_1) ownedBy = OUR_IDENTITY_1, issuedBy = MINI_CORP.ref(1), issuerServices = miniCorpServices)
miniCorpServices.fillWithSomeTestCash(howMuch = 80.SWISS_FRANCS, atLeastThisManyStates = 1, atMostThisManyStates = 1, miniCorpServices.fillWithSomeTestCash(howMuch = 80.SWISS_FRANCS, atLeastThisManyStates = 1, atMostThisManyStates = 1,
issuedBy = MINI_CORP.ref(1), issuerKey = MINI_CORP_KEY, ownedBy = OUR_IDENTITY_1) ownedBy = OUR_IDENTITY_1, issuedBy = MINI_CORP.ref(1), issuerServices = miniCorpServices)
vaultStatesUnconsumed = miniCorpServices.vaultQueryService.queryBy<Cash.State>().states vaultStatesUnconsumed = miniCorpServices.vaultQueryService.queryBy<Cash.State>().states
} }

View File

@ -17,8 +17,8 @@ import net.corda.core.node.services.vault.QueryCriteria.LinearStateQueryCriteria
import net.corda.core.node.services.vault.QueryCriteria.VaultCustomQueryCriteria; import net.corda.core.node.services.vault.QueryCriteria.VaultCustomQueryCriteria;
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria; import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria;
import net.corda.core.utilities.OpaqueBytes; import net.corda.core.utilities.OpaqueBytes;
import net.corda.node.services.identity.InMemoryIdentityService;
import net.corda.node.utilities.CordaPersistence; import net.corda.node.utilities.CordaPersistence;
import net.corda.node.services.identity.*;
import net.corda.schemas.CashSchemaV1; import net.corda.schemas.CashSchemaV1;
import net.corda.testing.TestConstants; import net.corda.testing.TestConstants;
import net.corda.testing.TestDependencyInjectionBase; import net.corda.testing.TestDependencyInjectionBase;
@ -44,13 +44,14 @@ import static net.corda.core.node.services.vault.QueryCriteriaUtils.DEFAULT_PAGE
import static net.corda.core.node.services.vault.QueryCriteriaUtils.MAX_PAGE_SIZE; import static net.corda.core.node.services.vault.QueryCriteriaUtils.MAX_PAGE_SIZE;
import static net.corda.core.utilities.ByteArrays.toHexString; import static net.corda.core.utilities.ByteArrays.toHexString;
import static net.corda.testing.CoreTestUtils.*; import static net.corda.testing.CoreTestUtils.*;
import static net.corda.testing.node.MockServicesKt.makeTestDatabaseAndMockServices;
import static net.corda.testing.TestConstants.*; import static net.corda.testing.TestConstants.*;
import static net.corda.testing.node.MockServicesKt.makeTestDatabaseAndMockServices;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
public class VaultQueryJavaTests extends TestDependencyInjectionBase { public class VaultQueryJavaTests extends TestDependencyInjectionBase {
private MockServices services; private MockServices services;
private MockServices issuerServices;
private VaultService vaultSvc; private VaultService vaultSvc;
private VaultQueryService vaultQuerySvc; private VaultQueryService vaultQuerySvc;
private CordaPersistence database; private CordaPersistence database;
@ -59,8 +60,10 @@ public class VaultQueryJavaTests extends TestDependencyInjectionBase {
public void setUp() { public void setUp() {
ArrayList<KeyPair> keys = new ArrayList<>(); ArrayList<KeyPair> keys = new ArrayList<>();
keys.add(getMEGA_CORP_KEY()); keys.add(getMEGA_CORP_KEY());
keys.add(getDUMMY_NOTARY_KEY());
InMemoryIdentityService identityService = new InMemoryIdentityService(getMOCK_IDENTITIES(), Collections.emptyMap(), getDUMMY_CA().getCertificate()); InMemoryIdentityService identityService = new InMemoryIdentityService(getMOCK_IDENTITIES(), Collections.emptyMap(), getDUMMY_CA().getCertificate());
Pair<CordaPersistence, MockServices> databaseAndServices = makeTestDatabaseAndMockServices(Collections.EMPTY_SET, keys); Pair<CordaPersistence, MockServices> databaseAndServices = makeTestDatabaseAndMockServices(Collections.EMPTY_SET, keys);
issuerServices = new MockServices(getDUMMY_CASH_ISSUER_KEY(), getBOC_KEY());
database = databaseAndServices.getFirst(); database = databaseAndServices.getFirst();
services = databaseAndServices.getSecond(); services = databaseAndServices.getSecond();
vaultSvc = services.getVaultService(); vaultSvc = services.getVaultService();
@ -129,16 +132,16 @@ public class VaultQueryJavaTests extends TestDependencyInjectionBase {
VaultFiller.fillWithSomeTestCash(services, VaultFiller.fillWithSomeTestCash(services,
new Amount<>(100, Currency.getInstance("USD")), new Amount<>(100, Currency.getInstance("USD")),
issuerServices,
TestConstants.getDUMMY_NOTARY(), TestConstants.getDUMMY_NOTARY(),
3, 3,
3, 3,
new Random(), new Random(),
new OpaqueBytes("1".getBytes()), new OpaqueBytes("1".getBytes()),
null, null,
getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER());
getDUMMY_CASH_ISSUER_KEY() );
VaultFiller.consumeCash(services, amount); VaultFiller.consumeCash(services, amount, getDUMMY_NOTARY());
// DOCSTART VaultJavaQueryExample1 // DOCSTART VaultJavaQueryExample1
VaultQueryCriteria criteria = new VaultQueryCriteria(Vault.StateStatus.CONSUMED); VaultQueryCriteria criteria = new VaultQueryCriteria(Vault.StateStatus.CONSUMED);
@ -163,8 +166,8 @@ public class VaultQueryJavaTests extends TestDependencyInjectionBase {
Vault<DealState> dealStates = VaultFiller.fillWithSomeTestDeals(services, dealIds); Vault<DealState> dealStates = VaultFiller.fillWithSomeTestDeals(services, dealIds);
// consume states // consume states
VaultFiller.consumeDeals(services, (List<? extends StateAndRef<? extends DealState>>) dealStates.getStates()); VaultFiller.consumeDeals(services, (List<? extends StateAndRef<? extends DealState>>) dealStates.getStates(), getDUMMY_NOTARY());
VaultFiller.consumeLinearStates(services, Collections.singletonList(linearState)); VaultFiller.consumeLinearStates(services, Collections.singletonList(linearState), getDUMMY_NOTARY());
// DOCSTART VaultJavaQueryExample2 // DOCSTART VaultJavaQueryExample2
Vault.StateStatus status = Vault.StateStatus.CONSUMED; Vault.StateStatus status = Vault.StateStatus.CONSUMED;
@ -202,10 +205,10 @@ public class VaultQueryJavaTests extends TestDependencyInjectionBase {
Amount<Currency> dollars10 = new Amount<>(10, Currency.getInstance("USD")); Amount<Currency> dollars10 = new Amount<>(10, Currency.getInstance("USD"));
Amount<Currency> dollars1 = new Amount<>(1, Currency.getInstance("USD")); Amount<Currency> dollars1 = new Amount<>(1, Currency.getInstance("USD"));
VaultFiller.fillWithSomeTestCash(services, pounds, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, pounds, issuerServices, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, dollars100, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, dollars100, issuerServices, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, dollars10, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, dollars10, issuerServices, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, dollars1, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, dollars1, issuerServices, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
try { try {
// DOCSTART VaultJavaQueryExample3 // DOCSTART VaultJavaQueryExample3
@ -242,14 +245,14 @@ public class VaultQueryJavaTests extends TestDependencyInjectionBase {
database.transaction(tx -> { database.transaction(tx -> {
VaultFiller.fillWithSomeTestCash(services, VaultFiller.fillWithSomeTestCash(services,
new Amount<>(100, Currency.getInstance("USD")), new Amount<>(100, Currency.getInstance("USD")),
issuerServices,
TestConstants.getDUMMY_NOTARY(), TestConstants.getDUMMY_NOTARY(),
3, 3,
3, 3,
new Random(), new Random(),
new OpaqueBytes("1".getBytes()), new OpaqueBytes("1".getBytes()),
null, null,
getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER());
getDUMMY_CASH_ISSUER_KEY() );
// DOCSTART VaultJavaQueryExample4 // DOCSTART VaultJavaQueryExample4
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -320,11 +323,11 @@ public class VaultQueryJavaTests extends TestDependencyInjectionBase {
Amount<Currency> pounds = new Amount<>(400, Currency.getInstance("GBP")); Amount<Currency> pounds = new Amount<>(400, Currency.getInstance("GBP"));
Amount<Currency> swissfrancs = new Amount<>(500, Currency.getInstance("CHF")); Amount<Currency> swissfrancs = new Amount<>(500, Currency.getInstance("CHF"));
VaultFiller.fillWithSomeTestCash(services, dollars100, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, dollars100, issuerServices, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, dollars200, TestConstants.getDUMMY_NOTARY(), 2, 2, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, dollars200, issuerServices, TestConstants.getDUMMY_NOTARY(), 2, 2, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, dollars300, TestConstants.getDUMMY_NOTARY(), 3, 3, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, dollars300, issuerServices, TestConstants.getDUMMY_NOTARY(), 3, 3, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, pounds, TestConstants.getDUMMY_NOTARY(), 4, 4, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, pounds, issuerServices, TestConstants.getDUMMY_NOTARY(), 4, 4, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, swissfrancs, TestConstants.getDUMMY_NOTARY(), 5, 5, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, swissfrancs, issuerServices, TestConstants.getDUMMY_NOTARY(), 5, 5, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
try { try {
// DOCSTART VaultJavaQueryExample21 // DOCSTART VaultJavaQueryExample21
@ -365,11 +368,11 @@ public class VaultQueryJavaTests extends TestDependencyInjectionBase {
Amount<Currency> pounds = new Amount<>(400, Currency.getInstance("GBP")); Amount<Currency> pounds = new Amount<>(400, Currency.getInstance("GBP"));
Amount<Currency> swissfrancs = new Amount<>(500, Currency.getInstance("CHF")); Amount<Currency> swissfrancs = new Amount<>(500, Currency.getInstance("CHF"));
VaultFiller.fillWithSomeTestCash(services, dollars100, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, dollars100, issuerServices, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, dollars200, TestConstants.getDUMMY_NOTARY(), 2, 2, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, dollars200, issuerServices, TestConstants.getDUMMY_NOTARY(), 2, 2, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, dollars300, TestConstants.getDUMMY_NOTARY(), 3, 3, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, dollars300, issuerServices, TestConstants.getDUMMY_NOTARY(), 3, 3, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, pounds, TestConstants.getDUMMY_NOTARY(), 4, 4, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, pounds, issuerServices, TestConstants.getDUMMY_NOTARY(), 4, 4, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, swissfrancs, TestConstants.getDUMMY_NOTARY(), 5, 5, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, swissfrancs, issuerServices, TestConstants.getDUMMY_NOTARY(), 5, 5, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
try { try {
// DOCSTART VaultJavaQueryExample22 // DOCSTART VaultJavaQueryExample22
@ -435,10 +438,10 @@ public class VaultQueryJavaTests extends TestDependencyInjectionBase {
Amount<Currency> pounds300 = new Amount<>(300, Currency.getInstance("GBP")); Amount<Currency> pounds300 = new Amount<>(300, Currency.getInstance("GBP"));
Amount<Currency> pounds400 = new Amount<>(400, Currency.getInstance("GBP")); Amount<Currency> pounds400 = new Amount<>(400, Currency.getInstance("GBP"));
VaultFiller.fillWithSomeTestCash(services, dollars100, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, dollars100, issuerServices, TestConstants.getDUMMY_NOTARY(), 1, 1, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, dollars200, TestConstants.getDUMMY_NOTARY(), 2, 2, new Random(0L), new OpaqueBytes("1".getBytes()), null, getBOC().ref(new OpaqueBytes("1".getBytes())), getBOC_KEY()); VaultFiller.fillWithSomeTestCash(services, dollars200, issuerServices, TestConstants.getDUMMY_NOTARY(), 2, 2, new Random(0L), new OpaqueBytes("1".getBytes()), null, getBOC().ref(new OpaqueBytes("1".getBytes())));
VaultFiller.fillWithSomeTestCash(services, pounds300, TestConstants.getDUMMY_NOTARY(), 3, 3, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER(), getDUMMY_CASH_ISSUER_KEY()); VaultFiller.fillWithSomeTestCash(services, pounds300, issuerServices, TestConstants.getDUMMY_NOTARY(), 3, 3, new Random(0L), new OpaqueBytes("1".getBytes()), null, getDUMMY_CASH_ISSUER());
VaultFiller.fillWithSomeTestCash(services, pounds400, TestConstants.getDUMMY_NOTARY(), 4, 4, new Random(0L), new OpaqueBytes("1".getBytes()), null, getBOC().ref(new OpaqueBytes("1".getBytes())), getBOC_KEY()); VaultFiller.fillWithSomeTestCash(services, pounds400, issuerServices, TestConstants.getDUMMY_NOTARY(), 4, 4, new Random(0L), new OpaqueBytes("1".getBytes()), null, getBOC().ref(new OpaqueBytes("1".getBytes())));
try { try {
// DOCSTART VaultJavaQueryExample23 // DOCSTART VaultJavaQueryExample23

View File

@ -96,17 +96,19 @@ class TwoPartyTradeFlowTests {
val aliceNode = basketOfNodes.partyNodes[0] val aliceNode = basketOfNodes.partyNodes[0]
val bobNode = basketOfNodes.partyNodes[1] val bobNode = basketOfNodes.partyNodes[1]
val bankNode = basketOfNodes.partyNodes[2] val bankNode = basketOfNodes.partyNodes[2]
val issuer = bankNode.info.legalIdentity.ref(1, 2, 3) val cashIssuer = bankNode.info.legalIdentity.ref(1)
val cpIssuer = bankNode.info.legalIdentity.ref(1, 2, 3)
aliceNode.disableDBCloseOnStop() aliceNode.disableDBCloseOnStop()
bobNode.disableDBCloseOnStop() bobNode.disableDBCloseOnStop()
bobNode.database.transaction { bobNode.database.transaction {
bobNode.services.fillWithSomeTestCash(2000.DOLLARS, outputNotary = notaryNode.info.notaryIdentity) bobNode.services.fillWithSomeTestCash(2000.DOLLARS, bankNode.services, outputNotary = notaryNode.info.notaryIdentity,
issuedBy = cashIssuer)
} }
val alicesFakePaper = aliceNode.database.transaction { val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity, fillUpForSeller(false, cpIssuer, aliceNode.info.legalIdentity,
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), null, notaryNode.info.notaryIdentity).second 1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), null, notaryNode.info.notaryIdentity).second
} }
@ -142,13 +144,15 @@ class TwoPartyTradeFlowTests {
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name) val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
val cashIssuer = bankNode.info.legalIdentity.ref(1)
val cpIssuer = bankNode.info.legalIdentity.ref(1, 2, 3) val cpIssuer = bankNode.info.legalIdentity.ref(1, 2, 3)
aliceNode.disableDBCloseOnStop() aliceNode.disableDBCloseOnStop()
bobNode.disableDBCloseOnStop() bobNode.disableDBCloseOnStop()
val cashStates = bobNode.database.transaction { val cashStates = bobNode.database.transaction {
bobNode.services.fillWithSomeTestCash(2000.DOLLARS, notaryNode.info.notaryIdentity, 3, 3) bobNode.services.fillWithSomeTestCash(2000.DOLLARS, bankNode.services, notaryNode.info.notaryIdentity, 3, 3,
issuedBy = cashIssuer)
} }
val alicesFakePaper = aliceNode.database.transaction { val alicesFakePaper = aliceNode.database.transaction {
@ -194,6 +198,7 @@ class TwoPartyTradeFlowTests {
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name) val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
val cashIssuer = bankNode.info.legalIdentity.ref(1)
val cpIssuer = bankNode.info.legalIdentity.ref(1, 2, 3) val cpIssuer = bankNode.info.legalIdentity.ref(1, 2, 3)
aliceNode.services.identityService.registerIdentity(bobNode.info.legalIdentityAndCert) aliceNode.services.identityService.registerIdentity(bobNode.info.legalIdentityAndCert)
@ -207,7 +212,8 @@ class TwoPartyTradeFlowTests {
mockNet.runNetwork() // Clear network map registration messages mockNet.runNetwork() // Clear network map registration messages
bobNode.database.transaction { bobNode.database.transaction {
bobNode.services.fillWithSomeTestCash(2000.DOLLARS, outputNotary = notaryNode.info.notaryIdentity) bobNode.services.fillWithSomeTestCash(2000.DOLLARS, bankNode.services, outputNotary = notaryNode.info.notaryIdentity,
issuedBy = cashIssuer)
} }
val alicesFakePaper = aliceNode.database.transaction { val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, cpIssuer, aliceNode.info.legalIdentity, fillUpForSeller(false, cpIssuer, aliceNode.info.legalIdentity,

View File

@ -1,14 +1,10 @@
package net.corda.node.services.database package net.corda.node.services.database
import net.corda.contracts.asset.Cash import net.corda.contracts.asset.*
import net.corda.contracts.asset.DUMMY_CASH_ISSUER
import net.corda.contracts.asset.DummyFungibleContract
import net.corda.contracts.asset.sumCash
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.toBase58String import net.corda.core.crypto.toBase58String
import net.corda.core.node.services.Vault import net.corda.core.node.services.Vault
import net.corda.core.node.services.VaultQueryService
import net.corda.core.node.services.VaultService import net.corda.core.node.services.VaultService
import net.corda.core.schemas.CommonSchemaV1 import net.corda.core.schemas.CommonSchemaV1
import net.corda.core.schemas.PersistentStateRef import net.corda.core.schemas.PersistentStateRef
@ -17,8 +13,6 @@ import net.corda.core.transactions.SignedTransaction
import net.corda.node.services.identity.InMemoryIdentityService import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.node.services.schema.HibernateObserver import net.corda.node.services.schema.HibernateObserver
import net.corda.node.services.schema.NodeSchemaService import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.services.vault.HibernateVaultQueryImpl
import net.corda.node.services.vault.NodeVaultService
import net.corda.node.services.vault.VaultSchemaV1 import net.corda.node.services.vault.VaultSchemaV1
import net.corda.node.utilities.CordaPersistence import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.configureDatabase import net.corda.node.utilities.configureDatabase
@ -52,6 +46,7 @@ import javax.persistence.criteria.CriteriaBuilder
class HibernateConfigurationTest : TestDependencyInjectionBase() { class HibernateConfigurationTest : TestDependencyInjectionBase() {
lateinit var services: MockServices lateinit var services: MockServices
lateinit var issuerServices: MockServices
lateinit var database: CordaPersistence lateinit var database: CordaPersistence
val vault: VaultService get() = services.vaultService val vault: VaultService get() = services.vaultService
@ -67,6 +62,7 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
@Before @Before
fun setUp() { fun setUp() {
issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY, BOB_KEY, BOC_KEY)
val dataSourceProps = makeTestDataSourceProperties() val dataSourceProps = makeTestDataSourceProperties()
val defaultDatabaseProperties = makeTestDatabaseProperties() val defaultDatabaseProperties = makeTestDatabaseProperties()
database = configureDatabase(dataSourceProps, defaultDatabaseProperties) database = configureDatabase(dataSourceProps, defaultDatabaseProperties)
@ -74,7 +70,7 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
database.transaction { database.transaction {
val identityService = InMemoryIdentityService(MOCK_IDENTITIES, trustRoot = DUMMY_CA.certificate) val identityService = InMemoryIdentityService(MOCK_IDENTITIES, trustRoot = DUMMY_CA.certificate)
hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), makeTestDatabaseProperties(), identityService) hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), makeTestDatabaseProperties(), identityService)
services = object : MockServices(BOB_KEY) { services = object : MockServices(BOB_KEY, BOC_KEY, DUMMY_NOTARY_KEY) {
override val vaultService: VaultService = makeVaultService(dataSourceProps, hibernateConfig) override val vaultService: VaultService = makeVaultService(dataSourceProps, hibernateConfig)
override fun recordTransactions(txs: Iterable<SignedTransaction>) { override fun recordTransactions(txs: Iterable<SignedTransaction>) {
@ -102,7 +98,7 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
private fun setUpDb() { private fun setUpDb() {
database.transaction { database.transaction {
cashStates = services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 10, 10, Random(0L)).states.toList() cashStates = services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 10, 10, Random(0L)).states.toList()
} }
} }
@ -121,7 +117,7 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
@Test @Test
fun `consumed states`() { fun `consumed states`() {
database.transaction { database.transaction {
services.consumeCash(50.DOLLARS) services.consumeCash(50.DOLLARS, notary = DUMMY_NOTARY)
} }
// structure query // structure query
@ -200,11 +196,11 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
fun `with sorting by state ref desc and asc`() { fun `with sorting by state ref desc and asc`() {
// generate additional state ref indexes // generate additional state ref indexes
database.transaction { database.transaction {
services.consumeCash(1.DOLLARS) services.consumeCash(1.DOLLARS, notary = DUMMY_NOTARY)
services.consumeCash(2.DOLLARS) services.consumeCash(2.DOLLARS, notary = DUMMY_NOTARY)
services.consumeCash(3.DOLLARS) services.consumeCash(3.DOLLARS, notary = DUMMY_NOTARY)
services.consumeCash(4.DOLLARS) services.consumeCash(4.DOLLARS, notary = DUMMY_NOTARY)
services.consumeCash(5.DOLLARS) services.consumeCash(5.DOLLARS, notary = DUMMY_NOTARY)
} }
// structure query // structure query
@ -230,11 +226,11 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
fun `with sorting by state ref index and txId desc and asc`() { fun `with sorting by state ref index and txId desc and asc`() {
// generate additional state ref indexes // generate additional state ref indexes
database.transaction { database.transaction {
services.consumeCash(1.DOLLARS) services.consumeCash(1.DOLLARS, notary = DUMMY_NOTARY)
services.consumeCash(2.DOLLARS) services.consumeCash(2.DOLLARS, notary = DUMMY_NOTARY)
services.consumeCash(3.DOLLARS) services.consumeCash(3.DOLLARS, notary = DUMMY_NOTARY)
services.consumeCash(4.DOLLARS) services.consumeCash(4.DOLLARS, notary = DUMMY_NOTARY)
services.consumeCash(5.DOLLARS) services.consumeCash(5.DOLLARS, notary = DUMMY_NOTARY)
} }
// structure query // structure query
@ -261,7 +257,7 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
fun `with pagination`() { fun `with pagination`() {
// add 100 additional cash entries // add 100 additional cash entries
database.transaction { database.transaction {
services.fillWithSomeTestCash(1000.POUNDS, DUMMY_NOTARY, 100, 100, Random(0L)) services.fillWithSomeTestCash(1000.POUNDS, issuerServices, DUMMY_NOTARY, 100, 100, Random(0L), issuedBy = DUMMY_CASH_ISSUER)
} }
// structure query // structure query
@ -363,11 +359,11 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
fun `calculate cash balances`() { fun `calculate cash balances`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 10, 10, Random(0L)) // +$100 = $200 services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 10, 10, Random(0L)) // +$100 = $200
services.fillWithSomeTestCash(50.POUNDS, DUMMY_NOTARY, 5, 5, Random(0L)) // £50 = £50 services.fillWithSomeTestCash(50.POUNDS, issuerServices, DUMMY_NOTARY, 5, 5, Random(0L)) // £50 = £50
services.fillWithSomeTestCash(25.POUNDS, DUMMY_NOTARY, 5, 5, Random(0L)) // +£25 = £175 services.fillWithSomeTestCash(25.POUNDS, issuerServices, DUMMY_NOTARY, 5, 5, Random(0L)) // +£25 = £175
services.fillWithSomeTestCash(500.SWISS_FRANCS, DUMMY_NOTARY, 10, 10, Random(0L)) // CHF500 = CHF500 services.fillWithSomeTestCash(500.SWISS_FRANCS, issuerServices, DUMMY_NOTARY, 10, 10, Random(0L)) // CHF500 = CHF500
services.fillWithSomeTestCash(250.SWISS_FRANCS, DUMMY_NOTARY, 5, 5, Random(0L)) // +CHF250 = CHF750 services.fillWithSomeTestCash(250.SWISS_FRANCS, issuerServices, DUMMY_NOTARY, 5, 5, Random(0L)) // +CHF250 = CHF750
} }
// structure query // structure query
@ -396,8 +392,8 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
@Test @Test
fun `calculate cash balance for single currency`() { fun `calculate cash balance for single currency`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(50.POUNDS, DUMMY_NOTARY, 5, 5, Random(0L)) // £50 = £50 services.fillWithSomeTestCash(50.POUNDS, issuerServices, DUMMY_NOTARY, 5, 5, Random(0L)) // £50 = £50
services.fillWithSomeTestCash(25.POUNDS, DUMMY_NOTARY, 5, 5, Random(0L)) // +£25 = £175 services.fillWithSomeTestCash(25.POUNDS, issuerServices, DUMMY_NOTARY, 5, 5, Random(0L)) // +£25 = £175
} }
// structure query // structure query
@ -427,9 +423,9 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
fun `calculate and order by cash balance for owner and currency`() { fun `calculate and order by cash balance for owner and currency`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(200.DOLLARS, DUMMY_NOTARY, 2, 2, Random(0L), issuedBy = BOC.ref(1), issuerKey = BOC_KEY) services.fillWithSomeTestCash(200.DOLLARS, issuerServices, DUMMY_NOTARY, 2, 2, Random(0L), issuedBy = BOC.ref(1))
services.fillWithSomeTestCash(300.POUNDS, DUMMY_NOTARY, 3, 3, Random(0L), issuedBy = DUMMY_CASH_ISSUER) services.fillWithSomeTestCash(300.POUNDS, issuerServices, DUMMY_NOTARY, 3, 3, Random(0L), issuedBy = DUMMY_CASH_ISSUER)
services.fillWithSomeTestCash(400.POUNDS, DUMMY_NOTARY, 4, 4, Random(0L), issuedBy = BOC.ref(2), issuerKey = BOC_KEY) services.fillWithSomeTestCash(400.POUNDS, issuerServices, DUMMY_NOTARY, 4, 4, Random(0L), issuedBy = BOC.ref(2))
} }
// structure query // structure query
@ -618,9 +614,9 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
hibernatePersister.persistStateWithSchema(dummyFungibleState, it.ref, SampleCashSchemaV3) hibernatePersister.persistStateWithSchema(dummyFungibleState, it.ref, SampleCashSchemaV3)
} }
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 2, 2, Random(0L), ownedBy = ALICE) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 2, 2, Random(0L), ownedBy = ALICE)
val cashStates = services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 2, 2, Random(0L), val cashStates = services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 2, 2, Random(0L),
issuedBy = BOB.ref(0), issuerKey = BOB_KEY, ownedBy = (BOB)).states issuedBy = BOB.ref(0), ownedBy = (BOB)).states
// persist additional cash states explicitly with V3 schema // persist additional cash states explicitly with V3 schema
cashStates.forEach { cashStates.forEach {
val cashState = it.state.data val cashState = it.state.data
@ -699,8 +695,8 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
hibernatePersister.persistStateWithSchema(dummyFungibleState, it.ref, SampleCashSchemaV3) hibernatePersister.persistStateWithSchema(dummyFungibleState, it.ref, SampleCashSchemaV3)
} }
val moreCash = services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 2, 2, Random(0L), val moreCash = services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 2, 2, Random(0L),
issuedBy = BOB.ref(0), issuerKey = BOB_KEY, ownedBy = BOB).states issuedBy = BOB.ref(0), ownedBy = BOB).states
// persist additional cash states explicitly with V3 schema // persist additional cash states explicitly with V3 schema
moreCash.forEach { moreCash.forEach {
val cashState = it.state.data val cashState = it.state.data
@ -708,7 +704,7 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
hibernatePersister.persistStateWithSchema(dummyFungibleState, it.ref, SampleCashSchemaV3) hibernatePersister.persistStateWithSchema(dummyFungibleState, it.ref, SampleCashSchemaV3)
} }
val cashStates = services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 2, 2, Random(0L), ownedBy = (ALICE)).states val cashStates = services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 2, 2, Random(0L), ownedBy = (ALICE)).states
// persist additional cash states explicitly with V3 schema // persist additional cash states explicitly with V3 schema
cashStates.forEach { cashStates.forEach {
val cashState = it.state.data val cashState = it.state.data

View File

@ -3,6 +3,7 @@ package net.corda.node.services.vault
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import net.corda.contracts.asset.Cash import net.corda.contracts.asset.Cash
import net.corda.contracts.asset.DUMMY_CASH_ISSUER import net.corda.contracts.asset.DUMMY_CASH_ISSUER
import net.corda.contracts.asset.DUMMY_CASH_ISSUER_KEY
import net.corda.contracts.asset.sumCash import net.corda.contracts.asset.sumCash
import net.corda.contracts.getCashBalance import net.corda.contracts.getCashBalance
import net.corda.core.contracts.* import net.corda.core.contracts.*
@ -10,11 +11,7 @@ import net.corda.core.crypto.generateKeyPair
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.node.services.StatesNotAvailableException import net.corda.core.node.services.*
import net.corda.core.node.services.Vault
import net.corda.core.node.services.VaultQueryService
import net.corda.core.node.services.VaultService
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.QueryCriteria import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.node.services.vault.QueryCriteria.* import net.corda.core.node.services.vault.QueryCriteria.*
import net.corda.core.transactions.NotaryChangeWireTransaction import net.corda.core.transactions.NotaryChangeWireTransaction
@ -23,9 +20,6 @@ import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.NonEmptySet import net.corda.core.utilities.NonEmptySet
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.toNonEmptySet import net.corda.core.utilities.toNonEmptySet
import net.corda.node.services.database.HibernateConfiguration
import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.utilities.CordaPersistence import net.corda.node.utilities.CordaPersistence
import net.corda.testing.* import net.corda.testing.*
import net.corda.testing.contracts.fillWithSomeTestCash import net.corda.testing.contracts.fillWithSomeTestCash
@ -47,6 +41,7 @@ import kotlin.test.assertTrue
class NodeVaultServiceTest : TestDependencyInjectionBase() { class NodeVaultServiceTest : TestDependencyInjectionBase() {
lateinit var services: MockServices lateinit var services: MockServices
lateinit var issuerServices: MockServices
val vaultSvc: VaultService get() = services.vaultService val vaultSvc: VaultService get() = services.vaultService
val vaultQuery: VaultQueryService get() = services.vaultQueryService val vaultQuery: VaultQueryService get() = services.vaultQueryService
lateinit var database: CordaPersistence lateinit var database: CordaPersistence
@ -54,9 +49,10 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
@Before @Before
fun setUp() { fun setUp() {
LogHelper.setLevel(NodeVaultService::class) LogHelper.setLevel(NodeVaultService::class)
val databaseAndServices = makeTestDatabaseAndMockServices() val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(BOC_KEY, DUMMY_CASH_ISSUER_KEY))
database = databaseAndServices.first database = databaseAndServices.first
services = databaseAndServices.second services = databaseAndServices.second
issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY, BOC_KEY)
} }
@After @After
@ -88,7 +84,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `states not local to instance`() { fun `states not local to instance`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 3, 3, Random(0L))
val w1 = vaultQuery.queryBy<Cash.State>().states val w1 = vaultQuery.queryBy<Cash.State>().states
assertThat(w1).hasSize(3) assertThat(w1).hasSize(3)
@ -115,7 +111,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `states for refs`() { fun `states for refs`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 3, 3, Random(0L))
val w1 = vaultQuery.queryBy<Cash.State>().states val w1 = vaultQuery.queryBy<Cash.State>().states
assertThat(w1).hasSize(3) assertThat(w1).hasSize(3)
@ -129,7 +125,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `states soft locking reserve and release`() { fun `states soft locking reserve and release`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 3, 3, Random(0L))
val unconsumedStates = vaultQuery.queryBy<Cash.State>().states val unconsumedStates = vaultQuery.queryBy<Cash.State>().states
assertThat(unconsumedStates).hasSize(3) assertThat(unconsumedStates).hasSize(3)
@ -180,7 +176,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val vaultStates = val vaultStates =
database.transaction { database.transaction {
assertEquals(0.DOLLARS, services.getCashBalance(USD)) assertEquals(0.DOLLARS, services.getCashBalance(USD))
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 3, 3, Random(0L))
} }
val stateRefsToSoftLock = (vaultStates.states.map { it.ref }).toNonEmptySet() val stateRefsToSoftLock = (vaultStates.states.map { it.ref }).toNonEmptySet()
println("State Refs:: $stateRefsToSoftLock") println("State Refs:: $stateRefsToSoftLock")
@ -235,7 +231,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val vaultStates = val vaultStates =
database.transaction { database.transaction {
assertEquals(0.DOLLARS, services.getCashBalance(USD)) assertEquals(0.DOLLARS, services.getCashBalance(USD))
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 3, 3, Random(0L))
} }
val stateRefsToSoftLock = vaultStates.states.map { it.ref } val stateRefsToSoftLock = vaultStates.states.map { it.ref }
println("State Refs:: $stateRefsToSoftLock") println("State Refs:: $stateRefsToSoftLock")
@ -263,7 +259,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val vaultStates = val vaultStates =
database.transaction { database.transaction {
assertEquals(0.DOLLARS, services.getCashBalance(USD)) assertEquals(0.DOLLARS, services.getCashBalance(USD))
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 3, 3, Random(0L))
} }
val stateRefsToSoftLock = (vaultStates.states.map { it.ref }).toNonEmptySet() val stateRefsToSoftLock = (vaultStates.states.map { it.ref }).toNonEmptySet()
println("State Refs:: $stateRefsToSoftLock") println("State Refs:: $stateRefsToSoftLock")
@ -290,7 +286,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val vaultStates = val vaultStates =
database.transaction { database.transaction {
assertEquals(0.DOLLARS, services.getCashBalance(USD)) assertEquals(0.DOLLARS, services.getCashBalance(USD))
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 3, 3, Random(0L))
} }
val stateRefsToSoftLock = vaultStates.states.map { it.ref } val stateRefsToSoftLock = vaultStates.states.map { it.ref }
println("State Refs:: $stateRefsToSoftLock") println("State Refs:: $stateRefsToSoftLock")
@ -312,7 +308,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `unconsumedStatesForSpending exact amount`() { fun `unconsumedStatesForSpending exact amount`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L))
val unconsumedStates = vaultQuery.queryBy<Cash.State>().states val unconsumedStates = vaultQuery.queryBy<Cash.State>().states
assertThat(unconsumedStates).hasSize(1) assertThat(unconsumedStates).hasSize(1)
@ -330,8 +326,8 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `unconsumedStatesForSpending from two issuer parties`() { fun `unconsumedStatesForSpending from two issuer parties`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (DUMMY_CASH_ISSUER)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (DUMMY_CASH_ISSUER))
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(1)), issuerKey = BOC_KEY) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(1)))
val spendableStatesUSD = vaultSvc.unconsumedCashStatesForSpending(200.DOLLARS, val spendableStatesUSD = vaultSvc.unconsumedCashStatesForSpending(200.DOLLARS,
onlyFromIssuerParties = setOf(DUMMY_CASH_ISSUER.party, BOC)) onlyFromIssuerParties = setOf(DUMMY_CASH_ISSUER.party, BOC))
@ -347,10 +343,10 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `unconsumedStatesForSpending from specific issuer party and refs`() { fun `unconsumedStatesForSpending from specific issuer party and refs`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (DUMMY_CASH_ISSUER)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (DUMMY_CASH_ISSUER))
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(1)), issuerKey = BOC_KEY, ref = OpaqueBytes.of(1)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(1)), ref = OpaqueBytes.of(1))
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(2)), issuerKey = BOC_KEY, ref = OpaqueBytes.of(2)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(2)), ref = OpaqueBytes.of(2))
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(3)), issuerKey = BOC_KEY, ref = OpaqueBytes.of(3)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(3)), ref = OpaqueBytes.of(3))
val unconsumedStates = vaultQuery.queryBy<Cash.State>().states val unconsumedStates = vaultQuery.queryBy<Cash.State>().states
assertThat(unconsumedStates).hasSize(4) assertThat(unconsumedStates).hasSize(4)
@ -369,7 +365,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `unconsumedStatesForSpending insufficient amount`() { fun `unconsumedStatesForSpending insufficient amount`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L))
val unconsumedStates = vaultQuery.queryBy<Cash.State>().states val unconsumedStates = vaultQuery.queryBy<Cash.State>().states
assertThat(unconsumedStates).hasSize(1) assertThat(unconsumedStates).hasSize(1)
@ -386,7 +382,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `unconsumedStatesForSpending small amount`() { fun `unconsumedStatesForSpending small amount`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 2, 2, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 2, 2, Random(0L))
val unconsumedStates = vaultQuery.queryBy<Cash.State>().states val unconsumedStates = vaultQuery.queryBy<Cash.State>().states
assertThat(unconsumedStates).hasSize(2) assertThat(unconsumedStates).hasSize(2)
@ -404,9 +400,9 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `states soft locking query granularity`() { fun `states soft locking query granularity`() {
database.transaction { database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 10, 10, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 10, 10, Random(0L))
services.fillWithSomeTestCash(100.POUNDS, DUMMY_NOTARY, 10, 10, Random(0L)) services.fillWithSomeTestCash(100.POUNDS, issuerServices, DUMMY_NOTARY, 10, 10, Random(0L))
services.fillWithSomeTestCash(100.SWISS_FRANCS, DUMMY_NOTARY, 10, 10, Random(0L)) services.fillWithSomeTestCash(100.SWISS_FRANCS, issuerServices, DUMMY_NOTARY, 10, 10, Random(0L))
var unlockedStates = 30 var unlockedStates = 30
val allStates = vaultQuery.queryBy<Cash.State>().states val allStates = vaultQuery.queryBy<Cash.State>().states
@ -535,21 +531,20 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
// Issue some cash // Issue some cash
val issueTxBuilder = TransactionBuilder(notary).apply { val issueTxBuilder = TransactionBuilder(notary).apply {
Cash().generateIssue(this, amount, anonymousIdentity.party, notary) Cash().generateIssue(this, amount, anonymousIdentity.party, notary)
signWith(BOC_KEY)
} }
val issueStx = services.signInitialTransaction(issueTxBuilder)
// We need to record the issue transaction so inputs can be resolved for the notary change transaction // We need to record the issue transaction so inputs can be resolved for the notary change transaction
services.validatedTransactions.addTransaction(issueTxBuilder.toSignedTransaction()) services.validatedTransactions.addTransaction(issueStx)
val issueTx = issueTxBuilder.toWireTransaction() val initialCashState = StateAndRef(issueStx.tx.outputs.single(), StateRef(issueStx.id, 0))
val initialCashState = StateAndRef(issueTx.outputs.single(), StateRef(issueTx.id, 0))
// Change notary // Change notary
val newNotary = DUMMY_NOTARY val newNotary = DUMMY_NOTARY
val changeNotaryTx = NotaryChangeWireTransaction(listOf(initialCashState.ref), issueTx.notary!!, newNotary) val changeNotaryTx = NotaryChangeWireTransaction(listOf(initialCashState.ref), issueStx.notary!!, newNotary)
val cashStateWithNewNotary = StateAndRef(initialCashState.state.copy(notary = newNotary), StateRef(changeNotaryTx.id, 0)) val cashStateWithNewNotary = StateAndRef(initialCashState.state.copy(notary = newNotary), StateRef(changeNotaryTx.id, 0))
database.transaction { database.transaction {
service.notifyAll(listOf(issueTx, changeNotaryTx)) service.notifyAll(listOf(issueStx.tx, changeNotaryTx))
} }
// Move cash // Move cash

View File

@ -2,6 +2,7 @@ package net.corda.node.services.vault
import net.corda.contracts.asset.Cash import net.corda.contracts.asset.Cash
import net.corda.contracts.asset.DUMMY_CASH_ISSUER import net.corda.contracts.asset.DUMMY_CASH_ISSUER
import net.corda.contracts.asset.DUMMY_CASH_ISSUER_KEY
import net.corda.contracts.getCashBalance import net.corda.contracts.getCashBalance
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.identity.AnonymousParty import net.corda.core.identity.AnonymousParty
@ -34,6 +35,7 @@ import kotlin.test.assertEquals
class VaultWithCashTest : TestDependencyInjectionBase() { class VaultWithCashTest : TestDependencyInjectionBase() {
lateinit var services: MockServices lateinit var services: MockServices
lateinit var issuerServices: MockServices
val vault: VaultService get() = services.vaultService val vault: VaultService get() = services.vaultService
val vaultQuery: VaultQueryService get() = services.vaultQueryService val vaultQuery: VaultQueryService get() = services.vaultQueryService
lateinit var database: CordaPersistence lateinit var database: CordaPersistence
@ -42,9 +44,10 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
@Before @Before
fun setUp() { fun setUp() {
LogHelper.setLevel(VaultWithCashTest::class) LogHelper.setLevel(VaultWithCashTest::class)
val databaseAndServices = makeTestDatabaseAndMockServices() val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(DUMMY_CASH_ISSUER_KEY, DUMMY_NOTARY_KEY))
database = databaseAndServices.first database = databaseAndServices.first
services = databaseAndServices.second services = databaseAndServices.second
issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY, MEGA_CORP_KEY)
} }
@After @After
@ -57,7 +60,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
fun splits() { fun splits() {
database.transaction { database.transaction {
// Fix the PRNG so that we get the same splits every time. // Fix the PRNG so that we get the same splits every time.
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 3, 3, Random(0L), issuedBy = DUMMY_CASH_ISSUER)
val w = vaultQuery.queryBy<Cash.State>().states val w = vaultQuery.queryBy<Cash.State>().states
assertEquals(3, w.size) assertEquals(3, w.size)
@ -117,10 +120,8 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
database.transaction { database.transaction {
// A tx that sends us money. // A tx that sends us money.
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 10, 10, Random(0L), services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 10, 10, Random(0L), ownedBy = AnonymousParty(freshKey),
issuedBy = MEGA_CORP.ref(1), issuedBy = MEGA_CORP.ref(1))
issuerKey = MEGA_CORP_KEY,
ownedBy = AnonymousParty(freshKey))
println("Cash balance: ${services.getCashBalance(USD)}") println("Cash balance: ${services.getCashBalance(USD)}")
assertThat(vaultQuery.queryBy<Cash.State>().states).hasSize(10) assertThat(vaultQuery.queryBy<Cash.State>().states).hasSize(10)
@ -269,9 +270,9 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val freshKey = services.keyManagementService.freshKey() val freshKey = services.keyManagementService.freshKey()
database.transaction { database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L), ownedBy = AnonymousParty(freshKey)) services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 3, 3, Random(0L), ownedBy = AnonymousParty(freshKey))
services.fillWithSomeTestCash(100.SWISS_FRANCS, DUMMY_NOTARY, 2, 2, Random(0L)) services.fillWithSomeTestCash(100.SWISS_FRANCS, issuerServices, DUMMY_NOTARY, 2, 2, Random(0L))
services.fillWithSomeTestCash(100.POUNDS, DUMMY_NOTARY, 1, 1, Random(0L)) services.fillWithSomeTestCash(100.POUNDS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L))
val cash = vaultQuery.queryBy<Cash.State>().states val cash = vaultQuery.queryBy<Cash.State>().states
cash.forEach { println(it.state.data.amount) } cash.forEach { println(it.state.data.amount) }

View File

@ -4,6 +4,7 @@ import co.paralleluniverse.fibers.Suspendable
import net.corda.contracts.Fix import net.corda.contracts.Fix
import net.corda.contracts.FixableDealState import net.corda.contracts.FixableDealState
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.TransactionSignature
import net.corda.core.crypto.toBase58String import net.corda.core.crypto.toBase58String
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatedBy import net.corda.core.flows.InitiatedBy
@ -12,13 +13,13 @@ import net.corda.core.flows.SchedulableFlow
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.node.services.ServiceType import net.corda.core.node.services.ServiceType
import net.corda.core.utilities.seconds
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.transient
import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.seconds
import net.corda.core.utilities.trace import net.corda.core.utilities.trace
import net.corda.core.utilities.transient
import net.corda.flows.TwoPartyDealFlow import net.corda.flows.TwoPartyDealFlow
import java.math.BigDecimal import java.math.BigDecimal
import java.security.PublicKey import java.security.PublicKey
@ -52,7 +53,7 @@ object FixingFlow {
} }
@Suspendable @Suspendable
override fun assembleSharedTX(handshake: TwoPartyDealFlow.Handshake<FixingSession>): Pair<TransactionBuilder, List<PublicKey>> { override fun assembleSharedTX(handshake: TwoPartyDealFlow.Handshake<FixingSession>): Triple<TransactionBuilder, List<PublicKey>, List<TransactionSignature>> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val fixOf = deal.nextFixingOf()!! val fixOf = deal.nextFixingOf()!!
@ -85,9 +86,9 @@ object FixingFlow {
} }
} }
} }
subFlow(addFixing) val sig = subFlow(addFixing)
// DOCEND 1 // DOCEND 1
return Pair(ptx, arrayListOf(myOldParty.owningKey)) return Triple(ptx, arrayListOf(myOldParty.owningKey), listOf(sig))
} }
} }

View File

@ -33,7 +33,7 @@ open class RatesFixFlow(protected val tx: TransactionBuilder,
protected val fixOf: FixOf, protected val fixOf: FixOf,
protected val expectedRate: BigDecimal, protected val expectedRate: BigDecimal,
protected val rateTolerance: BigDecimal, protected val rateTolerance: BigDecimal,
override val progressTracker: ProgressTracker = RatesFixFlow.tracker(fixOf.name)) : FlowLogic<Unit>() { override val progressTracker: ProgressTracker = RatesFixFlow.tracker(fixOf.name)) : FlowLogic<TransactionSignature>() {
companion object { companion object {
class QUERYING(val name: String) : ProgressTracker.Step("Querying oracle for $name interest rate") class QUERYING(val name: String) : ProgressTracker.Step("Querying oracle for $name interest rate")
@ -54,7 +54,7 @@ open class RatesFixFlow(protected val tx: TransactionBuilder,
// DOCSTART 2 // DOCSTART 2
@Suspendable @Suspendable
override fun call() { override fun call(): TransactionSignature {
progressTracker.currentStep = progressTracker.steps[1] progressTracker.currentStep = progressTracker.steps[1]
val fix = subFlow(FixQueryFlow(fixOf, oracle)) val fix = subFlow(FixQueryFlow(fixOf, oracle))
progressTracker.currentStep = WORKING progressTracker.currentStep = WORKING
@ -63,8 +63,7 @@ open class RatesFixFlow(protected val tx: TransactionBuilder,
beforeSigning(fix) beforeSigning(fix)
progressTracker.currentStep = SIGNING progressTracker.currentStep = SIGNING
val mtx = tx.toWireTransaction().buildFilteredTransaction(Predicate { filtering(it) }) val mtx = tx.toWireTransaction().buildFilteredTransaction(Predicate { filtering(it) })
val signature = subFlow(FixSignFlow(tx, oracle, mtx)) return subFlow(FixSignFlow(tx, oracle, mtx))
tx.addSignatureUnchecked(signature)
} }
// DOCEND 2 // DOCEND 2

View File

@ -6,6 +6,8 @@ import net.corda.contracts.Commodity
import net.corda.contracts.DealState import net.corda.contracts.DealState
import net.corda.contracts.asset.* import net.corda.contracts.asset.*
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SignatureMetadata
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty import net.corda.core.identity.AnonymousParty
@ -19,7 +21,6 @@ import net.corda.core.utilities.OpaqueBytes
import net.corda.testing.CHARLIE import net.corda.testing.CHARLIE
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.DUMMY_NOTARY_KEY import net.corda.testing.DUMMY_NOTARY_KEY
import java.security.KeyPair
import java.security.PublicKey import java.security.PublicKey
import java.time.Duration import java.time.Duration
import java.time.Instant import java.time.Instant
@ -28,17 +29,18 @@ import java.util.*
@JvmOverloads @JvmOverloads
fun ServiceHub.fillWithSomeTestDeals(dealIds: List<String>, fun ServiceHub.fillWithSomeTestDeals(dealIds: List<String>,
participants: List<AbstractParty> = emptyList()) : Vault<DealState> { participants: List<AbstractParty> = emptyList(),
notary: Party = DUMMY_NOTARY) : Vault<DealState> {
val myKey: PublicKey = myInfo.legalIdentity.owningKey val myKey: PublicKey = myInfo.legalIdentity.owningKey
val me = AnonymousParty(myKey) val me = AnonymousParty(myKey)
val transactions: List<SignedTransaction> = dealIds.map { val transactions: List<SignedTransaction> = dealIds.map {
// Issue a deal state // Issue a deal state
val dummyIssue = TransactionBuilder(notary = DUMMY_NOTARY).apply { val dummyIssue = TransactionBuilder(notary = notary).apply {
addOutputState(DummyDealContract.State(ref = it, participants = participants.plus(me))) addOutputState(DummyDealContract.State(ref = it, participants = participants.plus(me)))
signWith(DUMMY_NOTARY_KEY)
} }
return@map signInitialTransaction(dummyIssue) val stx = signInitialTransaction(dummyIssue)
return@map addSignature(stx, notary.owningKey)
} }
recordTransactions(transactions) recordTransactions(transactions)
@ -61,6 +63,8 @@ fun ServiceHub.fillWithSomeTestLinearStates(numberToCreate: Int,
linearTimestamp: Instant = now()) : Vault<LinearState> { linearTimestamp: Instant = now()) : Vault<LinearState> {
val myKey: PublicKey = myInfo.legalIdentity.owningKey val myKey: PublicKey = myInfo.legalIdentity.owningKey
val me = AnonymousParty(myKey) val me = AnonymousParty(myKey)
val issuerKey = DUMMY_NOTARY_KEY
val signatureMetadata = SignatureMetadata(myInfo.platformVersion, Crypto.findSignatureScheme(issuerKey.public).schemeNumberID)
val transactions: List<SignedTransaction> = (1..numberToCreate).map { val transactions: List<SignedTransaction> = (1..numberToCreate).map {
// Issue a Linear state // Issue a Linear state
@ -72,10 +76,9 @@ fun ServiceHub.fillWithSomeTestLinearStates(numberToCreate: Int,
linearNumber = linearNumber, linearNumber = linearNumber,
linearBoolean = linearBoolean, linearBoolean = linearBoolean,
linearTimestamp = linearTimestamp)) linearTimestamp = linearTimestamp))
signWith(DUMMY_NOTARY_KEY)
} }
return@map signInitialTransaction(dummyIssue) return@map signInitialTransaction(dummyIssue).withAdditionalSignature(issuerKey, signatureMetadata)
} }
recordTransactions(transactions) recordTransactions(transactions)
@ -95,18 +98,19 @@ fun ServiceHub.fillWithSomeTestLinearStates(numberToCreate: Int,
* *
* The service hub needs to provide at least a key management service and a storage service. * The service hub needs to provide at least a key management service and a storage service.
* *
* @param issuerServices service hub of the issuer node, which will be used to sign the transaction.
* @param outputNotary the notary to use for output states. The transaction is NOT signed by this notary. * @param outputNotary the notary to use for output states. The transaction is NOT signed by this notary.
* @return a vault object that represents the generated states (it will NOT be the full vault from the service hub!). * @return a vault object that represents the generated states (it will NOT be the full vault from the service hub!).
*/ */
fun ServiceHub.fillWithSomeTestCash(howMuch: Amount<Currency>, fun ServiceHub.fillWithSomeTestCash(howMuch: Amount<Currency>,
issuerServices: ServiceHub = this,
outputNotary: Party = DUMMY_NOTARY, outputNotary: Party = DUMMY_NOTARY,
atLeastThisManyStates: Int = 3, atLeastThisManyStates: Int = 3,
atMostThisManyStates: Int = 10, atMostThisManyStates: Int = 10,
rng: Random = Random(), rng: Random = Random(),
ref: OpaqueBytes = OpaqueBytes(ByteArray(1, { 1 })), ref: OpaqueBytes = OpaqueBytes(ByteArray(1, { 1 })),
ownedBy: AbstractParty? = null, ownedBy: AbstractParty? = null,
issuedBy: PartyAndReference = DUMMY_CASH_ISSUER, issuedBy: PartyAndReference = DUMMY_CASH_ISSUER): Vault<Cash.State> {
issuerKey: KeyPair = DUMMY_CASH_ISSUER_KEY): Vault<Cash.State> {
val amounts = calculateRandomlySizedAmounts(howMuch, atLeastThisManyStates, atMostThisManyStates, rng) val amounts = calculateRandomlySizedAmounts(howMuch, atLeastThisManyStates, atMostThisManyStates, rng)
val myKey: PublicKey = ownedBy?.owningKey ?: myInfo.legalIdentity.owningKey val myKey: PublicKey = ownedBy?.owningKey ?: myInfo.legalIdentity.owningKey
@ -117,9 +121,8 @@ fun ServiceHub.fillWithSomeTestCash(howMuch: Amount<Currency>,
val transactions: List<SignedTransaction> = amounts.map { pennies -> val transactions: List<SignedTransaction> = amounts.map { pennies ->
val issuance = TransactionBuilder(null as Party?) val issuance = TransactionBuilder(null as Party?)
cash.generateIssue(issuance, Amount(pennies, Issued(issuedBy.copy(reference = ref), howMuch.token)), me, outputNotary) cash.generateIssue(issuance, Amount(pennies, Issued(issuedBy.copy(reference = ref), howMuch.token)), me, outputNotary)
issuance.signWith(issuerKey)
return@map issuance.toSignedTransaction(true) return@map issuerServices.signInitialTransaction(issuance, issuedBy.party.owningKey)
} }
recordTransactions(transactions) recordTransactions(transactions)
@ -132,21 +135,26 @@ fun ServiceHub.fillWithSomeTestCash(howMuch: Amount<Currency>,
return Vault(states) return Vault(states)
} }
/**
*
* @param issuerServices service hub of the issuer node, which will be used to sign the transaction.
* @param outputNotary the notary to use for output states. The transaction is NOT signed by this notary.
* @return a vault object that represents the generated states (it will NOT be the full vault from the service hub!).
*/
// TODO: need to make all FungibleAsset commands (issue, move, exit) generic // TODO: need to make all FungibleAsset commands (issue, move, exit) generic
fun ServiceHub.fillWithSomeTestCommodity(amount: Amount<Commodity>, fun ServiceHub.fillWithSomeTestCommodity(amount: Amount<Commodity>,
issuerServices: ServiceHub = this,
outputNotary: Party = DUMMY_NOTARY, outputNotary: Party = DUMMY_NOTARY,
ref: OpaqueBytes = OpaqueBytes(ByteArray(1, { 1 })), ref: OpaqueBytes = OpaqueBytes(ByteArray(1, { 1 })),
ownedBy: AbstractParty? = null, ownedBy: AbstractParty? = null,
issuedBy: PartyAndReference = DUMMY_OBLIGATION_ISSUER.ref(1), issuedBy: PartyAndReference = DUMMY_OBLIGATION_ISSUER.ref(1)): Vault<CommodityContract.State> {
issuerKey: KeyPair = DUMMY_OBLIGATION_ISSUER_KEY): Vault<CommodityContract.State> {
val myKey: PublicKey = ownedBy?.owningKey ?: myInfo.legalIdentity.owningKey val myKey: PublicKey = ownedBy?.owningKey ?: myInfo.legalIdentity.owningKey
val me = AnonymousParty(myKey) val me = AnonymousParty(myKey)
val commodity = CommodityContract() val commodity = CommodityContract()
val issuance = TransactionBuilder(null as Party?) val issuance = TransactionBuilder(null as Party?)
commodity.generateIssue(issuance, Amount(amount.quantity, Issued(issuedBy.copy(reference = ref), amount.token)), me, outputNotary) commodity.generateIssue(issuance, Amount(amount.quantity, Issued(issuedBy.copy(reference = ref), amount.token)), me, outputNotary)
issuance.signWith(issuerKey) val transaction = issuerServices.signInitialTransaction(issuance, issuedBy.party.owningKey)
val transaction = issuance.toSignedTransaction(true)
recordTransactions(transaction) recordTransactions(transaction)
@ -181,62 +189,62 @@ fun calculateRandomlySizedAmounts(howMuch: Amount<Currency>, min: Int, max: Int,
return amounts return amounts
} }
fun <T : LinearState> ServiceHub.consume(states: List<StateAndRef<T>>) { fun <T : LinearState> ServiceHub.consume(states: List<StateAndRef<T>>, notary: Party) {
// Create a txn consuming different contract types // Create a txn consuming different contract types
states.forEach { states.forEach {
val consumedTx = TransactionBuilder(notary = DUMMY_NOTARY).apply { val builder = TransactionBuilder(notary = notary).apply {
addInputState(it) addInputState(it)
signWith(DUMMY_NOTARY_KEY) }
}.toSignedTransaction() val consumedTx = signInitialTransaction(builder, notary.owningKey)
recordTransactions(consumedTx) recordTransactions(consumedTx)
} }
} }
fun <T : LinearState> ServiceHub.consumeAndProduce(stateAndRef: StateAndRef<T>): StateAndRef<T> { fun <T : LinearState> ServiceHub.consumeAndProduce(stateAndRef: StateAndRef<T>, notary: Party): StateAndRef<T> {
// Create a txn consuming different contract types // Create a txn consuming different contract types
val consumedTx = TransactionBuilder(notary = DUMMY_NOTARY).apply { var builder = TransactionBuilder(notary = notary).apply {
addInputState(stateAndRef) addInputState(stateAndRef)
signWith(DUMMY_NOTARY_KEY) }
}.toSignedTransaction() val consumedTx = signInitialTransaction(builder, notary.owningKey)
recordTransactions(consumedTx) recordTransactions(consumedTx)
// Create a txn consuming different contract types // Create a txn consuming different contract types
val producedTx = TransactionBuilder(notary = DUMMY_NOTARY).apply { builder = TransactionBuilder(notary = notary).apply {
addOutputState(DummyLinearContract.State(linearId = stateAndRef.state.data.linearId, addOutputState(DummyLinearContract.State(linearId = stateAndRef.state.data.linearId,
participants = stateAndRef.state.data.participants)) participants = stateAndRef.state.data.participants))
signWith(DUMMY_NOTARY_KEY) }
}.toSignedTransaction() val producedTx = signInitialTransaction(builder, notary.owningKey)
recordTransactions(producedTx) recordTransactions(producedTx)
return producedTx.tx.outRef<T>(0) return producedTx.tx.outRef<T>(0)
} }
fun <T : LinearState> ServiceHub.consumeAndProduce(states: List<StateAndRef<T>>) { fun <T : LinearState> ServiceHub.consumeAndProduce(states: List<StateAndRef<T>>, notary: Party) {
states.forEach { states.forEach {
consumeAndProduce(it) consumeAndProduce(it, notary)
} }
} }
fun ServiceHub.consumeDeals(dealStates: List<StateAndRef<DealState>>) = consume(dealStates) fun ServiceHub.consumeDeals(dealStates: List<StateAndRef<DealState>>, notary: Party) = consume(dealStates, notary)
fun ServiceHub.consumeLinearStates(linearStates: List<StateAndRef<LinearState>>) = consume(linearStates) fun ServiceHub.consumeLinearStates(linearStates: List<StateAndRef<LinearState>>, notary: Party) = consume(linearStates, notary)
fun ServiceHub.evolveLinearStates(linearStates: List<StateAndRef<LinearState>>) = consumeAndProduce(linearStates) fun ServiceHub.evolveLinearStates(linearStates: List<StateAndRef<LinearState>>, notary: Party) = consumeAndProduce(linearStates, notary)
fun ServiceHub.evolveLinearState(linearState: StateAndRef<LinearState>) : StateAndRef<LinearState> = consumeAndProduce(linearState) fun ServiceHub.evolveLinearState(linearState: StateAndRef<LinearState>, notary: Party) : StateAndRef<LinearState> = consumeAndProduce(linearState, notary)
@JvmOverloads @JvmOverloads
fun ServiceHub.consumeCash(amount: Amount<Currency>, to: Party = CHARLIE): Vault.Update<ContractState> { fun ServiceHub.consumeCash(amount: Amount<Currency>, to: Party = CHARLIE, notary: Party): Vault.Update<ContractState> {
val update = vaultService.rawUpdates.toFuture() val update = vaultService.rawUpdates.toFuture()
val services = this val services = this
// A tx that spends our money. // A tx that spends our money.
val spendTX = TransactionBuilder(DUMMY_NOTARY).apply { val builder = TransactionBuilder(notary).apply {
Cash.generateSpend(services, this, amount, to) Cash.generateSpend(services, this, amount, to)
signWith(DUMMY_NOTARY_KEY) }
}.toSignedTransaction(checkSufficientSignatures = false) val spendTx = signInitialTransaction(builder, notary.owningKey)
recordTransactions(spendTX) recordTransactions(spendTx)
return update.getOrThrow(Duration.ofSeconds(3)) return update.getOrThrow(Duration.ofSeconds(3))
} }