一個區塊中的交易總數是一個重要的資訊,我們展示了如何在沒有受信任的第三方的情況下獲得它,這在以前被認為是不可能的,
范圍
讓我們將 Merkle 路徑的長度表示為 n,葉子的數量,即一個區塊中的交易數量,介于 2^(n-1) + 1 和 2^n 之間,這是因為高度為 n 的滿二叉樹1 恰好有 2^n 個葉子,Merkle 路徑的長度與 Merkle 樹的高度相同,

確切數字
查找最后一筆交易
在上一篇文章中,我們訪問了區塊中的第一個 coinbase 交易,如果我們還可以訪問最后一筆交易,我們就可以推斷出交易總數,我們可以通過驗證其 Merkle 路徑上的所有節點都在右分支上來識別第一個/最左邊的交易,類似地,通過要求所有 Merkle 路徑節點都在左分支上,找到最后/最右邊的交易看上去也很簡單合理,但這可能并不總是正確的,
如果我們有一個滿的 Merkle 樹,那么最后一筆交易的 Merkle 路徑上的所有節點確實都在左分支上,如下所示,

但是,當樹不滿時,情況并非如此,
例如,下面的樹有 5 個葉子,最后一個交易的 Merkle 路徑由所有顏色為橙色的節點組成,其中兩個在右邊的樹枝上,只有最上面的一個在左邊,

為了克服這個問題,我們注意到當 Merkle 樹的任何單層中有奇數個節點時,最后一個節點被復制,這意味著,如果最后一筆交易的 Merkle 路徑上的任何節點在右分支上,則必須從當前的左分支復制它,如下圖所示,

下面的代碼直接實作了演算法,
// is txid the last transaction in a block
static function lastTxInBlock(Sha256 txid, BlockHeader bh, MerkleProof merkleproof) : bool {
bool last = true;
Sha256 root = txid;
loop (MerklePath.DEPTH) : i {
Node node = merkleproof[i];
if(node.left != MerklePath.INVALID_NODE) { // s is valid
// if node on the merkle path is on the right, it must be a duplicate
// if node on the merkle path is on the left, it must NOT be a duplicate
if (node.left != MerklePath.LEFT_NODE && node.hash != root || node.left == MerklePath.LEFT_NODE && node.hash == root) {
last = false;
}
root = node.left == MerklePath.LEFT_NODE ? hash256(node.hash + root) : hash256(root + node.hash);
}
}
return last && root == bh.merkleRoot;
}
從默克爾路徑到交易索引
為了匯出交易的索引,我們遵循從根到代表它的葉子的 Merkle 路徑,當路徑上的一個節點在左分支上時,我們向右走(即二進制1);否則,我們向左走(二進制 0),容易看出,我們可以通過這種方式獲得其索引的二進制表示,在下面的示例中,我們將此規則應用于最后一筆交易,然后一直向右走,得到二進制的 111,這正是它的十進制索引 7,

此代碼如下所示:
// calculate a tx's index in a block from its merkle path
// goes from top to bottom, the path basically encodes the index in binary form
// left/L means 1, and right/R 0: e.g., (L, R, L) denotes 101 in binary, and 5 in decimal
static function txIndex(MerkleProof merkleproof) : int {
int sum = 0;
// traverse the path from top to bottom
loop (MerklePath.DEPTH) : i {
Node node = merkleproof[MerklePath.DEPTH - i - 1];
if(node.left != MerklePath.INVALID_NODE ) {
sum *= 2;
if (node.left == MerklePath.LEFT_NODE) {
sum++;
}
}
}
return sum;
}
獲取交易總數
最后,我們將上面的兩個函式應用于 blockTxCount() 函式中,以獲取某個區塊內包含的準確交易數量,
// get number of transactions in a block
static function blockTxCount(BlockHeader bh, Sha256 lastTxid, MerklePath merklePath) : int {
// ensure this tx is indeed the last one
require(lastTxInBlock(lastTxid, bh, merklePath));
return txIndex(merklePath) + 1;
}
總結
一旦我們可以訪問一個區塊中的交易數量,我們就可以使用它來構建以前被認為不可能的智能合約,
我們僅在下面列出幾個示例:
- 放置一個僅在一個區塊包含超過 100 萬筆交易時才支付的賞金合約,以贊助壓力測驗,
- 結合之前獲得的時間資訊,無論是區塊頭中的時間戳還是區塊高度,都可以忠實地計算每秒交易量(TPS)并在合約中使用,例如,只有在 TPS 達到 100,000 時才解鎖的合約,
我們期待看到您能提出什么樣的令人興奮的新合約,
致謝
這篇文章的靈感來自 shilch 的作業,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/392188.html
標籤:區塊鏈
