区块链开发之Corda训练营笔记12:Flow习题答案
1、IOUIssueFlow
一、类的成员与构造器
flow是用来定义tx的流转过程的,用来新建tx,然后交给需要的人进行签名,这只是第一步用来生成flow,最关键的还是新建flow,来进行会话
首先我们先进行声明,它扩展了抽象类flowLogic:
kjkjpublic class IOUIssueFlow extends FlowLogic<SignedTransaction>
如果我现在想issue一个债券,需要指定给定、多少钱,为什么没有issuer,就是谁调用它谁就是issuer?
债券是干嘛的?就是表示你欠我多少嘛,就是指定owner欠issuer多少钱,那么响应flow的那个class是干嘛的?
所以我们可以指定欠钱的人和欠的钱
private final Party owner;
private final int amunt;
然后是构造器:
public IOUIssueFlow(Party owner, int amount) {
this.owner = owner;UIssueFlow
一、类的成员与构造器
flow是用来定义tx的流转过程的,用来新建tx,然后交给需要的人进行签名,这只是第一步用来生成flow,最关键的还是新建flow,来进行会话
首先我们先进行声明,它扩展了抽象类flowLogic:

kjkjpublic class IOUIssueFlow extends FlowLogic<SignedTransaction>
如果我现在想issue一个债券,需要指定给定、多少钱,为什么没有issuer,就是谁调用它谁就是issuer?
债券是干嘛的?就是表示你欠我多少嘛,就是指定owner欠issuer多少钱,那么响应flow的那个class是干嘛的?
所以我们可以指定欠钱的人和欠的钱

private final Party owner;
private final int amunt;
然后是构造器:
this.amount = amount;
}
这个类总共有三个数据成员,第三个就是一个progressTracker
private final ProgressTracker progressTracker = new ProgressTracker();
它不用用户去指定,用户不知道这些东西,你也不可能要求懂这些底层的东西!但是他有get方法
@Override
public ProgressTracker getProgressTracker() {
return progressTracker;
}
二、class()方法
我们扩展了flowLogic类,这个类最重要的就是call方法,下面是这个函数的声明
@Suspendable
@Override
public signedTransaction call() throws FlowException
接下来是分为三大步:
- 新建state
- 将state及其contract加入到tx中去
- notrary需要放在outputState之前
- 新建tx
- 将command加入到tx中去
- tx的流转
I、新建state
此外我们还需要依靠公证人达成共识
Party issuer = getOurIdentity();
接下来是第一步,建立state:
一个iou需要issuer,谁启动这个流、谁就是issuer,流也是由party启动的!
IOUState iouState = new IOUState(issuer, owner, amount);
IOUContract.Commands.Issue command = new IOUContract.Commands.Issue();
II、新建tx
我个人感觉,从便于理解的角度,整个corda,乃至所有的区块链网络,都是以tx为核心的。
corda中的tx需要这些东西:
- 公证人
- 输入输出的state
- 检验命令的contract的引用
- 命令及其签名者
Party notrary = getServiceHub().getNetworkMapCache().getNotraryIdentities(0);
tx.setNotrary(notrary);
notrary.setOutputState(iouState, IOUContact.ID);
List<PublicKey> requiredSigner = ImmutableList.of(IOUState.getIssuer().getOwingKey());
tx.addCommnad(command,requiredSigner);
III、发送流更新账本
大致分为以下几步:
- 通过servicehub来验证tx
- 新建一个会话
- 将tx签名认证
- (————————————————————前方高能——————————————)
- 这应该就开始和responder进行交互
完全签名的tx的意思是不是需要其他方面的签名之后的,所以我们需要建立子流和其他节点进行交互,
所以需要收前面所有签名的流+会话,
最后返回的用完全签名流+单例会话形成的新的终止子流
等等,这张图是不是就是前面那张图的总结????????很有可能啊!!!我只要能弄懂应答流的程序&这个流的交换过程&读读文献我可能就打通了整个corda了!
根据contract验证tx的合法性
txBuidler.verify(getServiceHub())
生成流会话
Flow Session = initiateFlow(owner);
用私钥签署这个交易让它不可改变了
SignedTransaction signedTransaction = getSeriveHub().signInitialTransaction(txBuilder);
2、IOUIssueFlowResponder
2.1、类的声明与构造器
作为被启动流,它必须打上注释:
@InitiatedBy(IOUIssueFlow.class)
该类扩展flowLogic,返回的call的类型是Void
public class IOUIssueFlowResponder extends FlowLogic<Void> {
@Override
@Suspendable
public Void call() throws Exception {
}
}
它只有一个私有成员,就是另一边发来的会话?
private final FlowSession otherSide
然后Alt + Insert生成构造器
public IOUIssuerFlowResponder(FlowSession otherSide) {
this.other = otherSide
}
2.2 call()方法
说来也奇怪,这个call方法我完全看不懂嘞、、、
首先是生成一个stx,生成的方法是subFlow、、,subFlow就是调用子流的意思,一旦子流和它里面的call方法完成,生成结果就调用它呗
/*
*
*/
@Suspendable
@Throws(FlowException::class)
open fun <R> subFlow(subLogic: FlowLogic<R>): R {
subLogic.stateMachine = stateMachine
maybeWireUpProgressTracking(subLogic)
logger.debug { "Calling subflow: $subLogic" }
val result = stateMachine.subFlow(subLogic)
logger.debug { "Subflow finished with result ${result.toString().abbreviate(300)}" }
return result
}
传进去的也是flowLogic
3、完整代码
3.1 IOUIssueFlow
package bootcamp;
import co.paralleluniverse.fibers.Suspendable;
import com.google.common.collect.ImmutableList;
import net.corda.core.flows.*;
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
import net.corda.core.utilities.ProgressTracker;
import java.security.PublicKey;
import java.util.List;
import static java.util.Collections.singletonList;
@InitiatingFlow
@StartableByRPC
public class IOUIssueFlow extends FlowLogic<SignedTransaction> {
private final Party owner;
private final int amount;
public IOUIssueFlow(Party owner, int amount) {
this.owner = owner;
this.amount = amount;
}
private final 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();
/* ============================================================================
* TODO 1 - Create our TokenState to represent on-ledger tokens!
* ===========================================================================*/
// We create our new TokenState.
IOUState IOUState = new IOUState(issuer, owner, amount);
IOUContract.Commands.Issue command = new IOUContract.Commands.Issue();
/* ============================================================================
* TODO 3 - Build our token issuance transaction to update the ledger!
* ====================ommand(command, IOUState.getIssuer().getOwningKey()); //step5,把命令加到tx
transactionBuilder.setN=======================================================*/
// We build our transaction.
TransactionBuilder transactionBuilder = new TransactionBuilder();
transactionBuilder.setNotary(notary);
transactionBuilder.addOutputState(IOUState, IOUContract.ID); //把IOUState加上跟IOUStateContract的参考值,然后加到transactionBuilder
List<PublicKey> requiredSigners = ImmutableList.of(IOUState.getIssuer().getOwningKey(), owner.getOwningKey());
transactionBuilder.addCommand(command, requiredSigners); //step5,把命令加到tx
/* ============================================================================
* TODO 2 - Write our TokenContract to control token issuance!
* ===========================================================================*/
transactionBuilder.verify(getServiceHub());
FlowSession session = initiateFlow(owner);
SignedTransaction signedTransaction = getServiceHub().signInitialTransaction(transactionBuilder);
SignedTransaction fullySignedTransaction = subFlow(new CollectSignaturesFlow(signedTransaction,
singletonList(session)));
return subFlow(new FinalityFlow(fullySignedTransaction, singletonList(session)));
}
}
3.2 IOUIssueFlowResponder
package bootcamp;
import co.paralleluniverse.fibers.Suspendable;
import net.corda.core.flows.*;
import net.corda.core.transactions.SignedTransaction;
@InitiatedBy(IOUIssueFlow.class)
public class IOUIssuerFlowResponder extends FlowLogic<Void> {
private final FlowSession otherSide;
public IOUIssuerFlowResponder(FlowSession otherSide) {
this.otherSide = otherSide;
}
@Override
@Suspendable
public Void call() throws FlowException {
SignedTransaction signedTransaction = subFlow(new SignTransactionFlow(otherSide) {
@Suspendable
@Override
protected void checkTransaction(SignedTransaction stx) throws FlowException {
}
});
subFlow(new ReceiveFinalityFlow(otherSide, signedTransaction.getId()));
return null;
}
}