interfaceContract{ /** * Takes an object that represents a state transition, and ensures the inputs/outputs/commands make sense. * Must throw an exception if there's a problem that should prevent state transition. Takes a single object * rather than an argument so that additional data can be added without breaking binary compatibility with * existing contract code. */ @Throws(IllegalArgumentException::class) funverify(tx: LedgerTransaction) }
publicclassIouContractimplementsContract{ publicstatic String ID = "bootcamp.IouContract";
@Override publicvoidverify(LedgerTransaction tx){ // 1、Shape Constraint,No. input states, No. output states, command if (tx.getCommands().size() != 1) { thrownew IllegalArgumentException("command size must be one"); } Command<CommandData> command = tx.getCommand(0); if (!(command.getValue() instanceof Commands.Issue)) { thrownew IllegalArgumentException("command must be Issue"); } if (CollectionUtils.isNotEmpty(tx.getInputs())) { thrownew IllegalArgumentException("Issue must be not inputs"); } if (tx.getOutputs().size() != 1) { thrownew IllegalArgumentException("Issue outputs must be one"); }
ContractState output = tx.getOutput(0); // 2、Context Constraint if (!(output instanceof IouState)) { thrownew IllegalArgumentException("state must be IouState"); } IouState iouState = (IouState) output; if (iouState.getAmount() <= 0) { thrownew IllegalArgumentException("issue amount must big than zero"); }
// 3、Required Singer Constraint if (!command.getSigners().contains(iouState.getIssuer().getOwningKey())) { thrownew IllegalArgumentException("issue business must be sing by issuer"); } }
privatefinal ProgressTracker progressTracker = new ProgressTracker();
@Override public ProgressTracker getProgressTracker(){ return progressTracker; }
@Suspendable @Override public SignedTransaction call()throws FlowException { // We choose our transaction's notary (the notary prevents double-spends). Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0); // We get a reference to our own identity. Party issuer = getOurIdentity();
// We create our new IouState. IouState iouState = new IouState(issuer, owner, amount);
// We build our transaction. TransactionBuilder transactionBuilder = new TransactionBuilder(notary) // .addInputState() .addOutputState(iouState, IouContract.ID) .addCommand(new IouContract.Commands.Issue(), ImmutableList.of(issuer.getOwningKey(), owner.getOwningKey()));
// We check our transaction is valid based on its contracts. transactionBuilder.verify(getServiceHub());
FlowSession session = initiateFlow(owner);
// We sign the transaction with our private key, making it immutable. SignedTransaction signedTransaction = getServiceHub().signInitialTransaction(transactionBuilder);
// The counterparty signs the transaction SignedTransaction fullySignedTransaction = subFlow(new CollectSignaturesFlow(signedTransaction, singletonList(session)));
// We get the transaction notarised and recorded automatically by the platform. return subFlow(new FinalityFlow(fullySignedTransaction, singletonList(session))); } }
✅ Starting Requesting signature by notary service Requesting signature by Notary service Validating response from Notary service ✅ Broadcasting transaction to participants ➡️ Done Flow completed with result: SignedTransaction(id=14D268667D208D26BF92ADC1F58003DFC9EAF7E036ACB2C2CABC153E627500C0)
查询生成的数据
1
run vaultQuery contractStateType: bootcamp.IouState