以太坊中块的数据结构

我们知道在区块链中,数据是以区块的方式进行存储,而区块链就是由一个个区块(Block)组成的。以太坊每隔12秒就会生成一个区块,这12秒内的所有被接受的交易都会被打包到该区块中,区块的编号则被称为区块的高度。

参考go-ethereum源码可以看到区块(Block)中包含的内容有哪些,下面我们来分别介绍各个组成的含义

Block代码及字段解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type Block struct {
header *Header //区块头
uncles []*Header //数块数组
transactions Transactions //当前块包含的交易数组,类型为 []*Transaction

// 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 // 所有已打包的区块Difficulty之和

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

Header代码及字段解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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"`
}

各参数的含义:

  • ParentHash:父区块的Hash
  • UncleHash:叔区块的Hash
  • Coinbase:打包当前块的矿工地址,块奖励和矿工费都归该地址所有
  • Root:以太坊中的交易状态信息是以Merkle状态树的形式进行存储的,Root是该状态树Merkle的根节点Hash值
  • TxHash:保存该区块中交易Merkle树的根节点的Hash值
  • ReceiptHash:一个区块中包含的所有交易的接收者也是以Merkle树的形式进行存储的,该值是该Merkle树根节点Hash值
  • Bloom:用于索引和搜索
  • Difficulty:难度系数
  • Number:块编号,也称块高度
  • GasLimit:当前块的Gas Limit
  • GasUsed:当前块中所有交易消耗的Gas之和
  • Time:当前块的创建时间
  • Extra:该区块的附加信息
  • MixDigest:该哈希值与Nonce值一起能够证明在该区块上已经进行了足够的计算(用于验证该区块挖矿成功与否的Hash值)
  • Nonce:一个随机数,该值与MixDigest一起能够证明在该区块上已经进行了足够的计算(用于验证该区块挖矿成功与否的Hash值)

Body TODO

1
2
3
4
type Body struct {
Transactions []*Transaction
Uncles []*Header
}

Receipt(收据),保存交易结果的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
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"`
}

各参数的含义:

  • cumulativeGasUsed: 执行完此交易后,消耗的总的gas值
  • contractAddress: 如果此交易是创建合约,该值就是合约地址
  • logs:交易日志

Transaction(交易)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type Transaction struct {
data txdata
// caches
hash atomic.Value
size atomic.Value
from atomic.Value
}

type txdata struct {
AccountNonce uint64 `json:"nonce" gencodec:"required"`
Price *big.Int `json:"gasPrice" gencodec:"required"`
GasLimit uint64 `json:"gas" gencodec:"required"`
Recipient *common.Address `json:"to" rlp:"nil"` // nil means contract creation
Amount *big.Int `json:"value" gencodec:"required"`
Payload []byte `json:"input" gencodec:"required"`

// Signature values
V *big.Int `json:"v" gencodec:"required"`
R *big.Int `json:"r" gencodec:"required"`
S *big.Int `json:"s" gencodec:"required"`

// This is only used when marshaling to JSON.
Hash *common.Hash `json:"hash" rlp:"-"`
}

各参数的含义:

  • AccountNonce: 发送地址的交易计数
  • GasPrice:为交易付出的Gas价格
  • GasLimit:为交易付出的Gas
  • Recipient:接收者地址,如果为空,表示创建合约
  • Amount:向目标账户发送的金额
  • Payload:交易附加的数据

stateObject,以太坊账户,包含账号地址address、余额data.Balance,发送交易的次数data.Nonce(从该账号每发起一次合约,值就加1)、合约字节码code(如果是合约账号就有值)等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// stateObject represents an Ethereum account which is being modified.
//
// The usage pattern is as follows:
// First you need to obtain a state object.
// Account values can be accessed and modified through the object.
// Finally, call CommitTrie to write the modified storage trie into a database.
type stateObject struct {
address common.Address
addrHash common.Hash // hash of ethereum address of the account
data Account
db *StateDB

// DB error.
// State objects are used by the consensus core and VM which are
// unable to deal with database-level errors. Any error that occurs
// during a database read is memoized here and will eventually be returned
// by StateDB.Commit.
dbErr error

// Write caches.
trie Trie // storage trie, which becomes non-nil on first access
code Code // contract bytecode, which gets set when code is loaded

originStorage Storage // Storage cache of original entries to dedup rewrites
dirtyStorage Storage // Storage entries that need to be flushed to disk

// Cache flags.
// When an object is marked suicided it will be delete from the trie
// during the "update" phase of the state transition.
dirtyCode bool // true if the code was updated
suicided bool
deleted bool
}

// Account is the Ethereum consensus representation of accounts.
// These objects are stored in the main account trie.
type Account struct {
Nonce uint64
Balance *big.Int
Root common.Hash // merkle root of the storage trie
CodeHash []byte
}

StateDB,保存账号、合约信息,管理所有stateObject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// StateDBs within the ethereum protocol are used to store anything
// within the merkle trie. StateDBs take care of caching and storing
// nested states. It's the general query interface to retrieve:
// * Contracts
// * Accounts
type StateDB struct {
db Database
trie Trie

// This map holds 'live' objects, which will get modified while processing a state transition.
stateObjects map[common.Address]*stateObject
stateObjectsDirty map[common.Address]struct{}

// DB error.
// State objects are used by the consensus core and VM which are
// unable to deal with database-level errors. Any error that occurs
// during a database read is memoized here and will eventually be returned
// by StateDB.Commit.
dbErr error

// The refund counter, also used by state transitioning.
refund uint64

thash, bhash common.Hash
txIndex int
logs map[common.Hash][]*types.Log
logSize uint

preimages map[common.Hash][]byte

// Journal of state modifications. This is the backbone of
// Snapshot and RevertToSnapshot.
journal *journal
validRevisions []revision
nextRevisionId int

lock sync.Mutex
}

JouyPub wechat
欢迎订阅「K叔区块链」 - 专注于区块链技术学习