以太坊C++源碼解析(六)以太坊The DAO分叉

剛寫了一篇區(qū)塊鏈同步的文章,發(fā)現(xiàn)里面有一些DAO分叉的代碼繞不過去,需要專門寫一篇來簡單介紹一下這次以太坊歷史上著名的分叉事件。

區(qū)塊鏈分叉分為硬分叉和軟分叉,區(qū)別請自行谷歌,The DAO分叉是一次硬分叉。

The DAO是一個存在于以太坊區(qū)塊鏈智能合約中的去中心化組織,這個組織于2016年4月30日起通過合約發(fā)起眾籌,短短28天就籌集了相當于1.5億美金的以太幣。然而很不幸的是合約本身存在漏洞,更不幸的是被一個(多個?)聰明的黑客利用了,6月17日他(他們?)從中盜走了價值5000萬美元的以太幣。
巨大的損失讓The DAO和全球投資者難以承受,以V神為代表的7人組決定采取反制措施,當初采取軟分叉還是硬分叉在社區(qū)是有爭議的,但是經(jīng)過各種厲害權衡,硬分叉的方案被確定了下來。

這次分叉本身也存在很大爭議,相當于網(wǎng)游中的回檔,直接宣布黑客所擁有的以太幣是無效的,簡單粗暴,但是違反了區(qū)塊鏈上已打包交易任何人無法篡改的原則,人為地干預區(qū)塊鏈也違背了去中心化的精神。因此分叉后以太坊就此分裂,由V神和大多數(shù)人支持的一支叫以太坊(ETH),另一只叫以太經(jīng)典(ETC)。ETC由于缺乏官方的支持,處于弱勢,但是還是有一批堅守區(qū)塊鏈精神的人在維持。

這次硬分叉的方案是這樣的:

  • 分叉的節(jié)點位于1920000高度的區(qū)塊,該區(qū)塊的extra data設為dao-hard-fork (Hex:0x64616f2d686172642d666f726b),作為ETH和ETC區(qū)分的標志。
  • 將DAO賬戶的所有余額全部轉到一個退款合約賬戶上。

在1920000塊上總計有58個DAO和子DAO合約賬戶的共12,001,961.845205763407115004 ETH被轉到了退款合約賬戶上。
這些轉賬沒有在塊交易中體現(xiàn),而是直接被寫入源碼中!
你可以在Etherscan上找到這個區(qū)塊:區(qū)塊1920000

下面我們來看看這個分叉在源碼中的體現(xiàn):

  • 首先是記錄了分叉點。libethashseal\genesis\mainNetwork.cpp里記錄了mainnet的一些參數(shù),其中就有"daoHardforkBlock": "0x1d4c00",0x1d4c00就是1920000!libethashseal\genesis目錄下的ropsten.cpp里記錄了ropsten測試鏈的參數(shù),可以看到ropstendaoHardforkBlock值為0,表示沒有分叉。
  • Block::performIrregularModifications()函數(shù)中完成了轉賬操作。
void Block::performIrregularModifications()
{
    u256 const& daoHardfork = m_sealEngine->chainParams().daoHardforkBlock;
    if (daoHardfork != 0 && info().number() == daoHardfork)
    {
        Address recipient("0xbf4ed7b27f1d666546e30d74d50d173d20bca754");
        Addresses allDAOs = childDaos();
        for (Address const& dao: allDAOs)
            m_state.transferBalance(dao, recipient, m_state.balance(dao));
        m_state.commit(State::CommitBehaviour::KeepEmptyAccounts);
    }
}

這段代碼判斷如果當前塊高度為1920000時,遍歷所有的DAO賬號,將所有余額轉到recipient中,recipient就是那個退款合約賬戶。
分叉影響也波及到了區(qū)塊鏈同步模塊:

  • 收到peer的StatusPacket包后,需要進行一個DAO challenge。
    BlockChainSync::onPeerStatus()中有如下代碼:
// Before starting to exchange the data with the node, let's verify that it's on our chain
if (!requestDaoForkBlockHeader(_peer))
{
    // DAO challenge not needed
    syncPeer(_peer, false);
}

BlockChainSync::requestDaoForkBlockHeader()函數(shù)實現(xiàn)為:

bool BlockChainSync::requestDaoForkBlockHeader(std::shared_ptr<EthereumPeer> _peer)
{
    // DAO challenge
    unsigned const daoHardfork = static_cast<unsigned>(host().chain().sealEngine()->chainParams().daoHardforkBlock);
    if (daoHardfork == 0)
        return false;

    m_daoChallengedPeers.insert(_peer);
    _peer->requestBlockHeaders(daoHardfork, 1, 0, false);
    return true;
}

對于mainnet來說,daoHardfork為1920000,因此它首先需要向該peer請求這個分叉塊頭。

  • 收到對方的BlockHeadersPacket包后還需要校驗:
if (m_daoChallengedPeers.find(_peer) != m_daoChallengedPeers.end())
{
    if (verifyDaoChallengeResponse(_r))
        syncPeer(_peer, false);
    else
        _peer->disable("Peer from another fork.");

    m_daoChallengedPeers.erase(_peer);
    return;
}

校驗的代碼位于BlockChainSync::verifyDaoChallengeResponse()函數(shù)中:

bool BlockChainSync::verifyDaoChallengeResponse(RLP const& _r)
{
    if (_r.itemCount() != 1)
        return false;

    BlockHeader info(_r[0].data(), HeaderData);
    return info.number() == host().chain().sealEngine()->chainParams().daoHardforkBlock &&
        info.extraData() == fromHex("0x64616f2d686172642d666f726b");
}

可以看到校驗的方法很簡單,就是看塊頭的extraData里記錄的是不是dao-hard-fork (Hex:0x64616f2d686172642d666f726b),如果是則說明是ETH,可以繼續(xù)同步,否則是ETC,禁用該peer。
節(jié)點通過DAO challenge后就可以按正常流程同步了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 以太坊(Ethereum ):下一代智能合約和去中心化應用平臺 翻譯:巨蟹 、少平 譯者注:中文讀者可以到以太坊愛...
    車圣閱讀 3,923評論 1 7
  • 夏天如它的黑夜那樣短,轉瞬即過。隨之而來的便是清閑的的秋。 秋天,是樹葉的夢,秋把樹葉...
    LONGJI閱讀 216評論 0 0
  • 文/Barnabas|圖/網(wǎng)絡 「這感覺,這酸爽??!」昨晚9點多跑完步,我站在露臺上吹著涼風,心里感觸。 昨晚的跑...
    夢想教練Barnabas閱讀 777評論 0 2
  • 使用xgboost多分類模型識別手寫數(shù)字 數(shù)據(jù)下載牛客網(wǎng)的手寫數(shù)字識別 當然啦! 在許多網(wǎng)站上都有著類似的數(shù)據(jù)。 ...
    追風少年1899閱讀 6,169評論 0 6
  • 近三個月晚上22:00甚至24:00以后到家已經(jīng)是一種節(jié)奏。重新創(chuàng)業(yè)重在修煉,過程中會遇到無數(shù)的問題,我努力轉向對...
    寧寧1984閱讀 122評論 4 4

友情鏈接更多精彩內容