mirror of
https://github.com/corda/corda.git
synced 2025-04-06 19:07:08 +00:00
Code cleanup, mostly shortening long lines (#4070)
This commit is contained in:
parent
8e590cfc55
commit
6d4bdb84b9
@ -2,8 +2,6 @@ package net.corda.core.flows
|
||||
|
||||
import com.natpryce.hamkrest.and
|
||||
import com.natpryce.hamkrest.assertion.assert
|
||||
import net.corda.testing.internal.matchers.flow.willReturn
|
||||
import net.corda.testing.internal.matchers.flow.willThrow
|
||||
import net.corda.core.flows.mixins.WithFinality
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
@ -12,6 +10,8 @@ import net.corda.finance.POUNDS
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.issuedBy
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.internal.matchers.flow.willReturn
|
||||
import net.corda.testing.internal.matchers.flow.willThrow
|
||||
import net.corda.testing.node.internal.InternalMockNetwork
|
||||
import net.corda.testing.node.internal.TestStartedNode
|
||||
import net.corda.testing.node.internal.cordappsForPackages
|
||||
@ -21,7 +21,10 @@ import org.junit.Test
|
||||
class FinalityFlowTests : WithFinality {
|
||||
companion object {
|
||||
private val CHARLIE = TestIdentity(CHARLIE_NAME, 90).party
|
||||
private val classMockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages("net.corda.finance.contracts.asset","net.corda.finance.schemas"))
|
||||
private val classMockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages(
|
||||
"net.corda.finance.contracts.asset",
|
||||
"net.corda.finance.schemas"
|
||||
))
|
||||
|
||||
@JvmStatic
|
||||
@AfterClass
|
||||
@ -33,7 +36,6 @@ class FinalityFlowTests : WithFinality {
|
||||
private val aliceNode = makeNode(ALICE_NAME)
|
||||
private val bobNode = makeNode(BOB_NAME)
|
||||
|
||||
private val alice = aliceNode.info.singleIdentity()
|
||||
private val bob = bobNode.info.singleIdentity()
|
||||
private val notary = mockNet.defaultNotaryIdentity
|
||||
|
||||
@ -59,11 +61,9 @@ class FinalityFlowTests : WithFinality {
|
||||
}
|
||||
|
||||
private fun TestStartedNode.signCashTransactionWith(other: Party): SignedTransaction {
|
||||
val amount = 1000.POUNDS.issuedBy(alice.ref(0))
|
||||
val amount = 1000.POUNDS.issuedBy(info.singleIdentity().ref(0))
|
||||
val builder = TransactionBuilder(notary)
|
||||
Cash().generateIssue(builder, amount, other, notary)
|
||||
|
||||
return services.signInitialTransaction(builder)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -55,13 +55,13 @@ internal class CreateRefState : FlowLogic<SignedTransaction>() {
|
||||
}
|
||||
|
||||
// A flow to update a specific reference state.
|
||||
internal class UpdateRefState(private val stateAndRef: StateAndRef<ContractState>) : FlowLogic<SignedTransaction>() {
|
||||
internal class UpdateRefState(private val stateAndRef: StateAndRef<RefState.State>) : FlowLogic<SignedTransaction>() {
|
||||
@Suspendable
|
||||
override fun call(): SignedTransaction {
|
||||
val notary = serviceHub.networkMapCache.notaryIdentities.first()
|
||||
val stx = serviceHub.signInitialTransaction(TransactionBuilder(notary = notary).apply {
|
||||
addInputState(stateAndRef)
|
||||
addOutputState((stateAndRef.state.data as RefState.State).update(), RefState.CONTRACT_ID)
|
||||
addOutputState(stateAndRef.state.data.update(), RefState.CONTRACT_ID)
|
||||
addCommand(RefState.Update(), listOf(ourIdentity.owningKey))
|
||||
})
|
||||
return subFlow(FinalityFlow(stx))
|
||||
@ -160,5 +160,4 @@ class WithReferencedStatesFlowTests {
|
||||
val result = useRefTx.getOrThrow()
|
||||
assertEquals(updatedRefState.ref, result.tx.references.single())
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,7 +15,8 @@ Unreleased
|
||||
|
||||
* New overload for ``CordaRPCClient.start()`` method allowing to specify target legal identity to use for RPC call.
|
||||
|
||||
* Case insensitive vault queries can be specified via a boolean on applicable SQL criteria builder operators. By default queries will be case sensitive.
|
||||
* Case insensitive vault queries can be specified via a boolean on applicable SQL criteria builder operators. By default
|
||||
queries will be case sensitive.
|
||||
|
||||
* Getter added to ``CordaRPCOps`` for the node's network parameters.
|
||||
|
||||
@ -32,7 +33,8 @@ Unreleased
|
||||
* "app", "rpc", "p2p" and "unknown" are no longer allowed as uploader values when importing attachments. These are used
|
||||
internally in security sensitive code.
|
||||
|
||||
* Introduced ``TestCorDapp`` and utilities to support asymmetric setups for nodes through ``DriverDSL``, ``MockNetwork`` and ``MockServices``.
|
||||
* Introduced ``TestCorDapp`` and utilities to support asymmetric setups for nodes through ``DriverDSL``, ``MockNetwork``
|
||||
and ``MockServices``.
|
||||
|
||||
* Change type of the ``checkpoint_value`` column. Please check the upgrade-notes on how to update your database.
|
||||
|
||||
@ -46,7 +48,8 @@ Unreleased
|
||||
rather than IllegalStateException.
|
||||
|
||||
* The Corda JPA entities no longer implement java.io.Serializable, as this was causing persistence errors in obscure cases.
|
||||
Java serialization is disabled globally in the node, but in the unlikely event you were relying on these types being Java serializable please contact us.
|
||||
Java serialization is disabled globally in the node, but in the unlikely event you were relying on these types being Java
|
||||
serializable please contact us.
|
||||
|
||||
* Remove all references to the out-of-process transaction verification.
|
||||
|
||||
@ -104,7 +107,8 @@ Unreleased
|
||||
* The node's configuration is only printed on startup if ``devMode`` is ``true``, avoiding the risk of printing passwords
|
||||
in a production setup.
|
||||
|
||||
* ``NodeStartup`` will now only print node's configuration if ``devMode`` is ``true``, avoiding the risk of printing passwords in a production setup.
|
||||
* ``NodeStartup`` will now only print node's configuration if ``devMode`` is ``true``, avoiding the risk of printing passwords
|
||||
in a production setup.
|
||||
|
||||
* SLF4J's MDC will now only be printed to the console if not empty. No more log lines ending with "{}".
|
||||
|
||||
@ -169,13 +173,15 @@ Unreleased
|
||||
* Added public support for creating ``CordaRPCClient`` using SSL. For this to work the node needs to provide client applications
|
||||
a certificate to be added to a truststore. See :doc:`tutorial-clientrpc-api`
|
||||
|
||||
* The node RPC broker opens 2 endpoints that are configured with ``address`` and ``adminAddress``. RPC Clients would connect to the address, while the node will connect
|
||||
to the adminAddress. Previously if ssl was enabled for RPC the ``adminAddress`` was equal to ``address``.
|
||||
*The node RPC broker opens 2 endpoints that are configured with ``address`` and ``adminAddress``. RPC Clients would connect
|
||||
to the address, while the node will connect to the adminAddress. Previously if ssl was enabled for RPC the ``adminAddress``
|
||||
was equal to ``address``.
|
||||
|
||||
* Upgraded H2 to v1.4.197
|
||||
|
||||
* Shell (embedded available only in dev mode or via SSH) connects to the node via RPC instead of using the ``CordaRPCOps`` object directly.
|
||||
To enable RPC connectivity ensure node’s ``rpcSettings.address`` and ``rpcSettings.adminAddress`` settings are present.
|
||||
* Shell (embedded available only in dev mode or via SSH) connects to the node via RPC instead of using the ``CordaRPCOps``
|
||||
object directly. To enable RPC connectivity ensure node’s ``rpcSettings.address`` and ``rpcSettings.adminAddress`` settings
|
||||
are present.
|
||||
|
||||
* Changes to the network bootstrapper:
|
||||
|
||||
@ -183,7 +189,8 @@ Unreleased
|
||||
whitelist.
|
||||
* The CorDapp jars are also copied to each nodes' ``cordapps`` directory.
|
||||
|
||||
* Errors thrown by a Corda node will now reported to a calling RPC client with attention to serialization and obfuscation of internal data.
|
||||
* Errors thrown by a Corda node will now reported to a calling RPC client with attention to serialization and obfuscation
|
||||
of internal data.
|
||||
|
||||
* Serializing an inner class (non-static nested class in Java, inner class in Kotlin) will be rejected explicitly by the serialization
|
||||
framework. Prior to this change it didn't work, but the error thrown was opaque (complaining about too few arguments
|
||||
@ -191,13 +198,15 @@ Unreleased
|
||||
reference to the outer class) as per the Java documentation `here <https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html>`_
|
||||
we are disallowing this as the paradigm in general makes little sense for contract states.
|
||||
|
||||
* Node can be shut down abruptly by ``shutdown`` function in ``CordaRPCOps`` or gracefully (draining flows first) through ``gracefulShutdown`` command from shell.
|
||||
* Node can be shut down abruptly by ``shutdown`` function in ``CordaRPCOps`` or gracefully (draining flows first) through
|
||||
``gracefulShutdown`` command from shell.
|
||||
|
||||
* API change: ``net.corda.core.schemas.PersistentStateRef`` fields (index and txId) are now non-nullable.
|
||||
The fields were always effectively non-nullable - values were set from non-nullable fields of other objects.
|
||||
The class is used as database Primary Key columns of other entities and databases already impose those columns as non-nullable
|
||||
(even if JPA annotation nullable=false was absent).
|
||||
In case your Cordapps use this entity class to persist data in own custom tables as non Primary Key columns refer to :doc:`upgrade-notes` for upgrade instructions.
|
||||
In case your Cordapps use this entity class to persist data in own custom tables as non Primary Key columns refer to
|
||||
:doc:`upgrade-notes` for upgrade instructions.
|
||||
|
||||
* Adding a public method to check if a public key satisfies Corda recommended algorithm specs, `Crypto.validatePublicKey(java.security.PublicKey)`.
|
||||
For instance, this method will check if an ECC key lies on a valid curve or if an RSA key is >= 2048bits. This might
|
||||
@ -248,9 +257,10 @@ Version 3.0
|
||||
* Per CorDapp configuration is now exposed. ``CordappContext`` now exposes a ``CordappConfig`` object that is populated
|
||||
at CorDapp context creation time from a file source during runtime.
|
||||
|
||||
* Introduced Flow Draining mode, in which a node continues executing existing flows, but does not start new. This is to support graceful node shutdown/restarts.
|
||||
In particular, when this mode is on, new flows through RPC will be rejected, scheduled flows will be ignored, and initial session messages will not be consumed.
|
||||
This will ensure that the number of checkpoints will strictly diminish with time, allowing for a clean shutdown.
|
||||
* Introduced Flow Draining mode, in which a node continues executing existing flows, but does not start new. This is to
|
||||
support graceful node shutdown/restarts. In particular, when this mode is on, new flows through RPC will be rejected,
|
||||
scheduled flows will be ignored, and initial session messages will not be consumed. This will ensure that the number of
|
||||
checkpoints will strictly diminish with time, allowing for a clean shutdown.
|
||||
|
||||
* Make the serialisation finger-printer a pluggable entity rather than hard wiring into the factory
|
||||
|
||||
@ -261,17 +271,19 @@ Version 3.0
|
||||
* Refactored ``NodeConfiguration`` to expose ``NodeRpcOptions`` (using top-level "rpcAddress" property still works with warning).
|
||||
* Modified ``CordaRPCClient`` constructor to take a ``SSLConfiguration?`` additional parameter, defaulted to ``null``.
|
||||
|
||||
* Introduced ``CertificateChainCheckPolicy.UsernameMustMatchCommonName`` sub-type, allowing customers to optionally enforce username == CN condition on RPC SSL certificates.
|
||||
* Introduced ``CertificateChainCheckPolicy.UsernameMustMatchCommonName`` sub-type, allowing customers to optionally enforce
|
||||
username == CN condition on RPC SSL certificates.
|
||||
|
||||
* Modified ``DriverDSL`` and sub-types to allow specifying RPC settings for the Node.
|
||||
|
||||
* Modified the ``DriverDSL`` to start Cordformation nodes allowing automatic generation of "rpcSettings.adminAddress" in case "rcpSettings.useSsl" is ``false`` (the default).
|
||||
* Modified the ``DriverDSL`` to start Cordformation nodes allowing automatic generation of "rpcSettings.adminAddress" in case
|
||||
"rcpSettings.useSsl" is ``false`` (the default).
|
||||
|
||||
* Introduced ``UnsafeCertificatesFactory`` allowing programmatic generation of X509 certificates for test purposes.
|
||||
|
||||
* JPA Mapping annotations for States extending ``CommonSchemaV1.LinearState`` and ``CommonSchemaV1.FungibleState`` on the
|
||||
`participants` collection need to be moved to the actual class. This allows to properly specify the unique table name per a collection.
|
||||
See: DummyDealStateSchemaV1.PersistentDummyDealState
|
||||
`participants` collection need to be moved to the actual class. This allows to properly specify the unique table name per
|
||||
a collection. See: DummyDealStateSchemaV1.PersistentDummyDealState
|
||||
|
||||
* X.509 certificates now have an extension that specifies the Corda role the certificate is used for, and the role
|
||||
hierarchy is now enforced in the validation code. See ``net.corda.core.internal.CertRole`` for the current implementation
|
||||
@ -556,7 +568,9 @@ Release 1.0
|
||||
* Vault query soft locking enhancements and deprecations
|
||||
|
||||
* removed original ``VaultService`` ``softLockedStates`` query mechanism.
|
||||
* introduced improved ``SoftLockingCondition`` filterable attribute in ``VaultQueryCriteria`` to enable specification of different soft locking retrieval behaviours (exclusive of soft locked states, soft locked states only, specified by set of lock ids)
|
||||
* introduced improved ``SoftLockingCondition`` filterable attribute in ``VaultQueryCriteria`` to enable specification of
|
||||
different soft locking retrieval behaviours (exclusive of soft locked states, soft locked states only, specified by set
|
||||
of lock ids)
|
||||
|
||||
* Trader demo now issues cash and commercial paper directly from the bank node, rather than the seller node self-issuing
|
||||
commercial paper but labelling it as if issued by the bank.
|
||||
@ -586,7 +600,8 @@ Release 1.0
|
||||
This may require adjusting imports of Cash flow references and also of ``StartFlow`` permission in ``gradle.build`` files.
|
||||
|
||||
* Removed the concept of relevancy from ``LinearState``. The ``ContractState``'s relevancy to the vault can be determined
|
||||
by the flow context, the vault will process any transaction from a flow which is not derived from transaction resolution verification.
|
||||
by the flow context, the vault will process any transaction from a flow which is not derived from transaction resolution
|
||||
verification.
|
||||
|
||||
* Removed the tolerance attribute from ``TimeWindowChecker`` and thus, there is no extra tolerance on the notary side anymore.
|
||||
|
||||
@ -769,9 +784,11 @@ Milestone 14
|
||||
|
||||
* Pagination simplification. Pagination continues to be optional, with following changes:
|
||||
|
||||
- If no PageSpecification provided then a maximum of MAX_PAGE_SIZE (200) results will be returned, otherwise we fail-fast with a ``VaultQueryException`` to alert the API user to the need to specify a PageSpecification.
|
||||
Internally, we no longer need to calculate a results count (thus eliminating an expensive SQL query) unless a PageSpecification is supplied (note: that a value of -1 is returned for total_results in this scenario).
|
||||
Internally, we now use the AggregateFunction capability to perform the count.
|
||||
- If no PageSpecification provided then a maximum of MAX_PAGE_SIZE (200) results will be returned, otherwise we fail-fast
|
||||
with a ``VaultQueryException`` to alert the API user to the need to specify a PageSpecification. Internally, we no
|
||||
longer need to calculate a results count (thus eliminating an expensive SQL query) unless a PageSpecification is
|
||||
supplied (note: that a value of -1 is returned for total_results in this scenario). Internally, we now use the
|
||||
AggregateFunction capability to perform the count.
|
||||
- Paging now starts from 1 (was previously 0).
|
||||
|
||||
* Additional Sort criteria: by StateRef (or constituents: txId, index)
|
||||
|
@ -28,11 +28,11 @@ import java.security.GeneralSecurityException;
|
||||
import java.security.PublicKey;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.util.Collections.*;
|
||||
import static net.corda.core.contracts.ContractsDSL.requireThat;
|
||||
import static net.corda.core.crypto.Crypto.generateKeyPair;
|
||||
|
||||
@ -528,7 +528,7 @@ public class FlowCookbook {
|
||||
// other required signers using ``CollectSignaturesFlow``.
|
||||
// The responder flow will need to call ``SignTransactionFlow``.
|
||||
// DOCSTART 15
|
||||
SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(twiceSignedTx, Collections.emptySet(), SIGS_GATHERING.childProgressTracker()));
|
||||
SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(twiceSignedTx, emptySet(), SIGS_GATHERING.childProgressTracker()));
|
||||
// DOCEND 15
|
||||
|
||||
/*------------------------
|
||||
@ -557,7 +557,7 @@ public class FlowCookbook {
|
||||
// ``Arrays.asList(counterpartyPubKey)`` instead of
|
||||
// ``Collections.singletonList(counterpartyPubKey)``.
|
||||
// DOCSTART 54
|
||||
onceSignedTx.verifySignaturesExcept(Collections.singletonList(counterpartyPubKey));
|
||||
onceSignedTx.verifySignaturesExcept(singletonList(counterpartyPubKey));
|
||||
// DOCEND 54
|
||||
|
||||
// We can also choose to only check the signatures that are
|
||||
@ -583,7 +583,7 @@ public class FlowCookbook {
|
||||
// We can also choose to send it to additional parties who aren't one
|
||||
// of the state's participants.
|
||||
// DOCSTART 10
|
||||
Set<Party> additionalParties = Collections.singleton(regulator);
|
||||
Set<Party> additionalParties = singleton(regulator);
|
||||
SignedTransaction notarisedTx2 = subFlow(new FinalityFlow(fullySignedTx, additionalParties, FINALISATION.childProgressTracker()));
|
||||
// DOCEND 10
|
||||
|
||||
|
@ -15,7 +15,7 @@ import net.corda.core.utilities.ProgressTracker;
|
||||
|
||||
import static com.template.TemplateContract.TEMPLATE_CONTRACT_ID;
|
||||
|
||||
// Replace TemplateFlow's definition with:
|
||||
// Replace Initiator's definition with:
|
||||
@InitiatingFlow
|
||||
@StartableByRPC
|
||||
public class IOUFlow extends FlowLogic<Void> {
|
||||
@ -44,7 +44,7 @@ public class IOUFlow extends FlowLogic<Void> {
|
||||
@Override
|
||||
public Void call() throws FlowException {
|
||||
// We retrieve the notary identity from the network map.
|
||||
final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
|
||||
Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
|
||||
|
||||
// We create the transaction components.
|
||||
IOUState outputState = new IOUState(iouValue, getOurIdentity(), otherParty);
|
||||
@ -52,12 +52,12 @@ public class IOUFlow extends FlowLogic<Void> {
|
||||
Command cmd = new Command<>(cmdType, getOurIdentity().getOwningKey());
|
||||
|
||||
// We create a transaction builder and add the components.
|
||||
final TransactionBuilder txBuilder = new TransactionBuilder(notary)
|
||||
TransactionBuilder txBuilder = new TransactionBuilder(notary)
|
||||
.addOutputState(outputState, TEMPLATE_CONTRACT_ID)
|
||||
.addCommand(cmd);
|
||||
|
||||
// Signing the transaction.
|
||||
final SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
|
||||
SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
|
||||
|
||||
// Finalising the transaction.
|
||||
subFlow(new FinalityFlow(signedTx));
|
||||
@ -65,4 +65,4 @@ public class IOUFlow extends FlowLogic<Void> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// DOCEND 01
|
||||
// DOCEND 01
|
||||
|
@ -43,11 +43,11 @@ public class IOUFlow extends FlowLogic<Void> {
|
||||
@Override
|
||||
public Void call() throws FlowException {
|
||||
// We retrieve the notary identity from the network map.
|
||||
final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
|
||||
Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
|
||||
|
||||
// DOCSTART 02
|
||||
// We create a transaction builder.
|
||||
final TransactionBuilder txBuilder = new TransactionBuilder();
|
||||
TransactionBuilder txBuilder = new TransactionBuilder();
|
||||
txBuilder.setNotary(notary);
|
||||
|
||||
// We create the transaction components.
|
||||
@ -63,7 +63,7 @@ public class IOUFlow extends FlowLogic<Void> {
|
||||
txBuilder.verify(getServiceHub());
|
||||
|
||||
// Signing the transaction.
|
||||
final SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
|
||||
SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
|
||||
|
||||
// Creating a session with the other party.
|
||||
FlowSession otherPartySession = initiateFlow(otherParty);
|
||||
|
@ -18,7 +18,7 @@ import net.corda.core.utilities.ProgressTracker
|
||||
|
||||
import com.template.TemplateContract.TEMPLATE_CONTRACT_ID
|
||||
|
||||
// Replace TemplateFlow's definition with:
|
||||
// Replace Initiator's definition with:
|
||||
@InitiatingFlow
|
||||
@StartableByRPC
|
||||
class IOUFlow(val iouValue: Int,
|
||||
|
@ -14,7 +14,6 @@ import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
|
||||
// DOCEND 01
|
||||
|
||||
@InitiatingFlow
|
||||
|
@ -1,4 +1,8 @@
|
||||
.. highlight:: kotlin
|
||||
.. raw:: html
|
||||
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/codesets.js"></script>
|
||||
|
||||
Using attachments
|
||||
=================
|
||||
|
@ -1,10 +1,8 @@
|
||||
package net.corda.node.modes.draining
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.testMessage.MESSAGE_CONTRACT_PROGRAM_ID
|
||||
import net.corda.testMessage.Message
|
||||
import net.corda.testMessage.MessageContract
|
||||
import net.corda.testMessage.MessageState
|
||||
import net.corda.RpcInfo
|
||||
import net.corda.client.rpc.CordaRPCClient
|
||||
import net.corda.core.contracts.Command
|
||||
import net.corda.core.contracts.StateAndContract
|
||||
import net.corda.core.flows.*
|
||||
@ -15,9 +13,11 @@ import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.RpcInfo
|
||||
import net.corda.client.rpc.CordaRPCClient
|
||||
import net.corda.node.services.Permissions.Companion.all
|
||||
import net.corda.testMessage.MESSAGE_CONTRACT_PROGRAM_ID
|
||||
import net.corda.testMessage.Message
|
||||
import net.corda.testMessage.MessageContract
|
||||
import net.corda.testMessage.MessageState
|
||||
import net.corda.testing.core.ALICE_NAME
|
||||
import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.singleIdentity
|
||||
@ -53,7 +53,11 @@ class FlowsDrainingModeContentionTest {
|
||||
@Test
|
||||
fun `draining mode does not deadlock with acks between 2 nodes`() {
|
||||
val message = "Ground control to Major Tom"
|
||||
driver(DriverParameters(startNodesInProcess = true, portAllocation = portAllocation, extraCordappPackagesToScan = listOf(MessageState::class.packageName))) {
|
||||
driver(DriverParameters(
|
||||
startNodesInProcess = true,
|
||||
portAllocation = portAllocation,
|
||||
extraCordappPackagesToScan = listOf(MessageState::class.packageName)
|
||||
)) {
|
||||
val nodeA = startNode(providedName = ALICE_NAME, rpcUsers = users).getOrThrow()
|
||||
val nodeB = startNode(providedName = BOB_NAME, rpcUsers = users).getOrThrow()
|
||||
|
||||
@ -70,11 +74,12 @@ class FlowsDrainingModeContentionTest {
|
||||
|
||||
@StartableByRPC
|
||||
@InitiatingFlow
|
||||
class ProposeTransactionAndWaitForCommit(private val data: String, private val myRpcInfo: RpcInfo, private val counterParty: Party, private val notary: Party) : FlowLogic<SignedTransaction>() {
|
||||
|
||||
class ProposeTransactionAndWaitForCommit(private val data: String,
|
||||
private val myRpcInfo: RpcInfo,
|
||||
private val counterParty: Party,
|
||||
private val notary: Party) : FlowLogic<SignedTransaction>() {
|
||||
@Suspendable
|
||||
override fun call(): SignedTransaction {
|
||||
|
||||
val session = initiateFlow(counterParty)
|
||||
val messageState = MessageState(message = Message(data), by = ourIdentity)
|
||||
val command = Command(MessageContract.Commands.Send(), messageState.participants.map { it.owningKey })
|
||||
@ -91,10 +96,8 @@ class ProposeTransactionAndWaitForCommit(private val data: String, private val m
|
||||
|
||||
@InitiatedBy(ProposeTransactionAndWaitForCommit::class)
|
||||
class SignTransactionTriggerDrainingModeAndFinality(private val session: FlowSession) : FlowLogic<Unit>() {
|
||||
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
|
||||
val tx = subFlow(ReceiveTransactionFlow(session))
|
||||
val signedTx = serviceHub.addSignature(tx)
|
||||
val initiatingRpcInfo = session.receive<RpcInfo>().unwrap { it }
|
||||
@ -105,9 +108,8 @@ class SignTransactionTriggerDrainingModeAndFinality(private val session: FlowSes
|
||||
}
|
||||
|
||||
private fun triggerDrainingModeForInitiatingNode(initiatingRpcInfo: RpcInfo) {
|
||||
|
||||
CordaRPCClient(initiatingRpcInfo.address).start(initiatingRpcInfo.username, initiatingRpcInfo.password).use {
|
||||
it.proxy.setFlowsDrainingModeEnabled(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,14 @@ import kotlin.test.assertEquals
|
||||
|
||||
class ScheduledFlowIntegrationTests {
|
||||
@StartableByRPC
|
||||
class InsertInitialStateFlow(private val destination: Party, private val notary: Party, private val identity: Int = 1, private val scheduledFor: Instant? = null) : FlowLogic<Unit>() {
|
||||
class InsertInitialStateFlow(private val destination: Party,
|
||||
private val notary: Party,
|
||||
private val identity: Int = 1,
|
||||
private val scheduledFor: Instant? = null) : FlowLogic<Unit>() {
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
val scheduledState = ScheduledState(scheduledFor
|
||||
?: serviceHub.clock.instant(), ourIdentity, destination, identity.toString())
|
||||
val creationTime = scheduledFor ?: serviceHub.clock.instant()
|
||||
val scheduledState = ScheduledState(creationTime, ourIdentity, destination, identity.toString())
|
||||
val builder = TransactionBuilder(notary)
|
||||
.addOutputState(scheduledState, DummyContract.PROGRAM_ID)
|
||||
.addCommand(dummyCommand(ourIdentity.owningKey))
|
||||
@ -90,8 +93,20 @@ class ScheduledFlowIntegrationTests {
|
||||
val scheduledFor = Instant.now().plusSeconds(10)
|
||||
val initialiseFutures = mutableListOf<CordaFuture<*>>()
|
||||
for (i in 0 until N) {
|
||||
initialiseFutures.add(aliceClient.proxy.startFlow(::InsertInitialStateFlow, bob.nodeInfo.legalIdentities.first(), defaultNotaryIdentity, i, scheduledFor).returnValue)
|
||||
initialiseFutures.add(bobClient.proxy.startFlow(::InsertInitialStateFlow, alice.nodeInfo.legalIdentities.first(), defaultNotaryIdentity, i + 100, scheduledFor).returnValue)
|
||||
initialiseFutures.add(aliceClient.proxy.startFlow(
|
||||
::InsertInitialStateFlow,
|
||||
bob.nodeInfo.legalIdentities.first(),
|
||||
defaultNotaryIdentity,
|
||||
i,
|
||||
scheduledFor
|
||||
).returnValue)
|
||||
initialiseFutures.add(bobClient.proxy.startFlow(
|
||||
::InsertInitialStateFlow,
|
||||
alice.nodeInfo.legalIdentities.first(),
|
||||
defaultNotaryIdentity,
|
||||
i + 100,
|
||||
scheduledFor
|
||||
).returnValue)
|
||||
}
|
||||
initialiseFutures.getOrThrowAll()
|
||||
|
||||
|
@ -46,12 +46,12 @@ class SendMessageFlow(private val message: Message, private val notary: Party, p
|
||||
|
||||
progressTracker.currentStep = FINALISING_TRANSACTION
|
||||
|
||||
if (reciepent != null) {
|
||||
return if (reciepent != null) {
|
||||
val session = initiateFlow(reciepent)
|
||||
subFlow(SendTransactionFlow(session, signedTx))
|
||||
return subFlow(FinalityFlow(signedTx, setOf(reciepent), FINALISING_TRANSACTION.childProgressTracker()))
|
||||
subFlow(FinalityFlow(signedTx, setOf(reciepent), FINALISING_TRANSACTION.childProgressTracker()))
|
||||
} else {
|
||||
return subFlow(FinalityFlow(signedTx, FINALISING_TRANSACTION.childProgressTracker()))
|
||||
subFlow(FinalityFlow(signedTx, FINALISING_TRANSACTION.childProgressTracker()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -59,10 +59,9 @@ class SendMessageFlow(private val message: Message, private val notary: Party, p
|
||||
|
||||
@InitiatedBy(SendMessageFlow::class)
|
||||
class Record(private val session: FlowSession) : FlowLogic<Unit>() {
|
||||
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
val tx = subFlow(ReceiveTransactionFlow(session, statesToRecord = StatesToRecord.ALL_VISIBLE))
|
||||
serviceHub.addSignature(tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import net.corda.core.flows.FlowLogicRefFactory
|
||||
import net.corda.core.flows.SchedulableFlow
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.core.ALICE_NAME
|
||||
import net.corda.testing.core.BOB_NAME
|
||||
@ -28,6 +28,9 @@ import kotlin.reflect.jvm.jvmName
|
||||
import kotlin.test.fail
|
||||
|
||||
class ScheduledFlowsDrainingModeTest {
|
||||
companion object {
|
||||
private val logger = contextLogger()
|
||||
}
|
||||
|
||||
private lateinit var mockNet: InternalMockNetwork
|
||||
private lateinit var aliceNode: TestStartedNode
|
||||
@ -38,10 +41,6 @@ class ScheduledFlowsDrainingModeTest {
|
||||
|
||||
private var executor: ScheduledExecutorService? = null
|
||||
|
||||
companion object {
|
||||
private val logger = loggerFor<ScheduledFlowsDrainingModeTest>()
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages("net.corda.testing.contracts"), threadPerNode = true)
|
||||
@ -61,7 +60,6 @@ class ScheduledFlowsDrainingModeTest {
|
||||
|
||||
@Test
|
||||
fun `flows draining mode ignores scheduled flows until unset`() {
|
||||
|
||||
val latch = CountDownLatch(1)
|
||||
var shouldFail = true
|
||||
|
||||
@ -73,7 +71,8 @@ class ScheduledFlowsDrainingModeTest {
|
||||
.map { update -> update.produced.single().state.data as ScheduledState }
|
||||
|
||||
scheduledStates.filter { state -> !state.processed }.doOnNext { _ ->
|
||||
// this is needed because there is a delay between the moment a SchedulableState gets in the Vault and the first time nextScheduledActivity is called
|
||||
// This is needed because there is a delay between the moment a SchedulableState gets in the Vault and the
|
||||
// first time nextScheduledActivity is called
|
||||
executor!!.schedule({
|
||||
logger.info("Disabling flows draining mode")
|
||||
shouldFail = false
|
||||
@ -96,8 +95,11 @@ class ScheduledFlowsDrainingModeTest {
|
||||
latch.await()
|
||||
}
|
||||
|
||||
data class ScheduledState(private val creationTime: Instant, val source: Party, val destination: Party, val processed: Boolean = false, override val linearId: UniqueIdentifier = UniqueIdentifier()) : SchedulableState, LinearState {
|
||||
|
||||
data class ScheduledState(private val creationTime: Instant,
|
||||
val source: Party,
|
||||
val destination: Party,
|
||||
val processed: Boolean = false,
|
||||
override val linearId: UniqueIdentifier = UniqueIdentifier()) : SchedulableState, LinearState {
|
||||
override fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity? {
|
||||
return if (!processed) {
|
||||
val logicRef = flowLogicRefFactory.create(ScheduledFlow::class.jvmName, thisStateRef)
|
||||
@ -111,12 +113,12 @@ class ScheduledFlowsDrainingModeTest {
|
||||
}
|
||||
|
||||
class InsertInitialStateFlow(private val destination: Party, private val notary: Party) : FlowLogic<Unit>() {
|
||||
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
|
||||
val scheduledState = ScheduledState(serviceHub.clock.instant(), ourIdentity, destination)
|
||||
val builder = TransactionBuilder(notary).addOutputState(scheduledState, DummyContract.PROGRAM_ID).addCommand(dummyCommand(ourIdentity.owningKey))
|
||||
val builder = TransactionBuilder(notary)
|
||||
.addOutputState(scheduledState, DummyContract.PROGRAM_ID)
|
||||
.addCommand(dummyCommand(ourIdentity.owningKey))
|
||||
val tx = serviceHub.signInitialTransaction(builder)
|
||||
subFlow(FinalityFlow(tx))
|
||||
}
|
||||
@ -124,10 +126,8 @@ class ScheduledFlowsDrainingModeTest {
|
||||
|
||||
@SchedulableFlow
|
||||
class ScheduledFlow(private val stateRef: StateRef) : FlowLogic<Unit>() {
|
||||
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
|
||||
val state = serviceHub.toStateAndRef<ScheduledState>(stateRef)
|
||||
val scheduledState = state.state.data
|
||||
// Only run flow over states originating on this node
|
||||
@ -137,9 +137,12 @@ class ScheduledFlowsDrainingModeTest {
|
||||
require(!scheduledState.processed) { "State should not have been previously processed" }
|
||||
val notary = state.state.notary
|
||||
val newStateOutput = scheduledState.copy(processed = true)
|
||||
val builder = TransactionBuilder(notary).addInputState(state).addOutputState(newStateOutput, DummyContract.PROGRAM_ID).addCommand(dummyCommand(ourIdentity.owningKey))
|
||||
val builder = TransactionBuilder(notary)
|
||||
.addInputState(state)
|
||||
.addOutputState(newStateOutput, DummyContract.PROGRAM_ID)
|
||||
.addCommand(dummyCommand(ourIdentity.owningKey))
|
||||
val tx = serviceHub.signInitialTransaction(builder)
|
||||
subFlow(FinalityFlow(tx, setOf(scheduledState.destination)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import org.junit.After
|
||||
import org.junit.Test
|
||||
|
||||
class FinalityHandlerTest {
|
||||
private lateinit var mockNet: InternalMockNetwork
|
||||
private val mockNet = InternalMockNetwork()
|
||||
|
||||
@After
|
||||
fun cleanUp() {
|
||||
@ -32,8 +32,6 @@ class FinalityHandlerTest {
|
||||
fun `sent to flow hospital on error and attempted retry on node restart`() {
|
||||
// Setup a network where only Alice has the finance CorDapp and it sends a cash tx to Bob who doesn't have the
|
||||
// CorDapp. Bob's FinalityHandler will error when validating the tx.
|
||||
mockNet = InternalMockNetwork()
|
||||
|
||||
val alice = mockNet.createNode(InternalMockNodeParameters(legalName = ALICE_NAME, additionalCordapps = setOf(FINANCE_CORDAPP)))
|
||||
|
||||
var bob = mockNet.createNode(InternalMockNodeParameters(legalName = BOB_NAME))
|
||||
@ -82,8 +80,6 @@ class FinalityHandlerTest {
|
||||
}
|
||||
|
||||
private fun TestStartedNode.getTransaction(id: SecureHash): SignedTransaction? {
|
||||
return database.transaction {
|
||||
services.validatedTransactions.getTransaction(id)
|
||||
}
|
||||
return services.validatedTransactions.getTransaction(id)
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,11 @@ import rx.schedulers.Schedulers
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
class ServiceHubConcurrentUsageTest {
|
||||
|
||||
private val mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages("net.corda.finance.schemas", "net.corda.node.services.vault.VaultQueryExceptionsTests", Cash::class.packageName))
|
||||
private val mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages(
|
||||
"net.corda.finance.schemas",
|
||||
"net.corda.node.services.vault.VaultQueryExceptionsTests",
|
||||
Cash::class.packageName
|
||||
))
|
||||
|
||||
@After
|
||||
fun stopNodes() {
|
||||
@ -34,7 +37,6 @@ class ServiceHubConcurrentUsageTest {
|
||||
|
||||
@Test
|
||||
fun `operations requiring a transaction work from another thread`() {
|
||||
|
||||
val latch = CountDownLatch(1)
|
||||
var successful = false
|
||||
val initiatingFlow = TestFlow(mockNet.defaultNotaryIdentity)
|
||||
@ -57,10 +59,8 @@ class ServiceHubConcurrentUsageTest {
|
||||
}
|
||||
|
||||
class TestFlow(private val notary: Party) : FlowLogic<SignedTransaction>() {
|
||||
|
||||
@Suspendable
|
||||
override fun call(): SignedTransaction {
|
||||
|
||||
val builder = TransactionBuilder(notary)
|
||||
val issuer = ourIdentity.ref(OpaqueBytes.of(0))
|
||||
Cash().generateIssue(builder, 10.DOLLARS.issuedBy(issuer), ourIdentity, notary)
|
||||
@ -68,4 +68,4 @@ class ServiceHubConcurrentUsageTest {
|
||||
return subFlow(FinalityFlow(stx))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ import kotlin.test.assertEquals
|
||||
|
||||
class ScheduledFlowTests {
|
||||
companion object {
|
||||
const val PAGE_SIZE = 20
|
||||
val SORTING = Sort(listOf(Sort.SortColumn(SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF_TXN_ID), Sort.Direction.DESC)))
|
||||
}
|
||||
|
||||
@ -168,6 +167,7 @@ class ScheduledFlowTests {
|
||||
assertTrue("Expect all states have run the scheduled task", statesFromB.all { it.state.data.processed })
|
||||
}
|
||||
|
||||
private fun queryStates(vaultService: VaultService): List<StateAndRef<ScheduledState>> =
|
||||
vaultService.queryBy<ScheduledState>(VaultQueryCriteria(), sorting = SORTING).states
|
||||
private fun queryStates(vaultService: VaultService): List<StateAndRef<ScheduledState>> {
|
||||
return vaultService.queryBy<ScheduledState>(VaultQueryCriteria(), sorting = SORTING).states
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class NodePair(private val mockNet: InternalMockNetwork) {
|
||||
|
||||
@InitiatingFlow
|
||||
abstract class AbstractClientLogic<out T>(nodePair: NodePair) : FlowLogic<T>() {
|
||||
protected val server = nodePair.server.info.singleIdentity()
|
||||
private val server = nodePair.server.info.singleIdentity()
|
||||
protected abstract fun callImpl(): T
|
||||
@Suspendable
|
||||
override fun call() = callImpl().also {
|
||||
@ -82,9 +82,12 @@ class VaultSoftLockManagerTest {
|
||||
private val mockVault = rigorousMock<VaultServiceInternal>().also {
|
||||
doNothing().whenever(it).softLockRelease(any(), anyOrNull())
|
||||
}
|
||||
|
||||
private val mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages(ContractImpl::class.packageName), defaultFactory = { args ->
|
||||
object : InternalMockNetwork.MockNode(args) {
|
||||
override fun makeVaultService(keyManagementService: KeyManagementService, services: ServicesForResolution, database: CordaPersistence): VaultServiceInternal {
|
||||
override fun makeVaultService(keyManagementService: KeyManagementService,
|
||||
services: ServicesForResolution,
|
||||
database: CordaPersistence): VaultServiceInternal {
|
||||
val node = this
|
||||
val realVault = super.makeVaultService(keyManagementService, services, database)
|
||||
return object : VaultServiceInternal by realVault {
|
||||
@ -97,13 +100,11 @@ class VaultSoftLockManagerTest {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
private val nodePair = NodePair(mockNet)
|
||||
@After
|
||||
fun tearDown() {
|
||||
mockNet.stopNodes()
|
||||
}
|
||||
|
||||
object CommandDataImpl : CommandData
|
||||
|
||||
class ClientLogic(nodePair: NodePair, val state: ContractState) : NodePair.AbstractClientLogic<List<ContractState>>(nodePair) {
|
||||
override fun callImpl() = run {
|
||||
subFlow(FinalityFlow(serviceHub.signInitialTransaction(TransactionBuilder(notary = ourIdentity).apply {
|
||||
@ -151,6 +152,11 @@ class VaultSoftLockManagerTest {
|
||||
verifyNoMoreInteractions(mockVault)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
mockNet.stopNodes()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `plain old state is not soft locked`() = run(false, PlainOldState(nodePair), false)
|
||||
|
||||
|
@ -14,10 +14,9 @@ import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.unwrap
|
||||
|
||||
|
||||
@StartableByRPC
|
||||
@InitiatingFlow
|
||||
class TestCommsFlowInitiator(val x500Name: CordaX500Name? = null) : FlowLogic<List<String>>() {
|
||||
class TestCommsFlowInitiator(private val x500Name: CordaX500Name? = null) : FlowLogic<List<String>>() {
|
||||
|
||||
object SENDING : ProgressTracker.Step("SENDING")
|
||||
object RECIEVED_ALL : ProgressTracker.Step("RECIEVED_ALL")
|
||||
@ -42,7 +41,7 @@ class TestCommsFlowInitiator(val x500Name: CordaX500Name? = null) : FlowLogic<Li
|
||||
progressTracker.currentStep = RECIEVED_ALL
|
||||
}
|
||||
val tx = TransactionBuilder(notary = serviceHub.networkMapCache.notaryIdentities.first())
|
||||
tx.addOutputState(CommsTestState(responses, serviceHub.myInfo.legalIdentities.first()), CommsTestContract::class.qualifiedName!!)
|
||||
tx.addOutputState(CommsTestState(responses, serviceHub.myInfo.legalIdentities.first()), CommsTestContract::class.java.name)
|
||||
tx.addCommand(CommsTestCommand, serviceHub.myInfo.legalIdentities.first().owningKey)
|
||||
val signedTx = serviceHub.signInitialTransaction(tx)
|
||||
subFlow(FinalityFlow(signedTx))
|
||||
@ -55,27 +54,23 @@ class TestCommsFlowInitiator(val x500Name: CordaX500Name? = null) : FlowLogic<Li
|
||||
}
|
||||
|
||||
@InitiatedBy(TestCommsFlowInitiator::class)
|
||||
class TestCommsFlowResponder(val otherSideSession: FlowSession) : FlowLogic<Unit>() {
|
||||
class TestCommsFlowResponder(private val otherSideSession: FlowSession) : FlowLogic<Unit>() {
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
otherSideSession.send("Hello from: " + serviceHub.myInfo.legalIdentities.first().name.toString())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@CordaSerializable
|
||||
data class CommsTestState(val responses: List<String>, val issuer: AbstractParty) : ContractState {
|
||||
override val participants: List<AbstractParty>
|
||||
get() = listOf(issuer)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@CordaSerializable
|
||||
object CommsTestCommand : CommandData
|
||||
|
||||
|
||||
class CommsTestContract : Contract {
|
||||
override fun verify(tx: LedgerTransaction) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
|
||||
|
||||
@StartableByRPC
|
||||
class TestNotaryFlow : FlowLogic<String>() {
|
||||
|
||||
@ -28,38 +27,34 @@ class TestNotaryFlow : FlowLogic<String>() {
|
||||
override fun call(): String {
|
||||
val issueBuilder = TransactionBuilder()
|
||||
val notary = serviceHub.networkMapCache.notaryIdentities.first()
|
||||
issueBuilder.notary = notary;
|
||||
issueBuilder.notary = notary
|
||||
val myIdentity = serviceHub.myInfo.legalIdentities.first()
|
||||
issueBuilder.addOutputState(NotaryTestState(notary.name.toString(), myIdentity), NotaryTestContract::class.qualifiedName!!)
|
||||
issueBuilder.addOutputState(NotaryTestState(notary.name.toString(), myIdentity), NotaryTestContract::class.java.name)
|
||||
issueBuilder.addCommand(NotaryTestCommand, myIdentity.owningKey)
|
||||
val signedTx = serviceHub.signInitialTransaction(issueBuilder)
|
||||
val issueResult = subFlow(FinalityFlow(signedTx))
|
||||
progressTracker.currentStep = ISSUED
|
||||
val destroyBuilder = TransactionBuilder()
|
||||
destroyBuilder.notary = notary;
|
||||
destroyBuilder.notary = notary
|
||||
destroyBuilder.addInputState(issueResult.tx.outRefsOfType<NotaryTestState>().first())
|
||||
destroyBuilder.addCommand(NotaryTestCommand, myIdentity.owningKey)
|
||||
val signedDestroyT = serviceHub.signInitialTransaction(destroyBuilder)
|
||||
val result = subFlow(FinalityFlow(signedDestroyT))
|
||||
progressTracker.currentStep = DESTROYING
|
||||
progressTracker.currentStep = FINALIZED
|
||||
return "notarised: " + result.notary.toString() + "::" + result.tx.id
|
||||
return "notarised: ${result.notary}::${result.tx.id}"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@CordaSerializable
|
||||
data class NotaryTestState(val id: String, val issuer: AbstractParty) : ContractState {
|
||||
override val participants: List<AbstractParty>
|
||||
get() = listOf(issuer)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@CordaSerializable
|
||||
object NotaryTestCommand : CommandData
|
||||
|
||||
|
||||
class NotaryTestContract : Contract {
|
||||
override fun verify(tx: LedgerTransaction) {
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user