mirror of
https://github.com/corda/corda.git
synced 2025-04-06 19:07:08 +00:00
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:
parent
907ec9ff46
commit
f0c7d7665a
@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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`` .
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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) }
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user