Go-ethereum 源码解析之重要的数据结构和算法
1. 数据结构
(1) 哈希
32 个字节,256 位。由算法 Keccak-256 计算。
文件:go-ethereum/common/types.go
const (
HashLength = 32
)
type Hash [HashLength]byte
(2) 地址
20 个字节,160 位。由算法 RIPEMD-160 计算。
文件:go-ethereum/common/types.go
const (
AddressLength = 20
)
type Address [AddressLength]byte
(3) 区块头
文件:go-ethereum/core/types/block.go
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"`
}
(4) 交易
文件:go-ethereum/core/types/transaction.go
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:"-"`
}
(5) 交易回执
文件:go-ethereum/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"`
}
(6) 日志项
文件:go-ethereum/core/types/log.go
type Log struct {
// Consensus fields:
// address of the contract that generated the event
Address common.Address `json:"address" gencodec:"required"`
// list of topics provided by the contract.
Topics []common.Hash `json:"topics" gencodec:"required"`
// supplied by the contract, usually ABI-encoded
Data []byte `json:"data" gencodec:"required"`
// Derived fields. These fields are filled in by the node
// but not secured by consensus.
// block in which the transaction was included
BlockNumber uint64 `json:"blockNumber"`
// hash of the transaction
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
// index of the transaction in the block
TxIndex uint `json:"transactionIndex" gencodec:"required"`
// hash of the block in which the transaction was included
BlockHash common.Hash `json:"blockHash"`
// index of the log in the receipt
Index uint `json:"logIndex" gencodec:"required"`
// The Removed field is true if this log was reverted due to a chain reorganisation.
// You must pay attention to this field if you receive logs through a filter query.
Removed bool `json:"removed"`
}
(7) 区块
文件:go-ethereum/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{}
}
2. 算法
(1) keccak256
计算 Ethereum-SHA-3(Keccak-256)散列值。也被用来计算 Solidity 中的函数签名(仅使用散列值的前 4 个字节,8 个十六进制数)。
(2) sha3
keccak256 的别名。
(3) sha256
计算 SHA-256 散列值。
(4) ripemd160
计算 RIPEMD-160 散列值。这是非对称加密?公钥和私钥?
(5) secp256k1
签名算法,生成 65 个字节的签名信息,或者 R, S, V?
- 签名方法:secp256k1.Sign()
- 恢复签名方法:secp256k1.RecoverPubkey()
【备注】
在比特币中,采用非对称加密算法 secp256k1 根据给定的密码求出公钥和私钥,然后对公钥采用 SHA3 家族的散列算法 ripemd160 对公钥进行二次散列,散列为 20 字节,并将散列值作为账户地址。
而在以太坊中,采用非对称加密算法 secp256k1 根据给定的密码求出公钥和私钥,然后对公钥采用 SHA3 家族的散列算法 keccak256 对公钥进行二次散列,散列为 32 字节,将将散列值的前 20 个字节作为账户地址。
3. 重要的概念
(1) 区块头哈希
区块头哈希是指采用散列算法 keccak256 对区块头中所有数据计算出的散列值。
(2) 区块头签名哈希
区块头签名哈希是指采用散列算法 keccak256 对区块头中除了额外数据中的最后 65 个字节之外所有数据计算出的散列值。
(3) 区块哈希
区块哈希,即区块头哈希。
(4) 区块签名哈希
区块签名哈希即区块头签名哈希。
(5) 账户地址 & 以太坊账户地址 & 以太坊账户
以太坊账户地址即 common.Address,包含 20 个字节。
(6) 智能合约地址 & 以太坊智能合约地址
以太坊智能合约地址即 common.Address,包含 20 个字节。
在以太坊中账户地址和智能合约地址基本相同,但也有一些显著的差别:
- 账户地址由人操控,或者说由以太坊的外部操控。
- 智能合约地址由账户地址操控。
(7) 签名者
签名者即以太坊账户地址。
(8) 签名区块 & 待确定区块
签名区块是本地节点最新挖出来的区块,存入本地节点的待确定区块列表,需要等待网络中其它节点的验证。
签名区块中,区块头、交易列表、交易回执列表都已经组装完成,并且区块头中也已经包含了签名。
Reference
Contributor
- Windstamp, https://github.com/windstamp