
在 Web3.0 的发展过程中,区块链技术扮演者非常重要的作用。而在区块链中最基础的经济单元就是 token 了。Token 是“区块链技术”与“实体经济”体系相互作用的产物,也是驱动区块链社会经济发展的强大动力。
在区块链的 token 体系中,实体资产、虚拟资产的 token 化可以帮助实现资产上链,以及链上资产在区块链网络中实现点对点的自由交易。一个有价值的 Token 是构建区块链 Token 经济系统的核心[1]。同样的 token 也不仅限于一个特定的角色,也可以在其自身的生态系统中履行各种不同的角色。
在《商业区块链》一书中,威廉・穆贾雅提出了一个可以用 token 系统表示的事物的分类。他把区块链中可存储的事物的首字母组成了一个单词 “ATOMIC”[2]:
- 可编程的资产(assets)
- 可编程的信任(trust)
- 可编程的所有权(ownership)
- 可编程的货币(money)
*可编程的身份(identity)- 可编程的合同(contracts)
当然在不同的区块链平台中,创建 token 的方式及他们的特点又会有所不同。在以太坊中,通过编写一个创建 token 的智能合约,并在该智能合约中配置好 token 的名称、总量、精度、标识符号等属性,之后再部署并运行该智能合约就可以创建好一种 token 了。可以看到在以太坊中发布一个 ERC-20 token 是十分简单。也许正是由于在以太坊中发布 token 的便利性,才会有更多的项目选择在以太坊平台中构建。
但是,在 Corda 的生态中,token 又具备什么样的特点,以及它又是怎么发行的呢?

Token in Corda
-
Corda 中 token 有其唯一的发行者 (issuer) 和持有者 (holder)
在以太坊平台中发布 token 的方法中,我们是没有看到它对 token 发行者进行定义的。而在 Corda 中要发行一种 token,是需要定义它的发行者是谁的。以真实生活中的例子为例:央行发行了人民币,腾讯发行了 Q 币等,这里的央行、腾讯就是人民币和 Q 币的发行者。
可以发现当 token 有了发行者之后,我们就可以更好的对现实中的某些资产进行链上建模,这就会更有利于真实业务场景的实现。 -
Corda 中 token 是发行者和持有者之间的一中协议 (agreement)
在 Corda 中发行者不会平白无故的就发行了一种 token 或者转移了一笔 token 到某个持有者账户中的,而是双方就某些协议达成共识后才会触发的。例如:假设我们达成了 5 RMB 兑换 1 CordaToken 的共识。如果在这时,发行者确认我转账成功了 5RMB 之后,发行者才会发行 1 CordaToken 并转移给我。
Everything on Corda is an agreement.
-
Corda 中 token 从发行者的角度来看是负债,但从持有者的角度来看确是资产
由此可见,在 Corda 中的 token 就和现实中的 RMB 是类似的,它由央行发行,并在不同人之间进行转移。因此,和 RMB 类似,在 Corda 中 token 从不同视角来看,它既是负债,又是资产。 -
Corda 中的 token 可以在没有发行者参与签名的情况下进行 token 的转移
同样以人民币为例来看,我们在花钱的时候,是不需要得到央行的签名许可的,我们自己就可以决定花钱买什么东西,因为我们自己是这笔钱的持有者。在 Corda 中也是一样,在对 token 进行不同账户间的转移的时候,是不需要经过发行者的签名和参与就可以完成的。 -
Corda 中的 token 在实现上进行了良好的封装,仅暴露了发行(Issue),转移 (Move) 和赎回 (Redeem) 操作
当前来看,要在 Corda 中实现一种 token,最标准的方式就是采用 token-sdk,这是官方发布的可在 Corda 中创建和管理 token 的工具包。且该工具包中进行了比较好的封装,比如:token 的发行、转移和赎回操作,并且在 Corda 中对一种 token 而言,有且仅有这三种操作。
但 token-sdk 的高封装性,随之带来的就是低扩展性。例如:我们需要实现对一种 token 的冻结操作,我们就发现很难被实现。至于这两者孰轻孰重,可能还需要平衡后在做决定。
我们在实践中就遇到了这个问题,思考了好久都无法在 token-sdk 中实现对 token 的冻结功能的扩展。最后,只能通过新建了一种 LockedToken 来解决。
-
Corda 中的 token 只能由其发行者进行赎回操作,其他节点无此权限
在 Corda 中 token 不可避免的会离开 Corda 平台,例如用户将 Q币换回钱这样的过程就是如此。在 Corda 中,发生的这类操作被称为赎回操作。对于赎回操作来说,它就只能由其发行者进行赎回,就像人民币一样,我们只有权利进行钱的转移,但却没有权限发行人民币或废掉人民币。
如何基于 token-sdk 快速实现一个 ERC-20 token
那么在代码实现上如何才能快速实现一个类 ERC-20 这样的 FungibleToken 呢?可以先看一下代码。
// ** Create token **
TokenType myFixedToken = new TokenType(“CordaToken", 4);
IssuedTokenType issuedTokenType = new IssuedTokenType<>(issuer, myFixedToken); // 定义该中 token 的发行者(issuer)是谁
Amount amount = new Amount<>(10000, issuedTokenType);
FungibleToken fungibleToken = new FungibleToken(amount, holder);
// ** Issue token **(should call this on issuer node)
subFlow(new IssueTokens(ImmutableList.of(fungibleToken), ImmutableList.of(holder)));
// ** Move token **(should call this on holder node)
subFlow(new MoveFungibleTokens(PartyAndAmount(newHolder.legalIdentity(), amount))); // 将 token 转移给新的持有者(newHolder)
// ** Redeem token ** (should call this on issuer node)
subFlow(new RedeemFungibleTokens(amount, issuer));
可以看到,实现一个 token 全生命周期的代码实现是非常简洁的。总体来看就是以下 4 步:
-
创建 token
在创建 token 时,需要定义 token 的名称、精度、发行者和发行总量。 -
发行 token
通过 token-sdk 的封装,在发行者节点上调用 IssueTokens 方法就可以发行 token 了。只需在参数中传入创建好的 token 以及 token 的持有者即可。 -
转移 token
同样通过 token-sdk 的封装,在 token 持有者的节点上调用 MoveFungibleTokens 方法并传入新持有者的 Party 以及需转移 token 的总量就可以成功转移 token 了。 -
赎回 token
对于赎回操作也是一样,只需在发行者节点上调用 RedeemFungibleTokens 方法并传入需要赎回的 token 总量和发行者节点名就可以了。
设计约束
到这里你可能会认为在 Corda 中实现一种 token 真的好简单!确实是这样,不过要想真正维护好现实业务场景和区块链上建模的业务场景之间的一致性就没那么简单了。
简单来说,我们在实践中主要实现了一个这样的场景:用户通过支付宝扫码付款自动购买相应数量的 CordaToken;同样用户也可以在任何时候将 Corda 中的 CordaToken 换为法币提取出来。就在这个场景中,我们就经常遇到这样的问题:支付宝已经转账成功了,但查看 Corda 账户,token 并没有到账;用户已经调用了将 token 换为人民币的请求了,且其 Corda 账户上的 token 已经没有了,但是支付宝账户中的钱却没有到账。维护支付宝中钱和 Corda 账户中 token 的数据一致性着实让我们发愁了一阵。
后来,团队共同梳理出了如下 3 条设计约束,共同树立起了这样的 mindset ,对我们项目之后的完成有着重要作用。
- 由于 CordaToken 只可由现实世界的现金来做交换,因此 Corda 中 token 的总额和 token 发行者的账户中的现金总额数量必须相同。
- 如果现实世界中发生了现金转移,那么现实世界的交易 ID 和 Corda 中的交易ID之间应该始终存在着映射关系。
- 在 Corda 中,任何已发生的事实都应该先在现实世界发生之后才能被记录到 Corda 中。
其实这三条设计约束看起来蛮简单的,也比较好理解。就是要时刻将现实中的交易和 Corda 中的交易进行映射,将支付宝的交易 ID 和 Corda 中 token 发行的交易 ID 联系起来,这样就可以知道这一笔 token 发行的原因是由于什么。同样支付宝付款是 token 发行的唯一依据,因此 Corda 中的 token 数量就一定要和发行者支付宝账户的钱的总数量相同(在一定汇率下的相同)。最后,Corda 中实现的业务逻辑是现实中业务场景的一个映射,这也就意味着 Corda 中事实记录的时间要在现实世界的事件发生之后。
总结
在 Corda 中通过 token-sdk 可以快速的构建一款涉及到价值转移的 CorDapp,但若要更好的保证业务逻辑的一致性,更重要的是能定义好连接现实与Corda 之间的约束条件。
网友评论