什么是TaPos

全称:Transaction as Proof of Stake,基于交易的权益证明机制。
大白话:这笔交易所基于的证明。
啥意思?
就是说,在区块链的场景当中,每一过往的笔交易都基于一个区块。因为区块链当中所有的交易都是被打包到一个个区块当中的,如果这是一笔成功的交易,那它一定是存在于某一个特定的区块当中。
另外,每一笔交易都有一个唯一的Hash,保证这笔交易的唯一性。那就破案了,这里的证明就是指:区块

有什么实际作用

  1. 防止有不包含区块引用的交易被重放到某个分叉上,这样能避免不是该分叉的区块被添加到该分叉。
  2. 告诉用户该块是在哪个分支上面。

这个需要事先了解切链场景,才能说明这个问题。

先说分叉:

在区块链网络当中,如果同时收到相同高度的区块就,链就会分叉,你可以理解为git提交记录,从master分支中切出一个新的分叉,会有人基于这个分叉不断的提交代码。
在区块链的角度也是一样的,如果区块高度都是 1000 和 1000',那这个时候链就会出现分叉。

在哪里用

一般在验证广播交易阶段使用。

构建交易

构建一笔交易时,会将这笔交易所需要引用的区块高度带上。
交易构建之后会被广播到对应的FullNode节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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的区块高度,如果不是有资质的区块高度,就丢弃交易。

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

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);
}
}

总结

在去中心化的环境当中,各节点之间数据是独立的,也没有一个中心化的节点可以提供参照数据,还要保证是非切链的交易。
这样的场下,要保证刚创建的这笔交易是基于有交主链上的交易,就可以通过获取已经固化的区块,作为依据,这样就可以保证这笔交易是基于主链上的交易。