我在corda中创建了一个示例应用程序,并且还创建了两个流程。
在第一个流程中,我创建了一个状态,然后在我创建的另一个流程中使用了相同的状态。
下面是第一个流程
@InitiatingFlow
@StartableByRPC
public class Initiator extends FlowLogic<SignedTransaction> {
private final String batchId;
private final int numTomato;
private final Party toUser;
private final ProgressTracker.Step GENERATING_TRANSACTION = new ProgressTracker.Step("Generating transaction based on new BatchTransaction.");
private final ProgressTracker.Step VERIFYING_TRANSACTION = new ProgressTracker.Step("Verifying contract constraints.");
private final ProgressTracker.Step SIGNING_TRANSACTION = new ProgressTracker.Step("Signing transaction with our private key.");
private final ProgressTracker.Step GATHERING_SIGS = new ProgressTracker.Step("Gathering the counterparty's signature.") {
@Override
public ProgressTracker childProgressTracker() {
return CollectSignaturesFlow.Companion.tracker();
}
};
private final ProgressTracker.Step FINALISING_TRANSACTION = new ProgressTracker.Step("Obtaining notary signature and recording transaction.") {
@Override
public ProgressTracker childProgressTracker() {
return FinalityFlow.Companion.tracker();
}
};
private final ProgressTracker progressTracker = new ProgressTracker(
GENERATING_TRANSACTION,
VERIFYING_TRANSACTION,
SIGNING_TRANSACTION,
GATHERING_SIGS,
FINALISING_TRANSACTION
);
public Initiator(String batchId, int numTomato, Party toUser) {
this.batchId = batchId;
this.numTomato = numTomato;
this.toUser = toUser;
}
@Override
public ProgressTracker getProgressTracker() {
return progressTracker;
}
@Suspendable
@Override
public SignedTransaction call() throws FlowException {
ServiceHub serviceHub = getServiceHub();
List<StateAndRef<TemplateState>> statesFromVault = serviceHub.getVaultService().queryBy(TemplateState.class).getStates();
final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
//Stage 1
// Generating Unsigned Transaction
Party me = getOurIdentity();
TemplateState tempState = new TemplateState(batchId, numTomato, me, toUser, new UniqueIdentifier());
// LedgerTransaction tx = new LedgerTransaction();
// Command command = tx.getCommand(0);
final Command<TemplateContract.Commands.Register> txCommand = new Command<>(
new TemplateContract.Commands.Register(),
ImmutableList.of(tempState.getFromUser().getOwningKey(), tempState.getToUser().getOwningKey()));
final TransactionBuilder txBuilder = new TransactionBuilder(notary)
.addOutputState(tempState)
.addCommand(txCommand);
// Stage 2.
progressTracker.setCurrentStep(VERIFYING_TRANSACTION);
// Verify that the transaction is valid.
txBuilder.verify(getServiceHub());
// Stage 3.
progressTracker.setCurrentStep(SIGNING_TRANSACTION);
//sign the transaction
final SignedTransaction partSignedTx = getServiceHub().signInitialTransaction(txBuilder);
// Stage 4.
progressTracker.setCurrentStep(GATHERING_SIGS);
// Send the state to the counterparty, and receive it back with their signature.
FlowSession ownerSession = initiateFlow(toUser);
final SignedTransaction fullySignedTx = subFlow(
new CollectSignaturesFlow(partSignedTx, ImmutableSet.of(ownerSession), CollectSignaturesFlow.Companion.tracker()));
// Stage 5.
progressTracker.setCurrentStep(FINALISING_TRANSACTION);
// Notarise and record the transaction in both parties' vaults.
return subFlow(new FinalityFlow(fullySignedTx, ImmutableSet.of(ownerSession)));
}
@InitiatedBy(Initiator.class)
public static class Acceptor extends FlowLogic<SignedTransaction> {
private final FlowSession ownerSession;
public Acceptor(FlowSession ownerSession) {
this.ownerSession = ownerSession;
}
@Suspendable
@Override
public SignedTransaction call() throws FlowException {
class SignTxFlow extends SignTransactionFlow {
private SignTxFlow(FlowSession ownerPartyFlow, ProgressTracker progressTracker) {
super(ownerPartyFlow, progressTracker);
}
@Override
protected void checkTransaction(SignedTransaction stx) {
requireThat(require -> {
ContractState output = stx.getTx().getOutputs().get(0).getData();
require.using("This must be an TomatoBatch transaction.", output instanceof TemplateState);
return null;
});
}
}
final SignTxFlow signTxFlow = new SignTxFlow(ownerSession, SignTransactionFlow.Companion.tracker());
final SecureHash txId = subFlow(signTxFlow).getId();
return subFlow(new ReceiveFinalityFlow(ownerSession, txId));
}
}
}
下面是第二个流程
package com.template.flows;
@InitiatingFlow
@StartableByRPC
public class TransferBatch extends FlowLogic<SignedTransaction>{
private final String batchId;
private final Party toUser;
private final ProgressTracker.Step GENERATING_TRANSACTION = new ProgressTracker.Step("Generating transaction based on new BatchTransaction.");
private final ProgressTracker.Step VERIFYING_TRANSACTION = new ProgressTracker.Step("Verifying contract constraints.");
private final ProgressTracker.Step SIGNING_TRANSACTION = new ProgressTracker.Step("Signing transaction with our private key.");
private final ProgressTracker.Step GATHERING_SIGS = new ProgressTracker.Step("Gathering the counterparty's signature.") {
@Override
public ProgressTracker childProgressTracker() {
return CollectSignaturesFlow.Companion.tracker();
}
};
private final ProgressTracker.Step FINALISING_TRANSACTION = new ProgressTracker.Step("Obtaining notary signature and recording transaction.") {
@Override
public ProgressTracker childProgressTracker() {
return FinalityFlow.Companion.tracker();
}
};
private final ProgressTracker progressTracker = new ProgressTracker(
GENERATING_TRANSACTION,
VERIFYING_TRANSACTION,
SIGNING_TRANSACTION,
GATHERING_SIGS,
FINALISING_TRANSACTION
);
public TransferBatch(String batchId, Party toUser) throws NoSuchFieldException {
this.batchId = batchId;
this.toUser = toUser;
}
@Override
public ProgressTracker getProgressTracker() {
return progressTracker;
}
@Suspendable
@Override
public SignedTransaction call() throws FlowException {
ServiceHub serviceHub = getServiceHub();
final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
Party me = getOurIdentity();
QueryCriteria generalCriteria = new VaultQueryCriteria(Vault.StateStatus.UNCONSUMED);
FieldInfo attributeCurrency = null;
try {
attributeCurrency = getField("batchId", TemplateSchemaV1.PersistentBatch.class);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
CriteriaExpression currencyIndex = Builder.equal(attributeCurrency, this.batchId);
QueryCriteria customCriteria1 = new VaultCustomQueryCriteria(currencyIndex);
QueryCriteria criteria = generalCriteria.and(customCriteria1);
StateAndRef<TemplateState> state = serviceHub.getVaultService().queryBy(TemplateState.class, criteria).getStates().get(0);
TemplateState dataState = state.getState().getData();
TemplateState outState = new TemplateState(dataState.getBatchId(), dataState.getNumTomato(), me, toUser, dataState.getLinearId());
final Command<TemplateContract.Commands.Register> txCommand = new Command<>(
new TemplateContract.Commands.Register(),
ImmutableList.of(me.getOwningKey(), outState.getToUser().getOwningKey()));
final TransactionBuilder txBuilder = new TransactionBuilder(notary)
.addInputState(state)
.addOutputState(outState)
.addCommand(txCommand);
progressTracker.setCurrentStep(VERIFYING_TRANSACTION);
// Verify that the transaction is valid.
txBuilder.verify(getServiceHub());
progressTracker.setCurrentStep(SIGNING_TRANSACTION);
//sign the transaction
final SignedTransaction partSignedTx = getServiceHub().signInitialTransaction(txBuilder);
progressTracker.setCurrentStep(GATHERING_SIGS);
// Send the state to the counterparty, and receive it back with their signature.
FlowSession ownerSession = initiateFlow(toUser);
FlowSession oldOwnerSession = initiateFlow(dataState.getFromUser());
FlowSession fromUserSession = initiateFlow(outState.getFromUser());
final SignedTransaction fullySignedTx = subFlow(
new CollectSignaturesFlow(partSignedTx, ImmutableSet.of(ownerSession), CollectSignaturesFlow.Companion.tracker()));
// Stage 5.
progressTracker.setCurrentStep(FINALISING_TRANSACTION);
List<FlowSession> partySessions = Arrays.asList(ownerSession, oldOwnerSession);
// Notarise and record the transaction in both parties' vaults.
return subFlow(new FinalityFlow(fullySignedTx, partySessions));
}
@InitiatedBy(TransferBatch.class)
public static class Acceptor extends FlowLogic<SignedTransaction> {
private final FlowSession ownerSession;
public Acceptor(FlowSession ownerSession) {
this.ownerSession = ownerSession;
}
@Suspendable
@Override
public SignedTransaction call() throws FlowException {
class SignTxFlow extends SignTransactionFlow {
private SignTxFlow(FlowSession ownerPartyFlow, ProgressTracker progressTracker) {
super(ownerPartyFlow, progressTracker);
}
@Override
protected void checkTransaction(SignedTransaction stx) {
requireThat(require -> {
ContractState output = stx.getTx().getOutputs().get(0).getData();
require.using("This must be an TomatoBatch transaction.", output instanceof TemplateState);
return null;
});
}
}
final SignTxFlow signTxFlow = new SignTxFlow(ownerSession, SignTransactionFlow.Companion.tracker());
final SecureHash txId = subFlow(signTxFlow).getId();
return subFlow(new ReceiveFinalityFlow(ownerSession, txId));
}
}
}
如果可以在流中看到,我可以从Vault中搜索现有状态,并且可以通过在第二个流中添加输入和输出状态来从现有状态创建另一个状态。
所有操作均正常。但是当我检查第一个节点的状态时,我仍然认为它没有消耗。
请让我知道我在这里想念什么。