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].
private fun signInitialTransaction(builder: TransactionBuilder, publicKey: PublicKey, signatureMetadata: SignatureMetadata): SignedTransaction {
val signableData = SignableData(builder.toWireTransaction().id, signatureMetadata)
val sig = keyManagementService.sign(signableData, publicKey)
builder.addSignatureUnchecked(sig)
return builder.toSignedTransaction(false)
return builder.toSignedTransaction(keyManagementService, publicKey, signatureMetadata)
}
/**

View File

@ -1,15 +1,16 @@
package net.corda.core.transactions
import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.TransactionSignature
import net.corda.core.crypto.*
import net.corda.core.identity.Party
import net.corda.core.internal.VisibleForTesting
import net.corda.core.node.ServiceHub
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializedBytes
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.getOrThrow
import java.security.KeyPair
import java.security.PublicKey
import java.security.SignatureException
import java.util.*
@ -74,6 +75,12 @@ data class SignedTransaction(val txBits: SerializedBytes<CoreTransaction>,
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. */
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.internal.FlowStateMachine
import net.corda.core.node.ServiceHub
import net.corda.core.node.services.KeyManagementService
import java.security.KeyPair
import java.security.PublicKey
import java.security.SignatureException
import java.time.Duration
import java.time.Instant
import java.util.*
@ -149,59 +149,14 @@ open class TransactionBuilder(
fun outputStates(): List<TransactionState<*>> = ArrayList(outputs)
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.")
protected val currentSigs = arrayListOf<TransactionSignature>()
@Deprecated("Use ServiceHub.signInitialTransaction() instead.")
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()}")
}
/**
* Sign the built transaction and return it. This is an internal function for use by the service hub, please use
* [ServiceHub.signInitialTransaction] instead.
*/
fun toSignedTransaction(keyManagementService: KeyManagementService, publicKey: PublicKey, signatureMetadata: SignatureMetadata): SignedTransaction {
val wtx = toWireTransaction()
return SignedTransaction(wtx, ArrayList(currentSigs))
}
/**
* 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)
val signableData = SignableData(wtx.id, signatureMetadata)
val sig = keyManagementService.sign(signableData, publicKey)
return SignedTransaction(wtx, listOf(sig))
}
}

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
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``
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.
* 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
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
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.

View File

@ -79,7 +79,7 @@ the following:
txBuilder.verify(serviceHub)
// Signing the transaction.
val signedTx = serviceHub.signInitialTransaction(txBuilder)
val signedTx = serviceHub.toSignedTransaction(txBuilder)
// Finalising the transaction.
subFlow(FinalityFlow(signedTx))
@ -141,7 +141,7 @@ the following:
txBuilder.verify(getServiceHub());
// Signing the transaction.
final SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
final SignedTransaction signedTx = getServiceHub().toSignedTransaction(txBuilder);
// Finalising the transaction.
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
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.
Finalising the transaction

View File

@ -36,7 +36,7 @@ In ``IOUFlow.java``/``IOUFlow.kt``, update ``IOUFlow.call`` as follows:
txBuilder.verify(serviceHub)
// Signing the transaction.
val signedTx = serviceHub.signInitialTransaction(txBuilder)
val signedTx = serviceHub.toSignedTransaction(txBuilder)
// Obtaining the counterparty's signature
val fullySignedTx = subFlow(CollectSignaturesFlow(signedTx))
@ -56,7 +56,7 @@ In ``IOUFlow.java``/``IOUFlow.kt``, update ``IOUFlow.call`` as follows:
txBuilder.verify(getServiceHub());
// Signing the transaction.
final SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
final SignedTransaction signedTx = getServiceHub().toSignedTransaction(txBuilder);
// Obtaining the counterparty's signature
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
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.
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
val mySigningKey: PublicKey = serviceHub.legalIdentityKey
val issueTransaction = serviceHub.signInitialTransaction(issueTransaction, mySigningKey)
val issueTransaction = serviceHub.toSignedTransaction(issueTransaction, mySigningKey)
serviceHub.recordTransactions(issueTransaction)
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,
// 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
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.core.contracts.requireThat
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.TransactionSignature
import net.corda.core.flows.CollectSignaturesFlow
import net.corda.core.flows.FinalityFlow
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.node.NodeInfo
import net.corda.core.node.services.ServiceType
import net.corda.core.utilities.seconds
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.seconds
import net.corda.core.utilities.trace
import net.corda.core.utilities.unwrap
import java.security.PublicKey
@ -92,8 +93,12 @@ object TwoPartyDealFlow {
val handshake = receiveAndValidateHandshake()
progressTracker.currentStep = SIGNING
val (utx, additionalSigningPubKeys) = assembleSharedTX(handshake)
val ptx = signWithOurKeys(additionalSigningPubKeys, utx)
val (utx, additionalSigningPubKeys, additionalSignatures) = assembleSharedTX(handshake)
val ptx = if (additionalSignatures.any()) {
serviceHub.signInitialTransaction(utx, additionalSigningPubKeys).withAdditionalSignatures(additionalSignatures)
} else {
serviceHub.signInitialTransaction(utx, additionalSigningPubKeys)
}
logger.trace { "Signed proposed transaction." }
@ -136,13 +141,8 @@ object TwoPartyDealFlow {
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 assembleSharedTX(handshake: Handshake<U>): Pair<TransactionBuilder, List<PublicKey>>
@Suspendable protected abstract fun assembleSharedTX(handshake: Handshake<U>): Triple<TransactionBuilder, List<PublicKey>, List<TransactionSignature>>
}
@CordaSerializable
@ -178,14 +178,14 @@ object TwoPartyDealFlow {
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 ptx = deal.generateAgreement(handshake.payload.notary)
// 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.
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 val notaryServices = MockServices(DUMMY_NOTARY_KEY)
private val issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY)
private lateinit var moveTX: SignedTransaction
@ -216,7 +217,7 @@ class CommercialPaperTestsGeneric {
aliceVaultService = aliceServices.vaultService
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
}
@ -226,7 +227,7 @@ class CommercialPaperTestsGeneric {
bigCorpVaultService = bigCorpServices.vaultService
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
}

View File

@ -6,17 +6,11 @@ import net.corda.core.crypto.generateKeyPair
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty
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.queryBy
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.transactions.WireTransaction
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.utilities.CordaPersistence
import net.corda.testing.*
@ -47,6 +41,7 @@ class CashTests : TestDependencyInjectionBase() {
)
lateinit var miniCorpServices: MockServices
lateinit var megaCorpServices: MockServices
val vault: VaultService get() = miniCorpServices.vaultService
lateinit var database: CordaPersistence
lateinit var vaultStatesUnconsumed: List<StateAndRef<Cash.State>>
@ -54,19 +49,20 @@ class CashTests : TestDependencyInjectionBase() {
@Before
fun setUp() {
LogHelper.setLevel(NodeVaultService::class)
megaCorpServices = MockServices(MEGA_CORP_KEY)
val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(MINI_CORP_KEY, MEGA_CORP_KEY, OUR_KEY))
database = databaseAndServices.first
miniCorpServices = databaseAndServices.second
database.transaction {
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,
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,
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,
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
}

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

View File

@ -96,17 +96,19 @@ class TwoPartyTradeFlowTests {
val aliceNode = basketOfNodes.partyNodes[0]
val bobNode = basketOfNodes.partyNodes[1]
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()
bobNode.disableDBCloseOnStop()
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 {
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
}
@ -142,14 +144,16 @@ class TwoPartyTradeFlowTests {
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.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)
aliceNode.disableDBCloseOnStop()
bobNode.disableDBCloseOnStop()
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 {
fillUpForSeller(false, cpIssuer, aliceNode.info.legalIdentity,
@ -194,6 +198,7 @@ class TwoPartyTradeFlowTests {
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.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)
aliceNode.services.identityService.registerIdentity(bobNode.info.legalIdentityAndCert)
@ -207,7 +212,8 @@ class TwoPartyTradeFlowTests {
mockNet.runNetwork() // Clear network map registration messages
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 {
fillUpForSeller(false, cpIssuer, aliceNode.info.legalIdentity,

View File

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

View File

@ -3,6 +3,7 @@ package net.corda.node.services.vault
import co.paralleluniverse.fibers.Suspendable
import net.corda.contracts.asset.Cash
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.getCashBalance
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.AnonymousParty
import net.corda.core.identity.Party
import net.corda.core.node.services.StatesNotAvailableException
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.*
import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.node.services.vault.QueryCriteria.*
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.OpaqueBytes
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.testing.*
import net.corda.testing.contracts.fillWithSomeTestCash
@ -47,6 +41,7 @@ import kotlin.test.assertTrue
class NodeVaultServiceTest : TestDependencyInjectionBase() {
lateinit var services: MockServices
lateinit var issuerServices: MockServices
val vaultSvc: VaultService get() = services.vaultService
val vaultQuery: VaultQueryService get() = services.vaultQueryService
lateinit var database: CordaPersistence
@ -54,9 +49,10 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
@Before
fun setUp() {
LogHelper.setLevel(NodeVaultService::class)
val databaseAndServices = makeTestDatabaseAndMockServices()
val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(BOC_KEY, DUMMY_CASH_ISSUER_KEY))
database = databaseAndServices.first
services = databaseAndServices.second
issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY, BOC_KEY)
}
@After
@ -88,7 +84,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `states not local to instance`() {
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
assertThat(w1).hasSize(3)
@ -115,7 +111,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `states for refs`() {
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
assertThat(w1).hasSize(3)
@ -129,7 +125,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `states soft locking reserve and release`() {
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
assertThat(unconsumedStates).hasSize(3)
@ -180,7 +176,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val vaultStates =
database.transaction {
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()
println("State Refs:: $stateRefsToSoftLock")
@ -235,7 +231,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val vaultStates =
database.transaction {
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 }
println("State Refs:: $stateRefsToSoftLock")
@ -263,7 +259,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val vaultStates =
database.transaction {
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()
println("State Refs:: $stateRefsToSoftLock")
@ -290,7 +286,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val vaultStates =
database.transaction {
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 }
println("State Refs:: $stateRefsToSoftLock")
@ -312,7 +308,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `unconsumedStatesForSpending exact amount`() {
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
assertThat(unconsumedStates).hasSize(1)
@ -330,8 +326,8 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `unconsumedStatesForSpending from two issuer parties`() {
database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, 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 = (DUMMY_CASH_ISSUER))
services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(1)))
val spendableStatesUSD = vaultSvc.unconsumedCashStatesForSpending(200.DOLLARS,
onlyFromIssuerParties = setOf(DUMMY_CASH_ISSUER.party, BOC))
@ -347,10 +343,10 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `unconsumedStatesForSpending from specific issuer party and refs`() {
database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, 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, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(2)), issuerKey = BOC_KEY, 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 = (DUMMY_CASH_ISSUER))
services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(1)), ref = OpaqueBytes.of(1))
services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(2)), ref = OpaqueBytes.of(2))
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
assertThat(unconsumedStates).hasSize(4)
@ -369,7 +365,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `unconsumedStatesForSpending insufficient amount`() {
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
assertThat(unconsumedStates).hasSize(1)
@ -386,7 +382,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `unconsumedStatesForSpending small amount`() {
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
assertThat(unconsumedStates).hasSize(2)
@ -404,9 +400,9 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `states soft locking query granularity`() {
database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 10, 10, Random(0L))
services.fillWithSomeTestCash(100.POUNDS, DUMMY_NOTARY, 10, 10, Random(0L))
services.fillWithSomeTestCash(100.SWISS_FRANCS, DUMMY_NOTARY, 10, 10, Random(0L))
services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 10, 10, Random(0L))
services.fillWithSomeTestCash(100.POUNDS, issuerServices, DUMMY_NOTARY, 10, 10, Random(0L))
services.fillWithSomeTestCash(100.SWISS_FRANCS, issuerServices, DUMMY_NOTARY, 10, 10, Random(0L))
var unlockedStates = 30
val allStates = vaultQuery.queryBy<Cash.State>().states
@ -535,21 +531,20 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
// Issue some cash
val issueTxBuilder = TransactionBuilder(notary).apply {
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
services.validatedTransactions.addTransaction(issueTxBuilder.toSignedTransaction())
services.validatedTransactions.addTransaction(issueStx)
val issueTx = issueTxBuilder.toWireTransaction()
val initialCashState = StateAndRef(issueTx.outputs.single(), StateRef(issueTx.id, 0))
val initialCashState = StateAndRef(issueStx.tx.outputs.single(), StateRef(issueStx.id, 0))
// Change 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))
database.transaction {
service.notifyAll(listOf(issueTx, changeNotaryTx))
service.notifyAll(listOf(issueStx.tx, changeNotaryTx))
}
// 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.DUMMY_CASH_ISSUER
import net.corda.contracts.asset.DUMMY_CASH_ISSUER_KEY
import net.corda.contracts.getCashBalance
import net.corda.core.contracts.*
import net.corda.core.identity.AnonymousParty
@ -34,6 +35,7 @@ import kotlin.test.assertEquals
class VaultWithCashTest : TestDependencyInjectionBase() {
lateinit var services: MockServices
lateinit var issuerServices: MockServices
val vault: VaultService get() = services.vaultService
val vaultQuery: VaultQueryService get() = services.vaultQueryService
lateinit var database: CordaPersistence
@ -42,9 +44,10 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
@Before
fun setUp() {
LogHelper.setLevel(VaultWithCashTest::class)
val databaseAndServices = makeTestDatabaseAndMockServices()
val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(DUMMY_CASH_ISSUER_KEY, DUMMY_NOTARY_KEY))
database = databaseAndServices.first
services = databaseAndServices.second
issuerServices = MockServices(DUMMY_CASH_ISSUER_KEY, MEGA_CORP_KEY)
}
@After
@ -57,7 +60,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
fun splits() {
database.transaction {
// 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
assertEquals(3, w.size)
@ -117,10 +120,8 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
database.transaction {
// A tx that sends us money.
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 10, 10, Random(0L),
issuedBy = MEGA_CORP.ref(1),
issuerKey = MEGA_CORP_KEY,
ownedBy = AnonymousParty(freshKey))
services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 10, 10, Random(0L), ownedBy = AnonymousParty(freshKey),
issuedBy = MEGA_CORP.ref(1))
println("Cash balance: ${services.getCashBalance(USD)}")
assertThat(vaultQuery.queryBy<Cash.State>().states).hasSize(10)
@ -269,9 +270,9 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val freshKey = services.keyManagementService.freshKey()
database.transaction {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L), ownedBy = AnonymousParty(freshKey))
services.fillWithSomeTestCash(100.SWISS_FRANCS, DUMMY_NOTARY, 2, 2, Random(0L))
services.fillWithSomeTestCash(100.POUNDS, DUMMY_NOTARY, 1, 1, Random(0L))
services.fillWithSomeTestCash(100.DOLLARS, issuerServices, DUMMY_NOTARY, 3, 3, Random(0L), ownedBy = AnonymousParty(freshKey))
services.fillWithSomeTestCash(100.SWISS_FRANCS, issuerServices, DUMMY_NOTARY, 2, 2, Random(0L))
services.fillWithSomeTestCash(100.POUNDS, issuerServices, DUMMY_NOTARY, 1, 1, Random(0L))
val cash = vaultQuery.queryBy<Cash.State>().states
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.FixableDealState
import net.corda.core.contracts.*
import net.corda.core.crypto.TransactionSignature
import net.corda.core.crypto.toBase58String
import net.corda.core.flows.FlowLogic
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.node.NodeInfo
import net.corda.core.node.services.ServiceType
import net.corda.core.utilities.seconds
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.transient
import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.seconds
import net.corda.core.utilities.trace
import net.corda.core.utilities.transient
import net.corda.flows.TwoPartyDealFlow
import java.math.BigDecimal
import java.security.PublicKey
@ -52,7 +53,7 @@ object FixingFlow {
}
@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")
val fixOf = deal.nextFixingOf()!!
@ -85,9 +86,9 @@ object FixingFlow {
}
}
}
subFlow(addFixing)
val sig = subFlow(addFixing)
// 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 expectedRate: 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 {
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
@Suspendable
override fun call() {
override fun call(): TransactionSignature {
progressTracker.currentStep = progressTracker.steps[1]
val fix = subFlow(FixQueryFlow(fixOf, oracle))
progressTracker.currentStep = WORKING
@ -63,8 +63,7 @@ open class RatesFixFlow(protected val tx: TransactionBuilder,
beforeSigning(fix)
progressTracker.currentStep = SIGNING
val mtx = tx.toWireTransaction().buildFilteredTransaction(Predicate { filtering(it) })
val signature = subFlow(FixSignFlow(tx, oracle, mtx))
tx.addSignatureUnchecked(signature)
return subFlow(FixSignFlow(tx, oracle, mtx))
}
// DOCEND 2

View File

@ -6,6 +6,8 @@ import net.corda.contracts.Commodity
import net.corda.contracts.DealState
import net.corda.contracts.asset.*
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.identity.AbstractParty
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.DUMMY_NOTARY
import net.corda.testing.DUMMY_NOTARY_KEY
import java.security.KeyPair
import java.security.PublicKey
import java.time.Duration
import java.time.Instant
@ -28,17 +29,18 @@ import java.util.*
@JvmOverloads
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 me = AnonymousParty(myKey)
val transactions: List<SignedTransaction> = dealIds.map {
// 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)))
signWith(DUMMY_NOTARY_KEY)
}
return@map signInitialTransaction(dummyIssue)
val stx = signInitialTransaction(dummyIssue)
return@map addSignature(stx, notary.owningKey)
}
recordTransactions(transactions)
@ -61,6 +63,8 @@ fun ServiceHub.fillWithSomeTestLinearStates(numberToCreate: Int,
linearTimestamp: Instant = now()) : Vault<LinearState> {
val myKey: PublicKey = myInfo.legalIdentity.owningKey
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 {
// Issue a Linear state
@ -72,10 +76,9 @@ fun ServiceHub.fillWithSomeTestLinearStates(numberToCreate: Int,
linearNumber = linearNumber,
linearBoolean = linearBoolean,
linearTimestamp = linearTimestamp))
signWith(DUMMY_NOTARY_KEY)
}
return@map signInitialTransaction(dummyIssue)
return@map signInitialTransaction(dummyIssue).withAdditionalSignature(issuerKey, signatureMetadata)
}
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.
*
* @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!).
*/
fun ServiceHub.fillWithSomeTestCash(howMuch: Amount<Currency>,
issuerServices: ServiceHub = this,
outputNotary: Party = DUMMY_NOTARY,
atLeastThisManyStates: Int = 3,
atMostThisManyStates: Int = 10,
rng: Random = Random(),
ref: OpaqueBytes = OpaqueBytes(ByteArray(1, { 1 })),
ownedBy: AbstractParty? = null,
issuedBy: PartyAndReference = DUMMY_CASH_ISSUER,
issuerKey: KeyPair = DUMMY_CASH_ISSUER_KEY): Vault<Cash.State> {
issuedBy: PartyAndReference = DUMMY_CASH_ISSUER): Vault<Cash.State> {
val amounts = calculateRandomlySizedAmounts(howMuch, atLeastThisManyStates, atMostThisManyStates, rng)
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 issuance = TransactionBuilder(null as Party?)
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)
@ -132,21 +135,26 @@ fun ServiceHub.fillWithSomeTestCash(howMuch: Amount<Currency>,
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
fun ServiceHub.fillWithSomeTestCommodity(amount: Amount<Commodity>,
issuerServices: ServiceHub = this,
outputNotary: Party = DUMMY_NOTARY,
ref: OpaqueBytes = OpaqueBytes(ByteArray(1, { 1 })),
ownedBy: AbstractParty? = null,
issuedBy: PartyAndReference = DUMMY_OBLIGATION_ISSUER.ref(1),
issuerKey: KeyPair = DUMMY_OBLIGATION_ISSUER_KEY): Vault<CommodityContract.State> {
issuedBy: PartyAndReference = DUMMY_OBLIGATION_ISSUER.ref(1)): Vault<CommodityContract.State> {
val myKey: PublicKey = ownedBy?.owningKey ?: myInfo.legalIdentity.owningKey
val me = AnonymousParty(myKey)
val commodity = CommodityContract()
val issuance = TransactionBuilder(null as Party?)
commodity.generateIssue(issuance, Amount(amount.quantity, Issued(issuedBy.copy(reference = ref), amount.token)), me, outputNotary)
issuance.signWith(issuerKey)
val transaction = issuance.toSignedTransaction(true)
val transaction = issuerServices.signInitialTransaction(issuance, issuedBy.party.owningKey)
recordTransactions(transaction)
@ -181,62 +189,62 @@ fun calculateRandomlySizedAmounts(howMuch: Amount<Currency>, min: Int, max: Int,
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
states.forEach {
val consumedTx = TransactionBuilder(notary = DUMMY_NOTARY).apply {
val builder = TransactionBuilder(notary = notary).apply {
addInputState(it)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
}
val consumedTx = signInitialTransaction(builder, notary.owningKey)
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
val consumedTx = TransactionBuilder(notary = DUMMY_NOTARY).apply {
var builder = TransactionBuilder(notary = notary).apply {
addInputState(stateAndRef)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
}
val consumedTx = signInitialTransaction(builder, notary.owningKey)
recordTransactions(consumedTx)
// 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,
participants = stateAndRef.state.data.participants))
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
}
val producedTx = signInitialTransaction(builder, notary.owningKey)
recordTransactions(producedTx)
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 {
consumeAndProduce(it)
consumeAndProduce(it, notary)
}
}
fun ServiceHub.consumeDeals(dealStates: List<StateAndRef<DealState>>) = consume(dealStates)
fun ServiceHub.consumeLinearStates(linearStates: List<StateAndRef<LinearState>>) = consume(linearStates)
fun ServiceHub.evolveLinearStates(linearStates: List<StateAndRef<LinearState>>) = consumeAndProduce(linearStates)
fun ServiceHub.evolveLinearState(linearState: StateAndRef<LinearState>) : StateAndRef<LinearState> = consumeAndProduce(linearState)
fun ServiceHub.consumeDeals(dealStates: List<StateAndRef<DealState>>, notary: Party) = consume(dealStates, notary)
fun ServiceHub.consumeLinearStates(linearStates: List<StateAndRef<LinearState>>, notary: Party) = consume(linearStates, notary)
fun ServiceHub.evolveLinearStates(linearStates: List<StateAndRef<LinearState>>, notary: Party) = consumeAndProduce(linearStates, notary)
fun ServiceHub.evolveLinearState(linearState: StateAndRef<LinearState>, notary: Party) : StateAndRef<LinearState> = consumeAndProduce(linearState, notary)
@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 services = this
// A tx that spends our money.
val spendTX = TransactionBuilder(DUMMY_NOTARY).apply {
val builder = TransactionBuilder(notary).apply {
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))
}