Simplechainit can be regarded as a database, and changes in database data are catalyzed by transactions. In order to manage transactions effectively and orderly, one or more transactions must be formed into one data block before they can be submitted to the database. This data Block is a Block. A block not only contains multiple transactions, but also records some additional data for correct submission to the database.
The following figure shows the structure and relationship of Simplechain block data. When explaining the block data structure, other data must be presented together. Only by mastering the data sources in the block can you truly understand the block chain data.
The block is divided into two parts: the block Header and the block Body. The block header is rich in information. It not only establishes contact with the previous unit, but also records some transaction execution information and miner work information. The above figure involves a very important concept Trie, whose full name is Merkel compressed prefix tree.
Block header data interpretation
The data of each field is as follows:
parentHash
Is a hash value that records the hash value of the parent block directly referenced by this block. Only through this record can the blocks be organized in an orderly manner to form a blockchain. In addition, the content of the parent block can be prevented from being modified. Because of data modification, the block hash is bound to change. Therefore, a block directly or indirectly strengthens all parent blocks, the encryption algorithm ensures that historical blocks cannot be modified.
sha3Uncles
Is a hash value that represents multiple uncle blocks referenced by the block. The block body also contains the block header information of multiple uncle, while sha3Uncles is the RLPHASH hash value of the Uncle block set. In Bitcoin, only when blocks are successfully dug out and accepted by other nodes can they be rewarded. This is a reward for all miners to strive for accounting rights and joint rewards. Simplechain is slightly different from Simplechain. It cannot be an orphan block in the main chain. If you are lucky enough to be taken into the block chain by later blocks, it will become an orphan block. Additional rewards will be given to the blocks that have retained the isolated blocks. Once a block becomes a block, the block will be rewarded. Reduce Simplechain soft forking and balance the benefits of miners with slow network speed through the block reward mechanism.
miner
Is an address, indicating that the block is dug by the miners of this account, and the mining reward will be issued to this account.
stateRoot
Is a hash value that indicates the snapshot ID of the Simplechain status after all transactions in this block are executed. Because Simplechain is described as a state machine system, the snapshot ID is called a state hash value. And because the status hash is generated by all account states according to Merkel prefix tree algorithm, it is called status Merkel tree root value.
transactionsRoot
Is a hash value, indicating that all transactions in the block generate a Merkel tree root node hash value. It is a cryptographic summary of guaranteed transactions. This Root can directly verify whether a transaction is included in this block.
receiptRoot
Is a hash value, which is also a hash value of Merkel tree root node. A collection of transaction receipt information generated after a block transaction is executed.
logsBloom
Is a 256-Byte array. Extract the self-receipt to quickly locate and find the intelligent contract event information in the transaction receipt.
difficulty
Is a big.Int value, indicating the difficulty coefficient that this block can be dug up.
number
Is the big.Int value, indicating the height of the block. It is used to mark the sequence number of a block. On a block chain, the block height must increase continuously.
gasLimit
Is the uint64 value, indicating the amount of Gas and fuel allowed to be consumed in this block. This value is dynamically adjusted based on the parent block. The purpose of the adjustment is to adjust the number of transactions that the block can contain.
gasUsed
Is the uint64 value, indicating the amount of Gas and fuel actually consumed during the execution of all transactions in this block.
timestamp
Is the value of uint64, which indicates the UTC timestamp of the block. Unit: seconds. Because Simplechain produces a block for an average of 14.5 seconds (12 seconds in the white paper), the block timestamp can be used as a timestamp service, but cannot be fully trusted.
extraData
Is a Byte array of unfixed length, up to 32 bits. It is completely customized by miners, who usually write some public promotion content or use it as a vote.
mixHash
Is a hash value. Check whether the block is correctly dug out. It is actually a hash value when the block header data does not contain nonce.
nonce
Is an 8-length Byte, which is actually a uint64 value. It is used to verify whether the block is correctly dug up. mixHash can only prove the PoW workload with a correct nonce.
key code
The following is the block header and block structure definition code defined in Simplechain code. All core codes are in the core/types/block.go file:
//core/types/block.go:70
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 uint64 `json:"timestamp" gencodec:"required"`
Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
}
type Body struct {
Transactions []*Transaction
Uncles []*Header
}
To create a block, call the NewBlock function:
func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt) *Block {
b := &Block{header: CopyHeader(header), td: new(big.Int)}
// TODO: panic if len(txs) != len(receipts)
if len(txs) == 0 {
b.header.TxHash = EmptyRootHash
} else {
b.header.TxHash = DeriveSha(Transactions(txs))
b.transactions = make(Transactions, len(txs))
copy(b.transactions, txs)
}
if len(receipts) == 0 {
b.header.ReceiptHash = EmptyRootHash
} else {
b.header.ReceiptHash = DeriveSha(Receipts(receipts))
b.header.Bloom = CreateBloom(receipts)
}
if len(uncles) == 0 {
b.header.UncleHash = EmptyUncleHash
} else {
b.header.UncleHash = CalcUncleHash(uncles)
b.uncles = make([]*Header, len(uncles))
for i := range uncles {
b.uncles[i] = CopyHeader(uncles[i])
}
}
return b
}