比特幣中的默克爾樹Merkle

簡(jiǎn)介

Merkle Tree杖玲,通常也被稱作Hash Tree顿仇,顧名思義,就是存儲(chǔ)hash值的一棵樹摆马。Merkle樹的葉子是數(shù)據(jù)塊(例如臼闻,文件或者文件的集合)的hash值。非葉節(jié)點(diǎn)是其對(duì)應(yīng)子節(jié)點(diǎn)串聯(lián)字符串的hash囤采。


默克爾樹

比特幣中對(duì)應(yīng)的默克爾樹

  • 比特幣中區(qū)塊的定義結(jié)構(gòu)


    CBlock
//
// Nodes collect new transactions into a block, hash them into a hash tree,
// and scan through nonce values to make the block's hash satisfy proof-of-work
// requirements.  When they solve the proof-of-work, they broadcast the block
// to everyone and the block is added to the block chain.  The first transaction
// in the block is a special one that creates a new coin owned by the creator
// of the block.
//
// Blocks are appended to blk0001.dat files on disk.  Their location on disk
// is indexed by CBlockIndex objects in memory.
//
class CBlock
{
public:
    // header
    int nVersion;
    uint256 hashPrevBlock;
    uint256 hashMerkleRoot;
    unsigned int nTime;
    unsigned int nBits; // 記錄本區(qū)塊難度
    unsigned int nNonce;

    // network and disk
    vector<CTransaction> vtx;

    // memory only
    mutable vector<uint256> vMerkleTree;

    // 對(duì)應(yīng)的方法省略述呐,后面用到會(huì)單獨(dú)講解
};
  • 構(gòu)建塊中交易對(duì)應(yīng)的默克爾樹
    對(duì)應(yīng)的代碼如下:
uint256 CBlock::BuildMerkleTree() const
    {
        vMerkleTree.clear();
        foreach(const CTransaction& tx, vtx)
            vMerkleTree.push_back(tx.GetHash());
        int j = 0;
        for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
        {
            for (int i = 0; i < nSize; i += 2)
            {
                int i2 = min(i+1, nSize-1);
                vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),
                                           BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
            }
            j += nSize;
        }
        return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
    }

舉一個(gè)例子,假設(shè)對(duì)應(yīng)的block中有A,B,C,D四個(gè)交易記錄(這些交易記錄保存在block中的vector<CTransaction> vtx)


假設(shè)塊中對(duì)應(yīng)的交易vtx中內(nèi)容有A,B,C,D四個(gè)交易記錄

則使用上述構(gòu)建默克爾樹的方法BuildMerkleTree蕉毯,則使得block中對(duì)應(yīng)的默克爾樹結(jié)構(gòu)體vector<uint256> vMerkleTree如下圖所示:


對(duì)上述交易構(gòu)建的默克爾樹結(jié)果

默克爾樹對(duì)應(yīng)的樹形圖
  • 根據(jù)交易在塊中的索引查詢其對(duì)應(yīng)的默克爾樹分支

獲取對(duì)應(yīng)的默克爾樹的分支在CBlock中對(duì)應(yīng)的方法GetMerkleBranch代碼如下:

    vector<uint256> CBolck::GetMerkleBranch(int nIndex) const
    {
        if (vMerkleTree.empty())
            BuildMerkleTree();
        vector<uint256> vMerkleBranch;
        int j = 0;
        for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
        {
            int i = min(nIndex^1, nSize-1);
            vMerkleBranch.push_back(vMerkleTree[j+i]);
            nIndex >>= 1;
            j += nSize;
        }
        return vMerkleBranch;
    }

那么對(duì)應(yīng)于上面的例子乓搬,如果我想得到在交易列表vtx中A對(duì)應(yīng)的默克爾樹分支,則對(duì)應(yīng)函數(shù)GetMerkleBranch(0)對(duì)應(yīng)的返回結(jié)果列表如下所示:
交易索引0對(duì)應(yīng)的默克爾樹分支

紅色節(jié)點(diǎn)對(duì)應(yīng)的就是節(jié)點(diǎn)A的默克爾樹分支
  • 驗(yàn)證對(duì)應(yīng)的交易是否在默克爾樹中
    驗(yàn)證某個(gè)節(jié)點(diǎn)是否在默克爾樹中代虾,在CBlock中對(duì)應(yīng)的方法代碼如下:
 static uint256 CBlock::CheckMerkleBranch(uint256 hash, const vector<uint256>& vMerkleBranch, int nIndex)
    {
        if (nIndex == -1)
            return 0;
        foreach(const uint256& otherside, vMerkleBranch)
        {
            if (nIndex & 1)
                hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
            else
                hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
            nIndex >>= 1;
        }
        return hash;
    }

驗(yàn)證CheckMerkleBranch方法返回的結(jié)果是否和CBlock中對(duì)應(yīng)的默克爾樹中對(duì)應(yīng)根的值一樣进肯,即如下面代碼所示:

if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pBlock->hashMerkleRoot)
            return 0;

對(duì)應(yīng)上面的例子對(duì)應(yīng)的驗(yàn)證過程如下圖所示:


驗(yàn)證第一步是得到節(jié)點(diǎn)E

驗(yàn)證第二步是得到節(jié)點(diǎn)G

比特幣交易對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)

交易對(duì)應(yīng)的類圖

對(duì)應(yīng)的代碼如下:

//
// The basic transaction that is broadcasted on the network and contained in
// blocks.  A transaction can contain multiple inputs and outputs.
//
class CTransaction
{
public:
    int nVersion;
    vector<CTxIn> vin;
    vector<CTxOut> vout;
    int nLockTime;
// 方法省略
};
//
// A transaction with a merkle branch linking it to the block chain
//
class CMerkleTx : public CTransaction
{
public:
    uint256 hashBlock;
    vector<uint256> vMerkleBranch;
    int nIndex;

    // memory only
    mutable bool fMerkleVerified;
// 方法省略
};

從類圖或代碼中可以看到CMerkleTx 中有一個(gè)屬性是vMerkleBranch棉磨,表示的是對(duì)應(yīng)的每一個(gè)默克爾交易都對(duì)應(yīng)一個(gè)默克爾樹分支江掩,因此對(duì)應(yīng)默克爾交易可以很快的驗(yàn)證這個(gè)交易是否在某個(gè)CBlock中。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乘瓤,一起剝皮案震驚了整個(gè)濱河市环形,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌馅扣,老刑警劉巖斟赚,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異差油,居然都是意外死亡拗军,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門蓄喇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來发侵,“玉大人,你說我怎么就攤上這事妆偏∪婿” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵钱骂,是天一觀的道長(zhǎng)叔锐。 經(jīng)常有香客問我挪鹏,道長(zhǎng),這世上最難降的妖魔是什么愉烙? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任讨盒,我火速辦了婚禮,結(jié)果婚禮上步责,老公的妹妹穿的比我還像新娘返顺。我一直安慰自己,他們只是感情好蔓肯,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布遂鹊。 她就那樣靜靜地躺著,像睡著了一般蔗包。 火紅的嫁衣襯著肌膚如雪秉扑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天气忠,我揣著相機(jī)與錄音邻储,去河邊找鬼。 笑死旧噪,一個(gè)胖子當(dāng)著我的面吹牛吨娜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播淘钟,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼宦赠,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了米母?” 一聲冷哼從身側(cè)響起勾扭,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铁瞒,沒想到半個(gè)月后妙色,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡慧耍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年身辨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芍碧。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡煌珊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泌豆,到底是詐尸還是另有隱情定庵,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站蔬浙,受9級(jí)特大地震影響猪落,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜敛滋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一许布、第九天 我趴在偏房一處隱蔽的房頂上張望兴革。 院中可真熱鬧绎晃,春花似錦、人聲如沸杂曲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)擎勘。三九已至咱揍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間棚饵,已是汗流浹背煤裙。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留噪漾,地道東北人硼砰。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像欣硼,于是被迫代替她去往敵國(guó)和親题翰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 作者 Kevin 簡(jiǎn)介:“比特幣技術(shù)進(jìn)階”由知名比特幣技術(shù)專家Kevin原創(chuàng)的三篇文章《比特幣交易構(gòu)成》诈胜、《時(shí)間...
    西部之歌閱讀 1,005評(píng)論 0 0
  • 一豹障、快速術(shù)語(yǔ)檢索 比特幣地址:(例如:1DSrfJdB2AnWaFNgSbv3MZC2m74996JafV)由一串...
    不如假如閱讀 15,997評(píng)論 4 87
  • 早上接一個(gè)老客戶的新車拋光打蠟,開了接車單焦匈,忘了寫價(jià)錢血公,到晚上才想起來。核心:沒走心缓熟,不在狀態(tài)累魔。
    王佳歡雪閱讀 289評(píng)論 0 0
  • 1、 晚上荚虚,安然躺在床上薛夜,腦子塞滿了各種事情,睡不著也不想睡版述,回想著今天和陳陽(yáng)在一起的所經(jīng)歷的事情梯澜,又想到后來他和...
    有趣的生活閱讀 342評(píng)論 0 2