В Corda, как респондент может добавить компоненты к транзакции? - PullRequest
0 голосов
/ 16 ноября 2018

У меня есть поток Corda, в котором респонденту Party необходимо добавить компоненты к транзакции (например, респонденту, возможно, придется добавить свои собственные денежные средства в транзакцию для оплаты актива в сделке).

Как я могу разрешить респонденту добавлять эти данные?

1 Ответ

0 голосов
/ 16 ноября 2018

Ниже приведен пример того, как это делается.В итоге:

  • Инициатор использует send для отправки респонденту параметров состояния для добавления
  • Респондент использует receive для получения этих параметров и создаетсостояние
  • Ответчик использует send для отправки созданного состояния обратно инициатору
  • Инициатор добавляет состояние в построитель транзакций и продолжает выполнение потока как обычно
  • Когда респонденту предлагается подписать транзакцию как часть CollectSignaturesFlow, он проверяет, что предоставленное им состояние и транзакция, как правило, соответствуют ожиданиям

Код инициатора

@InitiatingFlow
@StartableByRPC
public class IOUFlowInitiator extends FlowLogic<SignedTransaction> {
    private final int iouValue;
    private final Party otherParty;

    private final ProgressTracker progressTracker = new ProgressTracker();

    public IOUFlowInitiator(int iouValue, Party otherParty) {
        this.iouValue = iouValue;
        this.otherParty = otherParty;
    }

    @Override
    public ProgressTracker getProgressTracker() {
        return progressTracker;
    }

    @Suspendable
    @Override
    public SignedTransaction call() throws FlowException {
        // Get the counterparty to create the output IOUState.
        final FlowSession otherPartySession = initiateFlow(otherParty);
        final IOUState iouState = otherPartySession.sendAndReceive(IOUState.class, iouValue).unwrap(wrappedIOU -> wrappedIOU);

        // Create the command.
        final List<PublicKey> requiredSigners = Arrays.asList(iouState.getLender().getOwningKey(), iouState.getBorrower().getOwningKey());
        final Command<IOUContract.Commands.Create> txCommand = new Command<>(
                new IOUContract.Commands.Create(), requiredSigners);

        // Build the transaction.
        final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
        final TransactionBuilder txBuilder = new TransactionBuilder(notary)
                .addOutputState(iouState, IOU_CONTRACT_ID)
                .addCommand(txCommand);

        // Verify, sign and finalise.
        txBuilder.verify(getServiceHub());
        final SignedTransaction partSignedTx = getServiceHub().signInitialTransaction(txBuilder);
        final SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(partSignedTx, ImmutableSet.of(otherPartySession), CollectSignaturesFlow.Companion.tracker()));
        return subFlow(new FinalityFlow(fullySignedTx));
    }
}

Код ответчика

@InitiatedBy(IOUFlowInitiator.class)
public class IOUFlowResponder extends FlowLogic<SignedTransaction> {
    private final FlowSession counterpartySession;

    public IOUFlowResponder(FlowSession counterpartySession) {
        this.counterpartySession = counterpartySession;
    }

    @Suspendable
    @Override
    public SignedTransaction call() throws FlowException {
        // Receive the IOU's value from the counterparty.
        Integer iouValue = counterpartySession.receive(Integer.class).unwrap(wrappedInt -> wrappedInt);

        // Create the output IOUState.
        Party otherParty = counterpartySession.getCounterparty();
        IOUState iouState = new IOUState(iouValue, getOurIdentity(), otherParty, new UniqueIdentifier());

        // Send the output IOUState to the counterparty.
        counterpartySession.send(iouState);

        // Sign the resulting transaction if it meets expectations.
        return subFlow(new CheckIOUAndSignFlow(iouState, counterpartySession, SignTransactionFlow.Companion.tracker()));
    }
}

class CheckIOUAndSignFlow extends SignTransactionFlow {
    private final IOUState expectedIOU;

    CheckIOUAndSignFlow(IOUState expectedIOU, FlowSession otherPartyFlow, ProgressTracker progressTracker) {
        super(otherPartyFlow, progressTracker);
        this.expectedIOU = expectedIOU;
    }

    @Override
    protected void checkTransaction(SignedTransaction stx) throws FlowException {
        LedgerTransaction ltx = null;
        try {
            ltx = stx.toLedgerTransaction(getServiceHub(), false);
        } catch (SignatureException e) {
            throw new FlowException("Transaction had invalid signature.");
        }

        // Check that the resulting transaction meets expectations.
        List<IOUState> outputs = ltx.outputsOfType(IOUState.class);
        List<Command<IOUContract.Commands.Create>> commands = ltx.commandsOfType(IOUContract.Commands.Create.class);

        if (outputs.size() != 1) throw new FlowException("Expected single IOU output in the transaction.");
        if (commands.size() != 1) throw new FlowException("Expected single IOU Create command in the transaction.");

        IOUState outputState = outputs.get(0);

        if (!outputState.equals(expectedIOU)) throw new FlowException("IOU does not match expected IOU..");
    }
}
...