Fabric智能合约开发基础
Fabric智能合约开发基础
区块链网络的核心是智能合约。
智能合约定义业务对象的不同状态,并管理对象在不同状态之间变化的过程。
在 PaperNet 案例中,商业票据智能合约中的代码定义了商业票据的有效状态,以及将票据从一种状态状态转变为另一种状态的交易逻辑。
本案例实现了商业票据中最简单的三个功能:发行、购买、兑换。
PaperNet 是一个商业票据网络,允许适当授权的参与者发行,交易,兑换和估价商业票据。PaperNet 商业票据网络。六个组织目前使用 PaperNet 网络发行,购买,出售,兑换和估价商业票据。MagentoCorp 发行和兑换商业票据。 DigiBank, BigFund,BrokerHouse 和 HedgeMatic 互相交易商业票据。RateM 为商业票据提供各种风险衡量标准。
目录
合约类
扩展自 Hyperledger Fabric
Contract
类,使用Contract类的内置功能,例如自动方法调用,每个交易上下文,交易处理器,和类共享状态等。
1 |
|
交易定义
Java 标注
@Transaction
用于标记该方法为交易定义;无论何时调用此合约来发行
商业票据,都会调用该方法
发行交易:
1 |
|
CommercialPaperContext ctx
称为交易上下文,默认情况下,它维护与交易逻辑相关的每个合约和每个交易的信息。
购买交易:
1 | Txn = buy |
1 |
|
兑换交易:
1 | Txn = redeem |
1 |
|
交易逻辑
发行交易 导致
issue
方法被传递调用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public CommercialPaper issue(CommercialPaperContext ctx,
String issuer,
String paperNumber,
String issueDateTime,
String maturityDateTime,
int faceValue) {
System.out.println(ctx);
// create an instance of the paper
CommercialPaper paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime, maturityDateTime,
faceValue,issuer,"");
// Smart contract, rather than paper, moves paper into ISSUED state
paper.setIssued();
// Newly issued paper is owned by the issuer
paper.setOwner(issuer);
System.out.println(paper);
// Add the paper to the list of all similar commercial papers in the ledger
// world state
ctx.paperList.addPaper(paper);
// Must return a serialized paper to caller of smart contract
return paper;
}逻辑如下:
- 获取交易输入变量
- 创建新的商业票据
paper
- 使用
paperList
将其添加到所有商业票据的列表中 - 将新的商业票据作为交易响应返回
购买交易
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public CommercialPaper buy(CommercialPaperContext ctx,
String issuer,
String paperNumber,
String currentOwner,
String newOwner,
int price,
String purchaseDateTime) {
// Retrieve the current paper using key fields provided
String paperKey = State.makeKey(new String[] { paperNumber });
CommercialPaper paper = ctx.paperList.getPaper(paperKey);
// Validate current owner
if (!paper.getOwner().equals(currentOwner)) {
throw new RuntimeException("Paper " + issuer + paperNumber + " is not owned by " + currentOwner);
}
// First buy moves state from ISSUED to TRADING
if (paper.isIssued()) {
paper.setTrading();
}
// Check paper is not already REDEEMED
if (paper.isTrading()) {
paper.setOwner(newOwner);
} else {
throw new RuntimeException(
"Paper " + issuer + paperNumber + " is not trading. Current state = " + paper.getState());
}
// Update the paper
ctx.paperList.updatePaper(paper);
return paper;
}逻辑如下:
- 检查一些前提条件
- 设置新拥有者
- 更新账本上的商业票据
- 并将更新的商业票据作为交易响应返回
兑换交易类似
对象的表示
上面的合约、运行逻辑已经有了,但是这些代码怎么工作?
参考 CommercialPaper 类 , 该类包含商业票据状态的内存表示。
1 |
|
createInstance
方法使用提供的参数初始化一个新的商业票据。
1 | public static CommercialPaper createInstance(String issuer, String paperNumber, String issueDateTime, |
需要注意的几个要点:
这是一个内存中的表示; 我们稍后会看到它如何在帐本上显示。
CommercialPaper
类扩展了State
类。State
是一个应用程序定义的类,它为状态创建一个公共抽象。所有状态都有一个它们代表的业务对象类、一个复合键,可以被序列化和反序列化,等等。当我们在帐本上存储多个业务对象类型时,State
可以帮助我们的代码更清晰。检查state.js
文件中的State
类。票据在创建时会计算自己的密钥,在访问帐本时将使用此密钥。密钥由
issuer
和paperNumber
的组合形成。1
2
3
4constructor(obj) {
super(CommercialPaper.getClass(), [obj.issuer, obj.paperNumber]);
Object.assign(this, obj);
}票据通过交易而不是票据类变更到
ISSUED
状态。
访问账本
参考 PaperList 类 , 此工具类用于管理 Hyperledger Fabric 状态数据库中的所有 PaperNet 商业票据。
1 | import org.example.ledgerapi.StateList; |
与 CommercialPaper
类一样,此类扩展了应用程序定义的 StateList
类,该类为一系列状态创建了一个通用抽象——在本例中是 PaperNet 中的所有商业票据。
StateList
类使用 Fabric API addState()
将商业票据作为状态数据写在帐本中。
帐本中的每个状态数据都需要以下两个基本要素:
- 键(Key): 由
createCompositeKey()
使用固定名称和state
密钥形成。在构造PaperList
对象时分配了名称,state.getSplitKey()
确定每个状态的唯一键。 - 数据(Data): 只是商业票据状态的序列化形式,使用
State.serialize()
方法创建。State
类使用 JSON 对数据进行序列化和反序列化,并根据需要使用 State 的业务对象类,在我们的例子中为CommercialPaper
,在构造PaperList
对象时再次设置。
注意 StateList
不存储有关单个状态或状态总列表的任何内容——它将所有这些状态委托给 Fabric 状态数据库。StateList getState()
和 updateState()
方法以类似的方式工作。
参考: