什么是TaPos
全称:Transaction as Proof of Stake,基于交易的权益证明机制。 大白话:这笔交易所基于的证明。 啥意思? 就是说,在区块链的场景当中,每一过往的笔交易都基于一个区块。因为区块链当中所有的交易都是被打包到一个个区块当中的,如果这是一笔成功的交易,那它一定是存在于某一个特定的区块当中。 另外,每一笔交易都有一个唯一的Hash,保证这笔交易的唯一性。那就破案了,这里的证明就是指:区块。
有什么实际作用
- 防止有不包含区块引用的交易被重放到某个分叉上,这样能避免不是该分叉的区块被添加到该分叉。
- 告诉用户该块是在哪个分支上面。
这个需要事先了解切链场景,才能说明这个问题。
先说分叉:
在区块链网络当中,如果同时收到相同高度的区块就,链就会分叉,你可以理解为git提交记录,从master分支中切出一个新的分叉,会有人基于这个分叉不断的提交代码。 在区块链的角度也是一样的,如果区块高度都是 1000 和 1000',那这个时候链就会出现分叉。
在哪里用
一般在验证广播交易阶段使用。
构建交易
构建一笔交易时,会将这笔交易所需要引用的区块高度带上。 交易构建之后会被广播到对应的FullNode节点。
代码语言:javascript复制private void setTransaction(TransactionCapsule trx) {
try {
BlockId blockId = chainBaseManager.getHeadBlockId();
if ("solid".equals(Args.getInstance().getTrxReferenceBlock())) {
blockId = chainBaseManager.getSolidBlockId();
}
trx.setReference(blockId.getNum(), blockId.getBytes());
long expiration = chainBaseManager.getHeadBlockTimeStamp() Args.getInstance()
.getTrxExpirationTimeInMilliseconds();
trx.setExpiration(expiration);
trx.setTimestamp();
} catch (Exception e) {
logger.error("Create transaction capsule failed.", e);
}
}
验证TaPos
接收到广播过来的交易后,会验证构建交易时记录的Tapos的区块高度,如果不是有资质的区块高度,就丢弃交易。
代码语言:javascript复制
void validateTapos(TransactionCapsule transactionCapsule) throws TaposException {
byte[] refBlockHash = transactionCapsule.getInstance()
.getRawData().getRefBlockHash().toByteArray();
byte[] refBlockNumBytes = transactionCapsule.getInstance()
.getRawData().getRefBlockBytes().toByteArray();
try {
// 通过交易中的区块高度,到最近的区块中去查找是否存在
byte[] blockHash = chainBaseManager.getRecentBlockStore().get(refBlockNumBytes).getData();
if (!Arrays.equals(blockHash, refBlockHash)) {
String str = String.format(
"Tapos failed, different block hash, %s, %s , recent block %s, "
"solid block %s head block %s",
ByteArray.toLong(refBlockNumBytes), Hex.toHexString(refBlockHash),
Hex.toHexString(blockHash),
chainBaseManager.getSolidBlockId().getString(),
chainBaseManager.getHeadBlockId().getString()).toString();
logger.info(str);
throw new TaposException(str);
}
} catch (ItemNotFoundException e) {
String str = String
.format("Tapos failed, block not found, ref block %s, %s , solid block %s head block %s",
ByteArray.toLong(refBlockNumBytes), Hex.toHexString(refBlockHash),
chainBaseManager.getSolidBlockId().getString(),
chainBaseManager.getHeadBlockId().getString()).toString();
logger.info(str);
throw new TaposException(str);
}
}
总结
在去中心化的环境当中,各节点之间数据是独立的,也没有一个中心化的节点可以提供参照数据,还要保证是非切链的交易。 这样的场下,要保证刚创建的这笔交易是基于有交主链上的交易,就可以通过获取已经固化的区块,作为依据,这样就可以保证这笔交易是基于主链上的交易。