是否可以在一个流中创建和使用相同的Corda状态,或者在不同的子流中创建和使用它?
我收到以下错误:
Caused by: net.corda.core.flows.NotaryException: Unable to notarise transactionBEDE8C3F8F2D7A646A9F7D1948DAF77CDAFC37F3B086E09FC766F0D412F02690: One or more input states have been used in another transaction
答案 0 :(得分:1)
是的,您可以在单个流程中创建和使用相同的Corda状态。
您需要执行两个步骤:
请注意,如果您创建第二笔交易,并导致交易对手在完成第一笔交易之前调用ResolveTransactionFlow
,这将导致TransactionResolutionException
,因为您在第一笔交易中没有您的存储空间尚未分发。例如,在运行CollectSignaturesFlow
时会发生这种情况。
以下是在同一流程中构建两个事务的示例:
@InitiatingFlow
@StartableByRPC
class TwoTransactionsFlow(val otherParty: Party) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
val otherPartySessions = listOf(initiateFlow(otherParty))
val transactionBuilderOne = TransactionBuilder()
// TODO: Add notary and transaction components.
val partSignedTransactionOne = serviceHub.signInitialTransaction(transactionBuilderOne)
val fullySignedTransactionOne = subFlow(CollectSignaturesFlow(partSignedTransactionOne, otherPartySessions))
val notarisedTransactionOne = subFlow(FinalityFlow(fullySignedTransactionOne))
val transactionOneFirstOutputRef = StateRef(notarisedTransactionOne.id, 0)
val transactionOneFirstOutput = serviceHub.toStateAndRef<ContractState>(transactionOneFirstOutputRef)
val transactionBuilderTwo = TransactionBuilder()
.addInputState(transactionOneFirstOutput)
// TODO: Add notary and other transaction components.
val partSignedTransactionTwo = serviceHub.signInitialTransaction(transactionBuilderTwo)
val fullySignedTransactionTwo = subFlow(CollectSignaturesFlow(partSignedTransactionTwo, otherPartySessions))
subFlow(FinalityFlow(fullySignedTransactionTwo))
}
}
答案 1 :(得分:1)
还有更多要考虑的地方
Java中启动程序流的代码段
...
// Signing the transaction.
SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
// Creating a session with the other party.
FlowSession otherPartySession = initiateFlow(otherParty);
// Obtaining the counterparty's signature.
SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(
signedTx, Arrays.asList(otherPartySession), CollectSignaturesFlow.Companion.tracker()));
//notarized transaction
SignedTransaction notraizedtransaction = subFlow(new FinalityFlow(fullySignedTx, otherPartySession));
//------------------------------------------------------------------------------------------------------------
// STEP-2:
// SINCE NOW WE HAVE A NEW UNCONSUMED RECORD-ANCHOR SO WE MUST MAKE IT CONSUMED ( BY USING THE PREVIOUS OUTPUT AS AN INPUT)
//
//------------------------------------------------------------------------------------------------------------
StateAndRef oldStateref = getServiceHub().toStateAndRef(new StateRef(notraizedtransaction.getId(),0));
Command storeCommand = new Command<>(new AnchorStateContract.Commands.ApproveRecAnchorCmd(), requiredSigners);
TransactionBuilder txBuilder2 = new TransactionBuilder(notary)
.addInputState(oldStateref)
.addCommand(storeCommand);
txBuilder2.verify(getServiceHub());
// signing
SignedTransaction signedTx2 = getServiceHub().signInitialTransaction(txBuilder2);
// Finalising the transaction.
SignedTransaction fullySignedTx2 = subFlow(new CollectSignaturesFlow(
signedTx2, Arrays.asList(otherPartySession), CollectSignaturesFlow.Companion.tracker()));
//notarized transaction
return subFlow(new FinalityFlow(fullySignedTx2, otherPartySession));
}
Java ResponderFlow的代码段
@InitiatedBy(Initiator.class)
public class Responder extends FlowLogic<SignedTransaction> {
private FlowSession otherPartySession;
public Responder(FlowSession otherPartySession) {
this.otherPartySession = otherPartySession;
}
@Suspendable
@Override
public SignedTransaction call() throws FlowException
{
//this class is used inside call function for the verification purposes before signed by this party
class SignTxFlow1 extends SignTransactionFlow
{
private SignTxFlow1(FlowSession otherPartySession) {
super(otherPartySession);
}
@Override
protected void checkTransaction(SignedTransaction stx) {
requireThat(require -> {
// Validation Logic
return null;
});
}
}
//this class is used inside call function for the verification purposes before signed by this party
class SignTxFlow2 extends SignTransactionFlow
{
private SignTxFlow2(FlowSession otherPartySession) {
super(otherPartySession);
}
@Override
protected void checkTransaction(SignedTransaction stx) {
requireThat(require -> {
// Validation Logic
return null;
});
}
}
//Validation, signing and storing of first transaction data
SecureHash expectedTxId1 = subFlow(new SignTxFlow1(otherPartySession)).getId();
subFlow(new ReceiveFinalityFlow(otherPartySession, expectedTxId1));
//Validation, signing and storing of second transaction data
SecureHash expectedTxId2 = subFlow(new SignTxFlow2(otherPartySession)).getId();
return subFlow(new ReceiveFinalityFlow(otherPartySession, expectedTxId2));
}
}