Go-ethereum source Analysis (1)--trading, block, blockchain

Source: Internet
Author: User

Objective

This period of time has been doing blockchain public chain project development, mainly based on Bitcoin-core source code development, understanding the principle of blockchain and basic concepts; The individual is also interested in Ethereum, so prepare to take go-ethereum to learn, the process will last a few months, here to record the study notes I now to Ethereum is also rookie small white, this article is mainly aimed at go-ethereum small white, Daniel please bypass it.

Let's start now.

The basic concept of blockchain: trading, block, blockchain , is the core of the blockchain, today from the concept of the analysis of it. (here can not help to say a few words, any scientific field of basic concepts is really important, many problems encountered in the work is because the basic concepts are not in place, to solve the problem needs to re-understand the basic concepts; still remember a few years ago Nanjing University Professor Xu Jiafu speech, a classmate asked how to learn computer, Professor Xu did not say anything, picked up the chalk on the blackboard trembling handwriting to: "Basic concepts, basic concepts, basic concepts", you know the importance of basic knowledge of it. If you do not know Professor Xu go to Baidu, the New China computer field of one of the founders, academia popular a word "north of Fuqing Yang (Tsinghua), south of Xu Jiafu (south)").

Transaction

Core/types/transaction.go

Type Transaction struct {

Data txdata//transaction content, stored in TxData type

Caches the following three fields are stored in memory only?

Hash atomic. Value//hash of the transaction

Size atomic. Value//size of trade

From Atomic. Value//Initiator of the transaction

}

Type TxData struct {

Accountnonce UInt64//account nonce? Why, I don't know.

Price *big. INT//Gasprice

Gaslimit UInt64//Gaslimit, we know that setting gas limit when writing smart contracts can prevent programs from consuming too much gas

Recipient *common. Address//Transaction receiver, nil means contract creation

Amount *big. INT//Trade The number of ether?? Pending confirmation

Payload []byte//trading can carry Payload, the byte code of the smart contract is stored here?? Pending confirmation

Signature values, related to the signature, not to delve into

V *big. Int

R *big. Int

S *big. Int

This is a used when the marshaling to JSON.

Hash *common. Hash

}

The above is the definition of the structure of the transaction, and the following is a look at the functions and methods associated with the transaction (Golang concepts of both functions and methods).

Func newtransaction (Nonce UInt64, to common. Address, amount *big. Int, Gaslimit UInt64, Gasprice *big. INT, data []byte]

*transaction {

Return Newtransaction (nonce, &to, amount, Gaslimit, Gasprice, data)

}

Func newcontractcreation (nonce UInt64, amount *big. Int, Gaslimit UInt64, Gasprice *big. INT, data []byte] *transaction {

Return newtransaction (nonce, nil, amount, gaslimit, Gasprice, data)

}

The above function, Newtransaction is to create a normal trade, newcontractcreation is used to create a smart contract, both call the intrinsic function (non-export) newtransaction, The difference is obviously that Newcontractcreation set the transaction receive address to nil.

Func newtransaction (Nonce UInt64, to *common. Address, amount *big. Int, Gaslimit UInt64, Gasprice *big. INT, data []byte]

*transaction {

If Len (data) > 0 {

data = Common. Copybytes (data)

}

D: = txdata{

Accountnonce:nonce,

Recipient:to,

Payload:data,

Amount:new (big. INT),

Gaslimit:gaslimit,

Price:new (big. INT),

V:new (big. INT),

R:new (big. INT),

S:new (big. INT),

}

If amount! = Nil {

D.amount.set (Amount)

}

If Gasprice! = Nil {

D.price.set (Gasprice)

}

Return &TRANSACTION{DATA:D}

}

The above functions are simple, create a TxData object first, and then initialize the data member.

The following ENCODERLP and DECODERLP are primarily responsible for the RLP codec of the transaction.

ENCODERLP implements RLP. Encoder

Func (TX *transaction) ENCODERLP (w io). Writer) Error {

Return RLP. Encode (W, &tx.data)

}

DECODERLP implements RLP. Decoder

Func (TX *transaction) DECODERLP (S *RLP. Stream) Error {

_, size, _: = S.kind ()

ERR: = S.decode (&tx.data)

If Err = = Nil {

Tx.size.Store (Common. Storagesize (RLP. Listsize (size)))

}

return err

}

Here is a brief introduction to several trading-related functions and methods, more functions and methods you can consult the source code. The reason why I do not expand is to pursue the whole understanding first, then the concrete realization.

Block

Core/types/block.go

First look at the data structure of the chunk header:

Header represents a block header in the Ethereum blockchain.

Type Header struct {

Parenthash Common. Hash/hash of the previous block, used to organize the block into a chain

Unclehash Common. Hash//unclehash, understanding is not too deep, and later

Coinbase Common. Address//pow consensus algorithm Coinbase transaction correspondence

Root Common. Hash//State trie tree Root

Txhash Common. Hash//Transactions Root

Receipthash Common. Hash//Receipts Root

Bloom Bloom//should be Bloom filter, not in depth

Difficulty *big. The difficulty value of the Int//pow consensus algorithm is adjusted with the block chain height

Number *big. Int//Block height

Gaslimit UInt64//block head of the Gaslimit?? It's not clear what the effect is.

gasused UInt64//The entire chunk of the consumed gas traded? Pending confirmation

Time *big. Int//Out block time

Extra []byte

Mixdigest Common. Hash//Temporarily do not know what to do

Nonce in nonce blocknonce//pow consensus algorithm

}

The following method gets the hash value of the block header:

Hash returns the block hash of the header, which is simply the keccak256 hash of its

RLP encoding.

Func (H *header) Hash () common. Hash {

return Rlphash (h)

}

Hashnononce returns the hash which is used as input for the proof-of-work search.

Func (H *header) hashnononce () common. Hash {

Return Rlphash ([]interface{}{

H.parenthash,

H.unclehash,

H.coinbase,

H.root,

H.txhash,

H.receipthash,

H.bloom,

H.difficulty,

H.number,

H.gaslimit,

H.gasused,

H.time,

H.extra,

})

}

Func rlphash (x interface{}) (H common. Hash) {

HW: = Sha3. NEWKECCAK256 ()

Rlp. Encode (HW, X)

Hw. Sum (h[:0])

Return h

}

The following is the data structure of the block body:

Body is a simple (mutable, non-safe) data container for storing and moving

A block ' s data contents (transactions and uncles) together.

Type Body struct {

transactions [All trades in]*transaction//block body

Uncles []*header//not quite understand the role of this field, is it related to the fork?

}

The data structure of the block is as follows:

Block represents an entire block in the Ethereum blockchain.

Type Block struct {

Header *header//block head pointer

Uncles []*header

Transactions transactions//chunks in the body of the 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//The overall difficulty value on the chain

These fields is used by package ETH-to-track

Inter-peer block relay.

As comments, these two fields are used to track the forwarding of chunks between nodes

Receivedat time. Time//Chunk received

Receivedfrom interface{}//Flag This chunk is received from which peer node

}

Storageblock defines the RLP encoding of a Block stored in the

State database. The Storageblock encoding contains fields

Would otherwise need to be recomputed.

Type Storageblock Block

"External" block encoding. Used for ETH protocol, etc.

Type Extblock struct {

Header *header

Txs []*transaction

Uncles []*header

}

The block data structure above is stored in memory, the actual structure stored in the database is Storageblock, defined as follows:

"Storage" block encoding. Used for database.

Type Storageblock struct {

Header *header

Txs []*transaction

Uncles []*header

TD *big. Int

}

Below is a simple analysis of the function Newblock to create a block:

Newblock creates a new block. The input data is copied,

Changes to header and to the field values would not affect the block.

The values of Txhash, Unclehash, Receipthash and Bloom in header

is ignored and set to values derived from the given txs, uncles and receipts.

Func Newblock (header *header, TXs []*transaction, uncles []*header, receipts []*receipt] *block {

B: = &block{header:copyheader (header), Td:new (big. INT)}//Create block Object

Todo:panic If Len (txs)! = Len (receipts)

If Len (txs) = = 0 {

B.header.txhash = emptyroothash//If there is no transaction in the block, the Txhash assignment is Emptyroothash

} else {

B.header.txhash = Derivesha (Transactions (TXS))

B.transactions = Make (Transactions, Len (TXS))

Copy (b.transactions, TXS)//Create and copy a copy of TX

}

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

}

Newblockwithheader creates a block with the given header data. The

Header data is copied, changes to header and to the field values

Would not affect the block.

Func Newblockwithheader (header *header) *block {

Return &block{header:copyheader (header)}

}

The DECODERLP and ENCODERLP methods are the concrete implementations of Block's RLP codec:

DECODERLP decodes the Ethereum

Func (b *block) DECODERLP (S *RLP. Stream) Error {

var eb extblock

_, size, _: = S.kind ()

If err: = S.decode (&EB); Err! = Nil {

return err

}

B.header, b.uncles, b.transactions = EB. Header, EB. Uncles, EB. Txs

B.size.store (Common. Storagesize (RLP. Listsize (size)))

return Nil

}

ENCODERLP serializes B into the Ethereum RLP block format.

Func (b *block) ENCODERLP (w io). Writer) Error {

Return RLP. Encode (W, extblock{

Header:b.header,

Txs:b.transactions,

Uncles:b.uncles,

})

}

This part introduces the data structure and method of chunk head, block body, block, database block, please refer to the source code for details.

Block chain

Core/blockchain.go

After introducing the transaction, block size, chunk, we look at the data structure of the blockchain:

BlockChain represents the canonical chain given a database with a Genesis

Block. The Blockchain manages chain imports, reverts, chain reorganisations.

Importing blocks in to the block chain happens according to the set of rules

Defined by the stage Validator. Processing of blocks is done using the

Processor which processes the included transaction. The validation of the state

Is do in the second part of the Validator. Failing results in aborting of the import.

//

The BlockChain also helps in returning blocks from **any** chain included

In the database as well as blocks that represents the canonical chain. It ' s

Important to note this getblock can return any block and does not need to be

Included in the canonical one where as Getblockbynumber always represents the

Canonical chain.

Type BlockChain struct {

Chainconfig *params. Chainconfig//Chain & Network config literally means the configuration of chains and networks, which are temporarily

CacheConfig *cacheconfig//Cache configuration for pruning

DB Ethdb. Database//Low levels persistent database to store final content in, bottom level db

TRIEGC *prque. Prque//Priority queue mapping block numbers to tries to GC do not know what the role

Gcproc time. Duration//accumulates canonical block processing for trie dumping

HC *headerchain

Rmlogsfeed event. Feed//event. Feeds store subscriber information, Blockchain notify subscribers when an event occurs

Chainfeed event. Feed

Chainsidefeed event. Feed

Chainheadfeed event. Feed

Logsfeed event. Feed

Scope event. Subscriptionscope

Genesisblock *types. Block//Genesis block pointers

Mu sync. Rwmutex//Global mutex for locking chain operations

Chainmu sync. Rwmutex//Blockchain insertion lock

PROCMU sync. Rwmutex//Block processor lock

Checkpoint int//checkpoint counts towards the new checkpoint

Currentblock Atomic. Value//Current Chunk

Currentfastblock Atomic. Value//Current head of the Fast-sync chain (could be above the block chain!)

Statecache state. Database//State database to reuse between imports (contains state cache)

Bodycache *lru. Cache//cache for the most recent block bodies

Bodyrlpcache *lru. Cache//cache for the most recent block bodies in RLP encoded format

Blockcache *lru. Cache//cache for the most recent entire blocks

Futureblocks *lru. Cache//Future blocks is blocks added for later processing

Quit Chan struct{}//Blockchain quit channel

Running int32//running must be called atomically

Procinterrupt must be atomically called

Procinterrupt Int32//interrupt Signaler for block processing

WG Sync. Waitgroup//Chain processing wait Group for shutting down

Engine consensus. Engine//consensus algorithm engines, different algorithms recognize engine interface

Processor Processor//block processor interface, very important data member

Validator Validator//block and State validator interface, very important data member

Vmconfig VMs. Config//virtual machine configuration

Badblocks *lru. Cache/Bad block cache

}

The above is the blockchain data structure, a lot of data members do not understand what role, no problem directly skip, as the analysis of the deepening, we will understand.

Newblockchain returns a fully initialised block chain using information available in the database. It initialises The default Ethereum Validator and Processor.

Func newblockchain (db ethdb. Database, CacheConfig *cacheconfig, Chainconfig *params. Chainconfig, engine consensus. Engine, Vmconfig vm. Config) (*blockchain, error) {

If the cache config is empty, create the object

if CacheConfig = = Nil {

CacheConfig = &cacheconfig{

TRIENODELIMIT:256 * 1024 * 1024,

Trietimelimit:5 * time. Minute,

}

}

Initializing various data members

Bodycache, _: = LRU. New (Bodycachelimit)

Bodyrlpcache, _: = LRU. New (Bodycachelimit)

Blockcache, _: = LRU. New (Blockcachelimit)

Futureblocks, _: = LRU. New (Maxfutureblocks)

Badblocks, _: = LRU. New (Badblocklimit)

To create a block chain object

BC: = &blockchain{

Chainconfig:chainconfig,

Cacheconfig:cacheconfig,

Db:db,

Triegc:prque. New (),

Statecache:state. Newdatabase (DB),

Quit:make (Chan struct{}),

Bodycache:bodycache,

Bodyrlpcache:bodyrlpcache,

Blockcache:blockcache,

Futureblocks:futureblocks,

Engine:engine,

Vmconfig:vmconfig,

Badblocks:badblocks,

}

Creating a blockchain validator and processor, it is important to see these two data members later

BC. Setvalidator (Newblockvalidator (chainconfig, BC, engine))

BC. Setprocessor (Newstateprocessor (chainconfig, BC, engine))

var err error

BC.HC, err = Newheaderchain (db, Chainconfig, Engine, Bc.getprocinterrupt)

If err! = Nil {

return nil, err

}

Get the Genesis block

bc.genesisblock = BC. Getblockbynumber (0)

if Bc.genesisblock = = Nil {

return Nil, errnogenesis

}

If err: = Bc.loadlaststate (); Err! = Nil {

return nil, err

}

Check the current state of the "hashes" and "make sure.

For hash: = Range Badhashes {

If header: = BC. Getheaderbyhash (hash); Header! = Nil {

Get the canonical block corresponding to the offending header ' s number

Headerbynumber: = BC. Getheaderbynumber (header. Number.uint64 ())

Make sure the Headerbynumber (if present) are in our current canonical chain

If headerbynumber! = Nil && headerbynumber.hash () = = header. Hash () {

Log. Error ("Found bad hash, rewinding chain", "number", header.) Number, "hash", header. Parenthash)

Bc. Sethead (header. Number.uint64 ()-1)

Log. Error ("Chain Rewind was successful, resuming normal operation")

}

}

}

Take ownership of the particular state

Go Bc.update ()

return BC, Nil

}

The above is the way to initialize the blockchain, blockchain there are many important methods, because space is limited, here is not one of them, after the analysis needs to come back to see. The following is a simple indicator of several important methods, which can be referenced in the code.

Loadlaststate loads the last known chain state from the database. This method

Assumes the chain manager mutex is held.

Func (BC *blockchain) loadlaststate () Error {

......

}

Sethead rewinds The local chain to a new head. In the case of headers, everythingabove the new head would be deleted and the new one set. In the case of blocks though, the head could be further rewound if block bodies is missing (non-archive nodes after a fast Sync).

Func (BC *blockchain) sethead(head UInt64) error {

......

}


Currentblock retrieves the current head block of the canonical chain. The block is retrieved from the blockchain ' s internal cache.

Func (BC *blockchain) currentblock () *types. Block {

......

}

Setprocessor sets the processor required for making state modifications.

Func (BC *blockchain) Setprocessor(processor processor) {

......

}

Setvalidator sets the validator which is used to validate incoming blocks.

Func (BC *blockchain) setvalidator(Validator validator) {

......

}

Validator returns the current Validator.

Func (BC *blockchain) Validator() Validator {

......

}

Processor returns the current Processor.

Func (BC *blockchain) Processor () Processor {

......

}

Summarize:

This article briefly introduced the Go Ethetheum source code in the transaction, block, blockchain data structure and initialization method, I hope you have some understanding. The next article will cover the trading pool, see how the trade is packaged into chunks, and how chunks are broadcast to the network. Because the author is also rookie, many concepts understand not in-depth, do not understand the concept for a while, analysis in depth will understand.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.