Derek解读Bytom源码-创世区块

作者:Derek

简介

Github地址:https://github.com/Bytom/bytom

Gitee地址:https://gitee.com/BytomBlockchain/bytom

本章介绍Derek解读-Bytom源码分析-创世区块

作者使用MacOS操作系统,其他平台也大同小异

Golang Version: 1.8

创世区块介绍

区块链里的第一个区块创被称为创世区块。它是区块链里面所有区块的共同祖先。

在比原链中创世区块被硬编码到bytomd中,每一个比原节点都始于同一个创世区块,这能确保创世区块不会被改变。每个节点都把创世区块作为区块链的首区块,从而构建了一个安全的、可信的区块链。

获取创世区块

./bytomcli get-block 0
{
  "bits": 2161727821137910500,
  "difficulty": "15154807",
  "hash": "a75483474799ea1aa6bb910a1a5025b4372bf20bef20f246a2c2dc5e12e8a053",
  "height": 0,
  "nonce": 9253507043297,
  "previous_block_hash": "0000000000000000000000000000000000000000000000000000000000000000",
  "size": 546,
  "timestamp": 1524549600,
  "transaction_merkle_root": "58e45ceb675a0b3d7ad3ab9d4288048789de8194e9766b26d8f42fdb624d4390",
  "transaction_status_hash": "c9c377e5192668bc0a367e4a4764f11e7c725ecced1d7b6a492974fab1b6d5bc",
  "transactions": [
    {
      "id": "158d7d7c6a8d2464725d508fafca76f0838d998eacaacb42ccc58cfb0c155352",
      "inputs": [
        {
          "amount": 0,
          "arbitrary": "496e666f726d6174696f6e20697320706f7765722e202d2d204a616e2f31312f323031332e20436f6d707574696e6720697320706f7765722e202d2d204170722f32342f323031382e",
          "asset_definition": {},
          "asset_id": "0000000000000000000000000000000000000000000000000000000000000000",
          "type": "coinbase"
        }
      ],
      "outputs": [
        {
          "address": "bm1q3jwsv0lhfmndnlag3kp6avpcq6pkd3xy8e5r88",
          "amount": 140700041250000000,
          "asset_definition": {},
          "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
          "control_program": "00148c9d063ff74ee6d9ffa88d83aeb038068366c4c4",
          "id": "e3325bf07c4385af4b60ad6ecc682ee0773f9b96e1cfbbae9f0f12b86b5f1093",
          "position": 0,
          "type": "control"
        }
      ],
      "size": 151,
      "status_fail": false,
      "time_range": 0,
      "version": 1
    }
  ],
  "version": 1
}

使用bytomcli客户端查询高度为0的区块信息。我们可以看到以上输出结果。

  • bits: 目标值,挖矿时计算的hash之后要小于等于的目标值则新块构建成功
  • difficulty: 难度值,矿工找到下一个有效区块的难度。该参数并不存储在区块链上,是由bits计算得出
  • hash: 当前区块hash
  • height: 当前区块高度
  • nonce: 随机数,挖矿时反复使用不同的nonce来生成不同哈希值
  • previous_block_hash: 当前区块的父区块hash值
  • size: 当前区块的字节数
  • timestamp: 出块时间
  • transaction_merkle_root: 创世区块的merkle树根节点
  • transactions: 当前块中的utxo交易

由于创世区块是第一个块,创世区块的父区块,也就是previous_block_hash参数,默认情况下为0000000000000000000000000000000000000000000000000000000000000000

时间戳timestamp为1524549600,时间为2018-04-24 14:00:00也就是比原链上主网的时间。

源码分析

获取区块链状态

** protocol/protocol.go **

func NewChain(store Store, txPool *TxPool) (*Chain, error) {
    // ...
    storeStatus := store.GetStoreStatus()
    if storeStatus == nil {
        if err := c.initChainStatus(); err != nil {
            return nil, err
        }
        storeStatus = store.GetStoreStatus()
    }
    // ...
}

当我们第一次启动比原链节点时,store.GetStoreStatus会从db中获取存储状态,获取存储状态的过程是从LevelDB中查询key为blockStore的数据,如果查询出错则认为是第一次运行比原链节点,那么就需要初始化比原主链。

初始化主链

** protocol/protocol.go **

func (c *Chain) initChainStatus() error {
    genesisBlock := config.GenesisBlock()
    txStatus := bc.NewTransactionStatus()
    for i := range genesisBlock.Transactions {
        txStatus.SetStatus(i, false)
    }

    if err := c.store.SaveBlock(genesisBlock, txStatus); err != nil {
        return err
    }

    utxoView := state.NewUtxoViewpoint()
    bcBlock := types.MapBlock(genesisBlock)
    if err := utxoView.ApplyBlock(bcBlock, txStatus); err != nil {
        return err
    }

    node, err := state.NewBlockNode(&genesisBlock.BlockHeader, nil)
    if err != nil {
        return err
    }
    return c.store.SaveChainStatus(node, utxoView)
}

初始化主链有几步操作:

  • config.GenesisBlock()获取创世区块
  • 设置创世区块中所有交易状态
  • 存储创世区块到LevelDB
  • state.NewUtxoViewpoint()用于临时小部分utxo状态存储集合
  • 实例化BlockNode,BlockNode用于选择最佳链作为主链
  • 保存最新主链状态

被硬编码的创世区块

** config/genesis.go **

func genesisTx() *types.Tx {
    contract, err := hex.DecodeString("00148c9d063ff74ee6d9ffa88d83aeb038068366c4c4")
    if err != nil {
        log.Panicf("fail on decode genesis tx output control program")
    }

    txData := types.TxData{
        Version: 1,
        Inputs: []*types.TxInput{
            types.NewCoinbaseInput([]byte("Information is power. -- Jan/11/2013. Computing is power. -- Apr/24/2018.")),
        },
        Outputs: []*types.TxOutput{
            types.NewTxOutput(*consensus.BTMAssetID, consensus.InitialBlockSubsidy, contract),
        },
    }
    return types.NewTx(txData)
}

func mainNetGenesisBlock() *types.Block {
    tx := genesisTx()
    txStatus := bc.NewTransactionStatus()
    txStatus.SetStatus(0, false)
    txStatusHash, err := bc.TxStatusMerkleRoot(txStatus.VerifyStatus)
    if err != nil {
        log.Panicf("fail on calc genesis tx status merkle root")
    }

    merkleRoot, err := bc.TxMerkleRoot([]*bc.Tx{tx.Tx})
    if err != nil {
        log.Panicf("fail on calc genesis tx merkel root")
    }

    block := &types.Block{
        BlockHeader: types.BlockHeader{
            Version:   1,
            Height:    0,
            Nonce:     9253507043297,
            Timestamp: 1524549600,
            Bits:      2161727821137910632,
            BlockCommitment: types.BlockCommitment{
                TransactionsMerkleRoot: merkleRoot,
                TransactionStatusHash:  txStatusHash,
            },
        },
        Transactions: []*types.Tx{tx},
    }
    return block
}

mainNetGenesisBlock主要有如下操作:

  • 生成创世区块中的交易,默认就一笔交易
  • 设置块中的交易状态为false
  • 将创世区块设置为merkle树的根节点
  • 实例化Block块并返回

genesisTx函数生成创世区块中的交易,默认就一笔交易,一笔交易中包含input输入和output输出。

input输入:
输入中有一句话"Information is power. -- Jan/11/2013. Computing is power. -- Apr/24/2018."这是为了纪念Aaron Swartz的精神

output输出:
输出中我们看到consensus.InitialBlockSubsidy创世区块的奖励。总共140700041250000000/1e8 = 1407000412。也就是14亿个BTM币。

计算即权力

引用比原链创始人长铗的话:

4月24号,我们主网上线,信息即权力,2013年Jaruary11;计算即权力,2018年April24。这句话是为了纪念Aaron Swartz的精神,信息即权力可以视为互联网宣言,致力于信息自由传播,让公民隐私得到保护。计算即权力,致力于让资产自由的交易,自由的流动,让公民的财富得到保护,我觉得这是非常好的纪念。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,667评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,361评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,700评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,027评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,988评论 5 361
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,230评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,705评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,366评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,496评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,405评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,453评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,725评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,803评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,015评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,514评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,111评论 2 341

推荐阅读更多精彩内容

  • 一、快速术语检索 比特币地址:(例如:1DSrfJdB2AnWaFNgSbv3MZC2m74996JafV)由一串...
    不如假如阅读 15,871评论 4 88
  • 以下为金马老师《精通比特币》解读的文稿整理。 第一章 介绍 1.1 什么是比特币 (1)比特币是一个区块链实现 (...
    梦之郎阅读 13,169评论 6 61
  • 1 货币的演变——从贝壳到比特币 当社会分工产生之后,人类就产生了商品交换的需求。在货币被发明之前,人类是以以物换...
    longlee阅读 7,590评论 1 23
  • 生命的脚步 没有坦途 离开的心 从不奢望落叶的归幕 夜空的星 引导前行的路 闪亮的瞬间 点燃生命的烛 用破碎的梦 ...
    围城十月阅读 226评论 0 0
  • 2018年2月1日晚在惠民医院由申主任为我做了双眼皮及开眼脚手术,手术做了两个半小时,2日凌晨12点手术结束,刚做...
    时间去哪儿呢阅读 213评论 0 0