Ниже приведен пример того, как это делается.В итоге:
- Инициатор использует
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..");
}
}