Corda 响应程序流不响应

Corda responder flow not answering

我使用 IntelliJ 创建了一个非常简单的流程测试。

@Test
    public void dummyTest() throws InterruptedException, ExecutionException {

        Party Alice = aliceNode.getServices().getIdentityService().wellKnownPartyFromX500Name(new CordaX500Name("Alice", "London", "GB"));

        FlowInitiatorIssueToken flow = new FlowInitiatorIssueToken(30, alice, network.getDefaultNotaryIdentity());
        SignedTransaction transaction = bobNode.startFlow(flow).get();
        // The error occurs because of this line ....

        State state = (State) transaction.getTx().getOutputStates().get(0);

        assertEquals(state.getParticipants(), alice);

        VaultQueryCriteria criteria = new VaultQueryCriteria(Vault.StateStatus.ALL);

        aliceNode.transaction(() -> {
            Vault.Page<State> result = aliceNode.getServices().getVaultService().queryBy(State.class, criteria);
            assertTrue(result.getStates().size() > 0);

            return null;
        });

    network.runNetwork();        
    }

IntelliJ 无法完成测试并给我错误

statemachine.FlowMonitor. - Flow with id 3982ab19-3e5b-4737-9adf-e4a6a97d20e6 has been waiting for 117 seconds to receive messages from parties [O=Alice, L=London, C=GB]

这导致了响应程序流没有做任何事情的假设。

// ******************
// * Initiator flow *
// ******************

@InitiatingFlow
@StartableByRPC
public class FlowInitiatorIssueToken extends FlowLogic<SignedTransaction> {
    private final Integer value;
    private final Party counterParty;
    private final Party notary; 

    public FlowInitiatorIssuToken(Integer value, Party counterParty, Party notary) {
        this.value = value;
        this.counterParty = counterParty;
        this.notary = notary; 
    }

    /**
     * The flow logic is encapsulated within the call() method.
     */
    @Suspendable
    @Override
    public SignedTransaction call() throws FlowException {


        /*------------------------------
         * SENDING AND RECEIVING DATA *
        ------------------------------*/

        FlowSession issueTokenSession = initiateFlow((Party) counterParty);


        /*------------------------------------------
         * GATHERING OTHER TRANSACTION COMPONENTS * 
        ------------------------------------------*/

        State outputState = new State(this.value, this.counterParty);
        Command<ContractToken.Commands.Issue> command = new Command<>(new ContractToken.Commands.Issue(), getOurIdentity().getOwningKey());

        /*------------------------
         * TRANSACTION BUILDING *
        ------------------------*/

        TransactionBuilder txBuilder = new TransactionBuilder(notary)
                .addOutputState(outputState, ContractToken.ID)
                .addCommand(command);


        /*-----------------------
         * TRANSACTION SIGNING *
        -----------------------*/

        SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);


        /*------------------------------
         * FINALISING THE TRANSACTION *
        ------------------------------*/

        System.out.println("Hey World!");

        subFlow(new FinalityFlow(signedTx, issueTokenSession));

        return null;
    }

}

// ******************
// * Responder flow *
// ******************
@InitiatedBy(FlowInitiatorIssueToken.class)
public class FlowResponderIssueToken extends FlowLogic<SignedTransaction> {
    private final FlowSession issueTokenSession;

    public FlowResponderIssueToken(FlowSession issueTokenSession) {
        this.issueTokenSession = issueTokenSession;
    }

    @Suspendable
    @Override
    public SignedTransaction call() throws FlowException {


        /*-----------------------------------------
         * RESPONDING TO COLLECT_SIGNATURES_FLOW *
        -----------------------------------------*/


        class SignTxFlow extends SignTransactionFlow {
            private SignTxFlow(FlowSession issueTokenSession) {
                super(issueTokenSession);
            }

            @Override
            protected void checkTransaction(SignedTransaction stx) {

            }
        }

        SecureHash idOfTxWeSigned = subFlow(new SignTxFlow(issueTokenSession, SignTransactionFlow.tracker())).getId();

        /*------------------------------
         * FINALISING THE TRANSACTION *
        ------------------------------*/

        subFlow(new ReceiveFinalityFlow(issueTokenSession, idOfTxWeSigned));
        return null;
    }
}

启动程序流程已执行。我可以看到,因为 System.out.println("Hey World!") 命令显示在日志中。但是,我不知道响应者流是否从未被发起者流启动,或者它只是没有反应。也许你可以帮我解决这个问题。

谢谢!

  1. 您没有在启动器中调用 CollectSignaturesFlow;这就是为什么您没有与响应者启动 "conversation" 让他们签署交易。请参阅示例 here
  2. 您在响应者中调用的
  3. SignTransactionFlow 是在发起者中调用 CollectSignaturesFlow 的 "reply"。
  4. 顺便说一句,您必须先验证交易,然后再在发起方中签名。请参阅示例 here

另一件遗漏的事情是对方的钥匙。初始化 command 时,我添加了

final Command<ContractToken.Commands.Issue> txCommand = new Command<>(
                    new ContractToken.Commands.Issue(),
                    ImmutableList.of(getOurIdentity().getOwningKey(), counterParty.getOwningKey()));