eth

package module
v0.0.0-...-508c5de Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 4, 2022 License: LGPL-2.1-or-later Imports: 28 Imported by: 0

README


go-ethereum v0.7.10 - core Module - Source Code Analysis

In this project I dive into the core module of the official go-ethereumv0.7.10 and try
to give a thorough explanation on all code that's included in this module.

The code can alternatively be explored through:
https://pkg.go.dev/github.com/georzaza/go-ethereum-v0.7.10_official

Please note that both this repository and the above link contain the official code
along with comments that I've written in order to help myself get through with
this project
. The original codebase contained very-very limited comment sections.

Any inner links in this file point just below the definition/signature of
a data structure/function. Remember to scroll up just a bit after clicking
on a link.

If you are interested in analyzing any of the other modules you might find useful
the folder georzaza_scripts and/or the file georzaza_output, which examine files'
similarity across all modules of this go-ethereum version.



1. Description

The core module is the implementation of the basic logic of Ethereum.
What is shown below is a list of all files the core contains with a short description.
With very few exceptions, each file implements a ... core idea of Ethereum.


  • core/types/block.go
    Block type definition along with functions on how to create a block,
    set it's header, find a transaction in a block, set it's uncles and more.

  • core/types/bloom9.go
    Bloom definition. The bloom is used in order to save space while storing
    a transaction receipt's log fields.

  • core/types/common.go
    Contains the definition of 2 interfaces, namely BlockProcessor and Broadcaster
    which are implemented by the ChainManager and TxPool accordingly.


  • core/types/receipt.go
    Contains the definition of a receipt and functions which may be used on a receipt object.

  • core/types/transaction.go
    Contains the definition of a transaction. It's important to note that in this file
    functions are defined which either sign a transaction or get it's public key.


  • core/block_manager.go
    Aside from the BlockManager, this file also contains the definition of a very
    important interface, 'EthManager', which is implemented by the 'Ethereum' object,
    defined in the file ethereum.go. The BlockManager is responsible for:
    1. Applying the transactions of a block.
    2. Validating the block.
    3. Calculating the new total difficulty and the miner's reward.

  • core/chain_manager.go The ChainManager as it's name suggests is responsible for:
    1. Adding a block to the chain. Note however that the BlockManager is the one
      responsible for applying the transactions. After adding a block, that block
      will also be saved in the main db.
    2. Reseting the chain. This means that through the ChainManager we can reset
      the chain to the point where it will include only the genesis block.
    3. Providing ways to determine whether a block is in the chain or not.
    4. Calculating the total difficulty.
    5. Inserting a chain of blocks to the current chain. (function InsertChain)
      This file also includes the definition of the function CalcDifficulty which calculates
      the difficulty of a block (which is different than the total difficulty of the chain).

  • core/dagger.go
    The Dagger consensus model. Dagger is a memory-hard proof of work model
    based on directed acyclic graphs. Memory hardness refers to the concept that
    computing a valid proof of work should require not only a large number of
    computations, but also a large amount of memory.

  • core/error.go
    Contains the definition of error types that might come up when either
    validating a block, applying it's transactions or inserting it into the chain.

  • core/events.go
    Containts the definition of events fired when:
    1. a transaction is added to the transaction pool
    2. a transaction has been processed
    3. a block has been imported to the chain.

  • execution.go
    Contains the definition of an Execution type alongside the most basic (inner) function
    through which all code execution happens. The EVM creates and calls an Execution's
    object functions in order to execute code.





  • core/state_transition.go
    Contains the implementation of the state transition that comes up through the execution of a msg/transaction.
    In short, it can be defined as follows:

    1. Check if the transaction is well-formed (ie. has the right number of values), the signature is valid, and the nonce matches the nonce in the sender's account. If not, return an error.
    2. Calculate the transaction fee as initialGas * gasPrice, and determine the sending address from the signature. Subtract the fee from the sender's account balance and increment the sender's nonce. If there is not enough balance to spend, return an error.
    3. Initialize gas = initialGas, and take off a certain quantity of gas per byte to pay for the bytes in the transaction.
    4. Transfer the transaction value from the sender's account to the receiving account. If the receiving account does not yet exist, create it. If the receiving account is a contract, run the contract's code either to completion or until the execution runs out of gas.
    5. If the value transfer failed because the sender did not have enough money, or the code execution ran out of gas, revert all state changes except the payment of the fees, and add the fees to the miner's account.
    6. Otherwise, refund the fees for all remaining gas to the sender, and send the fees paid for gas consumed to the miner.

  • core/transaction_pool.go
    Contains the definition of TxPool. A TxPool object is used to group transactions.
    Validation of transactions happens through this object's methods.

  • core/vm_env.go
    Definition of the EVM. The EVM implements the Environment interface,
    defined in the file vm/environment.go and works closely with the Execution
    model in order to handle smart contract deployment and code execution.
    The below image shows in detail how most of the above concepts are glued together with the EVM:


    hello



1. Package types

1.1 block.go

1.1.1 Data structures
type BlockInfo struct {
	Number uint64
	Hash   []byte
	Parent []byte
	TD     *big.Int
}

A 'compact' way of representing a block is by the use of the BlockInfo type

  • Number: The number of the block
  • Hash: The hash of the block
  • Parent: The parent of the block.
  • TD: used by the package core to store the total difficulty of the chain up to and including a block.
    More specifically:
    $Block.TD = Block.parent.TD + Block.difficulty + \sum_{u;\epsilon;Uncles} {u.difficulty}$

type Block struct {
	PrevHash          ethutil.Bytes
	Uncles            Blocks
	UncleSha          []byte
	Coinbase          []byte
	state             *state.StateDB
	Difficulty        *big.Int
	Time              int64
	Number            *big.Int
	GasLimit          *big.Int
	GasUsed           *big.Int
	Extra             string
	Nonce             ethutil.Bytes
	transactions      Transactions
	receipts          Receipts
	TxSha, ReceiptSha []byte
	LogsBloom         []byte
	Reward            *big.Int
}

A Block type is the main type used to represent a block.

  • PrevHash: The Keccak 256-bit hash of the parent block’s header
  • Uncles : The uncles of the Block.
  • UncleSha: The Keccak 256-bit hash of the uncles of the Block.
  • CoinBase: The address of the beneficiary.
  • beneficiary: The 160-bit address to which all fees collected from
    the successful mining of this block are transferred to (miner's address).
  • state: The Keccak 256-bit hash of the root node of the state trie,
    after all transactions are executed
  • Difficulty : Difficulty of the current block.
  • Time: Creation time of the Block.
  • Number: The number of the Block. This is equal to the number of ancestor blocks.
  • GasLimit: The maximum gas limit all the transactions inside this Block are allowed to consume.
  • GasUsed: The total gas used by the transactions of the Block.
  • Extra: An arbitrary byte array containing data relevant to this block.
    According to the Ethereum yellow paper this should be 32 bytes or less.
  • Nonce: The Block nonce. This is what miners keep changing to compute a solution to PoW.
  • transactions: List of transactions and/or contracts to be created included in this Block.
  • receipts: The receipts of the transactions
  • TxSha: The Keccak 256-bit hash of the root node of the transactions trie of the block
  • ReceiptSha: The Keccak 256-bit hash of the root node of the receipts trie of the block.
  • LogsBloom: The Bloom filter composed from indexable information (logger address and log
    topics) contained in each log entry from the receipt of each transaction in the transactions list.
  • Reward: The reward of the beneficiary (miner)

Notes about uncles: "In case of proof-of-work mining, there are many miners
trying to mine the same set of transactions at the same time. Since the block
mining time is very short (about 15 sec. in case of ethereum) there is a
possibility,that more than one blocks are mined within a very short interval.
The block mined first is added to the main chain but the effort of miner who
mined the other block in not simply let off. These competing blocks are called
orphaned blocks.

According to ethereum beige paper, " An uncle is a block whose parent is equal
to the current block’s parent’s parent." The purpose of uncles is to help reward
miners for including these orphaned blocks. The uncles that miners include must
be “valid,” meaning within the sixth generation or smaller of the present block.
After six children, stale orphaned blocks can no longer be referenced.

Uncle blocks receive a smaller reward than a full block. Nonetheless, there’s
still some incentive for miners to include these orphaned blocks and reap a reward."

Source: https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369

type Blocks []*Block

Blocks grouping type.

type BlockBy func(b1, b2 *Block) bool

type blockSorter struct {
	blocks Blocks
	by     func(b1, b2 *Block) bool
}

A BlockBy type along with a blockSorter type are used as a sorting mechanism
(which makes use of the sort.Sort function: https://pkg.go.dev/sort#Sort ).
Note that the blockSorter type is not exported (does not start with a capital letter),
so it's only visible to the current file.

  • blocks: the blocks to be sorted (can be any number of Blocks).
  • by: The sorting function to be used between two Blocks of the blockSorter.
    Although internally a BlockBy object is assigned to this field, note
    that the definition allows any function that is matching the function
    signature of 'by') to be assigned to this field.

1.1.2 Functions

func (bi *BlockInfo) RlpDecode(data []byte)
RlpDecode sets the caller's (BlockInfo) fields to the RLP-decoded parts of the 'data' parameter.
To do so, data is converted to an ethutil.Value object and the RLP-decoding operation happens on the Value object.

func (bi *BlockInfo) RlpEncode() []byte
RlpEncode returns the rlp-encoding of a BlockInfo object (by calling the function Encode defined in ethutil/rlp.go)

func (self Blocks) AsSet() ethutil.UniqueSet
AsSet returns the Blocks that the caller consists of as an ethutil.UniqueSet object.
The elements of the returned set will be the hashes of these Blocks (only a Blocks object can call this function).

func (self BlockBy) Sort(blocks Blocks)
Sort sorts Blocks.
This function creates a blockSorter object, assigns the caller (BlockBy) object to the blockSorter's 'by' field
and the param 'blocks' object to the blockSorter's 'blocks' field, and then calls the sort.Sort function (https://pkg.go.dev/sort#Sort) by passing to it the created blockSorter object.
The sort.Sort function makes use of Len, Less, Swap functions to sort the objects, all defined below.

func (self blockSorter) Len() int
Len returns the number of Blocks that a blockSorter object consists of.

func (self blockSorter) Swap(i, j int)
Swap swaps two Blocks of a blockSorter object.

func (self blockSorter) Less(i, j int)
Less. For any 2 Blocks that the caller (blockSorter) consists of, denoted as i, j, this function returns
true if Block i is less than j. To determine whether i is less than j, a BlockBy object is used.

func Number(b1, b2 *Block) bool
Number returns true if the block number of b1 is less than b2, false otherwise.

func NewBlockFromBytes(raw []byte) *Block
NewBlockFromBytes creates a new Block from the 'raw' bytes param and returns it.
These bytes however should be the bytes representation of the result of the RLP-encoding of a Block.

func NewBlockFromRlpValue(rlpValue *ethutil.Value) *Block
NewBlockFromRlpValue creates a new Block from the 'rlpValue' param.
To do so, this function calls the Block.RlpValueDecode function. As described in the latter,
only the Block's header, transactions and uncles fields are derived from the rlpValue object.

func CreateBlock(root interface{}, prevHash []byte, base []byte, Difficulty *big.Int, Nonce []byte, extra string) *Block
CreateBlock creates a Block and returns it. See the Block data structure for an explanation of the fields used.
The root parameter is the root of the Block's state trie. The Block created will be created at the current Unix time.
Notice that there are no transactions and receipts passed as arguments to this function, aka these are not set.

func (block *Block) Hash() ethutil.Bytes
Hash returns the block's hash. To do so, these are the steps followed:

  1. block's header is first cast to an ethutil.Value object
  2. the Encode function is called upon the casted object.
  3. the keccak-256 hash of the returned object of the step 2 is returned.

func (block *Block) HashNoNonce() []byte
HashNoNonce returns the hash of an object that is almost the same as a Block. The differences are:

  1. The object to be hashed contains only the uncles hash.
  2. The object to be hashed contains the root of the state and not the state as a whole.
  3. The object to be hashed contains only the TxSha and not the receipts.
  4. The object to be hashed contains only the ReceiptSha and not the transactions.
  5. The object to be hashed does not contain the Reward of the miner.

Note: The object to be hashed if appended with the Nonce field of the Block will comprise the Block's header.

func (block *Block) State() *state.StateDB
State returns the state of the Block. (not just the root)

func (block *Block) Transactions() Transactions
Transactions returns the transactions of the block.

func (block *Block) CalcGasLimit(parent *Block) *big.Int
CalcGasLimit calculates the gas limit.
If the Block passed as a parameter (aka the parent) is the genesis block the gas limit is set to $10^6$.
Otherwise the gas limit will be:
$1023 \cdot parent.GasLimit + parent.GasUsed \cdot \frac{6}{5}$.
The minimum gas limit is set to $125000$ Wei.

func (block *Block) BlockInfo() BlockInfo
BlockInfo returns the BlockInfo representation of a Block.

func (self *Block) GetTransaction(hash []byte) *Transaction
GetTransaction searches for a transaction in the current Block by comparing the hash of all
the transactions in the block to the 'hash' parameter.
Returns the block's matching transaction, or nil if there is no match.

func (block *Block) Sync()
Sync syncs the block's state and contract respectively. For more, see the state package.

func (block *Block) Undo()
Undo resets the block's state to nil.

func (block *Block) rlpReceipts() interface{}
rlpReceipts is an inner function that returns the receipts as a string.
This function is used to derive the ReceiptSha of the receipts.
Although defined, this function is never used in this go-ethereum version.

func (block *Block) rlpUncles() interface{}
rlpUncles returns the uncles as a string.
This function is used to derive the UncleSha of the uncles.
Gets called by the Block.SetUncles, Block.Value and Block.RlpData functions.

func (block *Block) SetUncles(uncles []*Block)
SetUncles sets the uncles of Block to the parameter 'uncles'.
This function is also called by the CreateBlock function. Also sets the UncleSha of
the Block based on the provided parameter. To do so, the inner function rlpUncles is called.

func (self *Block) SetReceipts(receipts Receipts)
SetReceipts sets the receipts of this block to the parameter 'receipts'.
Also calculates and sets the LogsBloom field of the block which is derived by the receipts.

func (self *Block) SetTransactions(txs Transactions)
SetTransactions sets the transactions of a Block to the parameter 'transactions'.
Also calculates and sets the TxSha field which is derived by the transactions.

func (block *Block) Value() *ethutil.Value
Value casts a block to an ethutil.Value object containing the header,
the transactions and the uncles of the block and then returns it.

func (block *Block) RlpEncode() []byte
RlpEncode calls the Value function on the current Block and then rlp-encodes the Block.
The rlp-encodable fields of a Block are it's header, transactions and uncles.

func (block *Block) RlpDecode(data []byte)
RlpDecode RLP-decodes a Block.
To do so, a new ethutil.Value object is created from the data param and then
the function RlpValueDecode(data) is called on the current Block.

  • data represents the rlp-encodable fields of this block and can be
    obtained through the function RlpData.

func (block *Block) RlpValueDecode(decoder *ethutil.Value)
RlpValueDecode RLP-decodes the rlp-encodable fields of a Block, aka the header, transactions and uncles.

  • decoder: The above fields of this Block after having been cast to an ethutil.Value object.

func (self *Block) setHeader(header *ethutil.Value)
setHeader is an inner function that sets the header of this block,
given an ethutil.Value object that contains that information.

func NewUncleBlockFromValue(header *ethutil.Value) *Block
NewUncleBlockFromValue creates and sets the uncle of a block based
on an ethutil.Value object that contains that information.

  • header: an ethutil.Value object containing the header of the uncle block.
    The header of the uncle Block (and any Block) contains those fields:
    PrevHash, UncleSha, Coinbase, state, TxSha, ReceiptSha, LogsBloom,
    Difficulty, Number, GasLimit, GasUsed, Time, Extra, Nonce
    .
    See also the HashNoNonce function for details about these fields.

func (block *Block) Trie() *trie.Trie
Trie returns the block's state trie

func (block *Block) Root() interface{}
Root returns the block's state root

func (block *Block) Diff() *big.Int
Diff returns the block's difficulty.

func (self *Block) Receipts() []*Receipt
Receipts returns the block's receipts.

func (block *Block) miningHeader() []interface{}
miningHeader returns an object that is almost the same as a Block. The differences are:

  1. The Block struct also contains the uncles as a slice of Blocks and not only the uncles hash.
  2. The Block struct contains the state object as a whole and not the root of the state.
  3. The Block struct contains the receipts and not only the TxSha
  4. The Block struct contains the transactions and not only the ReceiptSha
  5. The Block struct contains the Reward to be given to the miner.
    The object returned, if appended with the Nonce field of the Block is the Block's header.

func (block *Block) header() []interface{}
header returns the header of the Block. See the function miningHeader for a detailed explanation.

func (block *Block) String() string
String returns the string representation of the block.

func (self *Block) Size() ethutil.StorageSize
Size returns a float64 object representing the size of storage needed to save this block's rlp-encoding.
The rlp-encodable fields of a Block are it's header, transactions and uncles.

func (self *Block) RlpData() interface{}
RlpData returns an object containing this block's rlp-encodable fields.
The rlp-encodable fields of a Block are it's header, transactions and uncles.
(this is also the order in which the returned object contains them).

func (self *Block) N() []byte
N returns the Nonce field of the block.


1.2 common.go

Only contains the definition of 2 interfaces.

type BlockProcessor interface {
	Process(*Block) (*big.Int, state.Messages, error)
}

Any type that implements the BlockProcessor interface must also implement the Process
function which is called upon a Block and calculates and returns in that order:
the total difficulty of the block, the messages of the block (aka the transactions) and/or an error.
In case of an error, the values returned by the function Process for the td and messages are nil.
In case of no errors, the error value returned by the Process function is nil.
Only a ChainManager object implements this interface.


type Broadcaster interface {
	Broadcast(wire.MsgType, []interface{})
}

Any object that implements the Broadcaster interface must also implement the function 'Broadcast',
which is used to broadcast messages of a given type to a list of recipients. The type of the message to
be broadcasted, wire.MsgType, is a single byte and is defined in the package wire (file wire/messaging.go).
Only a TxPool object implements this interface.


1.3 derive_sha.go


type DerivableList interface {
	Len() int
	GetRlp(i int) []byte
}

Any object that implements the DerivableList interface can then call the function DeriveSha.
Examples of objects that implement this interface are the Receipt and the Transaction objects.

  • Len(): returns the number of the elements of the object that implements this interface.
  • GetRlp(i int): returns the RLP-encoding of i-th element of the object that implements this interface.

func DeriveSha(list DerivableList) []byte
DerivableList contructs a trie based on the list parameter and returns the root hash of the trie.
Examples of objects that make use of this function are the Receipt and Transaction objects.


1.4 transaction.go

1.4.1 Data structures
type Transaction struct {
	nonce     uint64
	recipient []byte
	value     *big.Int
	gas       *big.Int
	gasPrice  *big.Int
	data      []byte
	v         byte
	r, s      []byte
}

Definition of a Transaction object. A Transaction object implements the Message interface.

  • Nonce: A value equal to the number of transactions that originated from
    this address or, in the case of accounts with associated code, the number
    of contract-creations made by this account.
  • recipient: The 160-bit address of the transaction's recipient or,
    for a contract creation transaction, nil.
  • value: This is equal to the number of Wei to be transferred to the
    transaction's recipient or, in the case of contract creation, as an
    endowment to the newly created account.
  • gas: The gas limit equal to the maximum amount of gas that should be
    used when executing this transaction.
  • gasPrice: This is equal to the number of Wei to be paid per unit of gas for
    all computation costs incurred as a result of the execution of this transaction.
  • data: An unlimited size byte array specifying the input data of the transaction.
    The first 4 bytes of this field specify which function to call when the transaction
    will execute by using the hash of the function's name to be called and it's arguments.
    The rest of the data field are the arguments passed to the function.
    If the data field is empty, it means a transaction is for a payment and not an execution of the contract.
  • v, r, s: Values corresponding to the ECDSA digital signature of the transaction and used to determine
    the originating Externally Owned Account.

type Transactions []*Transaction

The Transactions data type is defined as a means to

  1. sort Transactions and
  2. derive the root hash of a trie consisting of a list of transactions.

type TxByNonce struct{ Transactions }

the TxByNonce data type is used for to perform comparison operations on Transaction objects.


1.4.2 Functions

func IsContractAddr(addr []byte) bool
IsContractAddr returns true if the provided 'addr' has a length of 0, false otherwise.

func NewContractCreationTx(value, gas, gasPrice *big.Int, script []byte) *Transaction
NewContractCreationTx creates and returns a new Transaction which represents the creation of a contract.
The Transaction's 'recipient' field will be set to nil and the Transaction's 'data' field will be set to the 'script' parameter.
All other Transaction fields will be set to the corresponing parameters passed to this function
(except of course for the fields nonce,v,r,s which are not set)

func NewTransactionMessage(to []byte, value, gas, gasPrice *big.Int, data []byte) *Transaction
NewTransactionMessage creates and returns a new Transaction.
All Transaction fields will be set to the corresponing parameters passed to this function
(except of course for the fields nonce,v,r,s which are not set)

func NewTransactionFromBytes(data []byte) *Transaction
NewTransactionFromBytes creates and returns a new Transaction based on the 'data' parameter.
The latter should be a valid rlp-encoding of the Transaction object to be created.
(The 'data' param is converted to an ethutil.Value object first and then gets decoded)

func NewTransactionFromValue(val *ethutil.Value) *Transaction
NewTransactionFromValue creates and returns a new Transaction based on the 'val' parameter.
The latter should be a valid rlp-encoding - of the Transaction object to be created - that has been cast
to an ethutil.Value object.

func (tx *Transaction) Hash() []byte
Hash returns the hash of the caller. The hash will be the Kecchak-256 hash of these Transaction fields:
nonce, gasPrice, gas, recipient, value, data.
This function is implemented as part of the Message interface

func (self *Transaction) Data() []byte
Data returns the 'data' field of the caller.

func (self *Transaction) Gas() *big.Int
Gas returns the 'gas' field of the caller.
This function is implemented as part of the Message interface

func (self *Transaction) GasPrice() *big.Int
GasPrice returns the 'gasPrice' field of the caller.
This function is implemented as part of the Message interface

func (self *Transaction) Value() *big.Int
Value returns the 'value' field of the caller.
This function is implemented as part of the Message interface

func (self *Transaction) Nonce() uint64
Nonce returns the 'nonce' field of the caller.
This function is implemented as part of the Message interface

func (self *Transaction) SetNonce(nonce uint64)
SetNonce assigns the 'nonce' param to the caller's nonce field.

func (self *Transaction) From() []byte
From returns the 'sender' of the caller.
This function is implemented as part of the Message interface

func (self *Transaction) To() []byte
To returns the 'recipient' field of the caller.
This function is implemented as part of the Message interface

func (tx *Transaction) Curve() (v byte, r []byte, s []byte)
Curve returns v, r, s of the Transaction. r and s are left-padded to 32 bytes.
For more, see the function ethutil.leftPadBytes

func (tx *Transaction) Signature(key []byte) []byte
Signature calculates and returns the signature of the hash of a transaction with the param key.
The signature used to be obtained through the github.com/obscuren/secp256k1-go package repo
but this package no longer exists. One may now use the function Sign from:
https://github.com/ethereum/go-ethereum/blob/master/crypto/secp256k1/secp256.go

func (tx *Transaction) PublicKey() []byte
PublicKey retrieves and returns the public key of the transaction.
The public key used to be obtained through the github.com/obscuren/secp256k1-go
package repo but this package no longer exists. One may now use the function RecoverPubKey from:
https://github.com/ethereum/go-ethereum/blob/master/crypto/secp256k1/secp256.go

func (tx *Transaction) Sender() []byte
Sender returns the sender of the transaction. To do so, the public key of the transaction is first
retrieved through the function PublicKey. If the public key passes validation then the last 12
bytes of the public key are returned (aka the sender address).

func (tx *Transaction) Sign(privk []byte) error
Sign signes the transaction.
To do so, the function Signature is called (which makes use of a non-existent package, refer to it for more).
After the transaction has been signed the r,s,v fields of the Transaction are set to the signatures appropriate fields.
r is set to the first 32 bytes of thTransaction.e signature.
s is set to the 32-th up to and including the 63-th bytes of the signature.
v is set to the sum of the last bit of the transaction and the number 27.

func (tx *Transaction) RlpData() interface{}
RlpData returns the rlp-encodable fields of the caller (all fields of a Transaction object).

func (tx *Transaction) RlpValue() *ethutil.Value
RlpValue casts and returns the caller to an ethutil.Value object.

func (tx *Transaction) RlpEncode() []byte
RlpEncode returns the rlp-encoding of the cast of the caller object to an ethutil.Value object.
The cast is done through the RlpValue function.

func (tx *Transaction) RlpDecode(data []byte)
RlpDecode sets the caller's fields equal to the rlp-decoding of the 'data' parameter.
The data param must be a valid bytes representation of a Transaction that has been cast to an ethutil.Value object.

func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value)
RlpValueDecode sets the caller's fields equal to the rlp-decoding of the 'decoder'.
The decoder must be a valid bytes representation of a Transaction that has been cast to an ethutil.Value object.

func (tx *Transaction) String() string
String returns the string representation of the caller.

func (self Transactions) RlpData() interface{}
RlpData returns the rlp-encodable fields of all the Transaction objects that the caller consists of.

func (s Transactions) Len() int
Len returns the number of the Transaction objects that the caller consists of.
This function, along with the GetRlp function are implemented as parts of the DerivableList interface
in order to be able to call the DeriveSha function on a Transactions object, which would return the hash
of the root of the trie consisted of the Transaction objects that are included in the Transactions object.

func (s Transactions) GetRlp(i int) []byte
GetRlp returns the rlp-encoding of the i-th Transaction of the caller. This function, along with the Len function
are implemented as parts of the DerivableList interface in order to be able to call the DeriveSha function on
a Transactions object, which would return the hash of the root of the trie consisted of the Transaction objects
that are included in the Transactions object.

func (s TxByNonce) Less(i, j int) bool
Less returns true if the i-th Transaction of a list of Transactions is less than the j-th Transaction.
This is determined by only comparing the two Transactions' nonces.


1.5 receipt.go

1.5.1 Data structures

type Receipt struct {
	PostState         []byte
	CumulativeGasUsed *big.Int
	Bloom             []byte
	logs              state.Logs
}

The Receipt data structure represents the receipts field of a Transaction.
The receipt contains certain information regarding the execution of the transaction
and are mainly used for providing logs and events regarding the transaction.
Each receipt is placed on a trie.

  • PostState: the world state after the execution of the transaction this receipt refers to.
  • CumulativeGasUsed: The cumulative gas used up to and including the current transaction of a Block.
  • Bloom: A 'bloom' is composed from the log entries of the receipt. This field is the 2048-bit hash of that bloom.
    (See file bloom9.go)
  • logs: A series of log entries. Each entry is a tuple of the logger’s address, a possibly empty series of 32-byte log
    topics, and some number of bytes of data. The logs are created through the execution of a transaction.


type Receipts []*Receipt

The Receipts data type is defined as a means to

  1. sort Receipt objects and
  2. derive the root hash of a trie consisting of a list of receipts.


1.5.2 Functions

func NewReceipt(root []byte, cumalativeGasUsed *big.Int) *Receipt
NewReceipt creates a new Receipt provided the 'root' of the receipts trie and the cumulative gas used, and returns it.

func NewRecieptFromValue(val *ethutil.Value) *Receipt
NewRecieptFromValue creates a new Receipt from 'val' and returns it.
The val param should be the bytes representation of the rlp-encoded Receipt object to be created.

func (self *Receipt) SetLogs(logs state.Logs)
SetLogs sets the caller's logs field equal to the 'logs' parameter.

func (self *Receipt) RlpValueDecode(decoder *ethutil.Value)
RlpValueDecode sets the caller's (Receipt) fields to the rlp-decoded fields of the decoder parameter.

func (self *Receipt) RlpData() interface{}
RlpData returns the rlp-encodable fields of the caller. The only difference between what this function returns
and the caller's fields is that instead of the logs field this function returns the result of the function call logs.RlpData().

func (self *Receipt) RlpEncode() []byte
RlpEncode Returns the RLP-encoding of the rlp-encodable fields of a Receipt object.
These fields are obtained through the function RlpData

func (self *Receipt) Cmp(other *Receipt) bool
Cmp returns true if the caller Receipt is the same as the 'other', false otherwise.
Two Receipt objects are the same if their PostState fields are equal.

func (self *Receipt) String() string
String returns the string representation of the caller.

func (self Receipts) RlpData() interface{}
RlpData returns the rlp-encodable fields of the caller, aka an array that is populated with the result of the
consecutive calls to RlpData function for each of the Receipt objects that the Receipts caller object consists of.

func (self Receipts) RlpEncode() []byte
RlpEncode returns the rlp-encoding of the caller, aka rlp-encodes each Receipt object that the caller consists
of and returns the result.

func (self Receipts) Len() int
Len returns the number of Receipts that the caller consists of.
This function, along with the GetRlp function are implemented as parts of the DerivableList
interface in order to be able to call the DeriveSha function on a Receipts object, which would
return the hash of the root of the trie consisted of the Receipt objects that are included in the
Receipts object.

func (self Receipts) GetRlp(i int) []byte
GetRlp returns the rlp-encoding of the i-th Receipt of the caller.
This function, along with the Len function are implemented as parts of the DerivableList
interfacein order to be able to call the DeriveSha function on a Receipts object, which would
return the hash of the root of the trie consisted of the Receipt objects that are included in the
Receipts object.


1.6 bloom9.go

This file includes functions regarding the logsBloom field of a Block.
Every block contains many transactions. Each transaction has a receipt. Each receipt
has many logs. Each log consists of 3 fields: the address, the topics and the data.
The LogsBloom will be the lower 11 bits of the modulo operation by 2048 of the expression
kecchak-256(address and logs of all the receipts of the block's transactions).

"Events in the ethereum system must be easily searched for, so that applications can
filter and display events, including historical ones, without undue overhead. At the
same time, storage space is expensive, so we don't want to store a lot of duplicate data
- such as the list of transactions, and the logs they generate. The logs bloom filter
exists to resolve this.

When a block is generated or verified, the address of any logging contract,
and all the indexed fields from the logs generated by executing those transactions
are added to a bloom filter, which is included in the block header. The actual logs
are not included in the block data, to save space.

When an application wants to find all the log entries from a given contract, or with
specific indexed fields (or both), the node can quickly scan over the header of each
block, checking the bloom filter to see if it may contain relevant logs. If it does,
the node re-executes the transactions from that block, regenerating the logs, and
returning the relevant ones to the application."

Source:
https://ethereum.stackexchange.com/questions/3418/how-does-ethereum-make-use-of-bloom-filters

A thorough explanation on bloom filters:
https://brilliant.org/wiki/bloom-filter/

A complete example of the bloom filters on Ethereum:
https://medium.com/coinmonks/ethereum-under-the-hood-part-8-blocks-2-5fba93293213


1.6.1 Functions

func CreateBloom(receipts Receipts) []byte
CreateBloom creates the LogsBloom field of the given 'receipts', aka the LogsBloom field of a Block and returns it.
For each of the receipts, a logical OR operation happens between the so-far result and the result of a call to the
LogsBloom function call on the current receipt. Finally, the overall result is left-padded by 64 bytes and returned.

func LogsBloom(logs state.Logs) *big.Int
LogsBloom returns the LogBloom of the param logs, aka the LogBloom of a receipt, as a big.Int.
Steps to do so are as follows:

  1. Iterate over the logs field of the receipt.
  2. Create an array for every log. The array's first element will be the address of the log.
    All other elements will be the topics of the log.
  3. Initialize the result to be returned to 0 and iterate over that array.
  4. result = (previous_result) | (lower 11 bits of kecchak-256(current_element_of_array) % 2048)
    where the | operator is a logical OR operator.

func bloom9(b []byte) *big.Int
bloom9 is an inner function that returns the lower 11 bits of b % 2048.

func BloomLookup(bin, topic []byte) bool
BloomLookup checks whether the bin bloom has it's bit field of the 'topic' set to 1, aka the bloom may contain the 'topic'.
This function is only called by the bloomFilter function defined in the file core/filter.go. Even if the bit is set to 1 that
does not mean that the bin bloom will contain the topic. A bloom filter is like a hash table where instead of storing the values of the keys, a bit set to 1 indicates that there is a value with the specified key. That means that multiple values with different keys are mapped to the same bit field of the bloom filter. Only if that bit field is 0 we know that the bloom does not contain that value pair.


2. Package core

2.1 simple_pow.go

This file does not contain any code.

2.2 fees.go

Only contains the definition of the following variable:

var BlockReward *big.Int = big.NewInt(1.5e+18)
The BlockReward represents the initial block reward for miners, set to 1.5 Ether.
Only the function AccumelateRewards defined in the file block_manager.go uses this variable.


2.3 genesis.go

2.3.1 Data Structures

var ZeroHash256 = make([]byte, 32)
Used to set the parent's hash of the genesis block.

var ZeroHash160 = make([]byte, 20)
Used to set the coinbase of the genesis block.

var ZeroHash512 = make([]byte, 64)
Used to set the bloom field of the genesis block.

var EmptyShaList = crypto.Sha3(ethutil.Encode([]interface{}{}))
Used to set the root state of the genesis block.

var EmptyListRoot = crypto.Sha3(ethutil.Encode(""))
Used to set the tx root and receipt root of the genesis block.

var GenesisHeader = []interface{}{
	ZeroHash256,
	EmptyShaList,
	ZeroHash160,
	EmptyShaList,
	EmptyListRoot,
	EmptyListRoot,
	ZeroHash512,
	big.NewInt(131072),
	ethutil.Big0,
	big.NewInt(1000000),
	ethutil.Big0,
	ethutil.Big0,
	nil,
	crypto.Sha3(big.NewInt(42).Bytes()),
}

This is the special genesis block. The fields set are the same as those of a Block.

  • ZeroHash256: Previous hash (none)
  • EmptyShaList: Empty uncles
  • ZeroHash160: Coinbase, (aka miner's address)
  • EmptyShaList: Root state
  • EmptyListRoot: tx root
  • EmptyListRoot: receipt root
  • ZeroHash512: bloom field
  • big.NewInt(131072): difficulty
  • ethutil.Big0: block number
  • big.NewInt(1000000): Block upper gas bound
  • ethutil.Big0: Block gas used
  • ethutil.Big0: Time field
  • nil: Extra field.
  • crypto.Sha3(big.NewInt(42).Bytes()): Nonce field

var Genesis = []interface{}{GenesisHeader, []interface{}{}, []interface{}{}}
Genesis is defined so as to be able to RLP-encode the genesis block.
To rlp-encode any Block we provide it's header, transactions and uncles.
The genesis block does not have any transactions and uncles, thus the use of the 2 empty objects.
This variable is only used by the function NewChainManager defined in the file chain_manager.go.
For example, the function NewChainManager creates a new ChainManager object for which there
is a field that represents the genesis block. To set that block, the NewChainManager function uses
the ethutil.Encode(Genesis) function.


2.4 block_manager.go

2.4.1 Data Structures

var statelogger = logger.NewLogger("BLOCK")
statelogger is a channel used to log messages regarding Blocks processing.

type Peer interface {
	Inbound() bool
	LastSend() time.Time
	LastPong() int64
	Host() []byte
	Port() uint16
	Version() string
	PingTime() string
	Connected() *int32
	Caps() *ethutil.Value
}

This interface is only implemented by a Peer object defined in the 'eth' package (file peer.go)

  • Inbound(): Determines whether it's an inbound or outbound peer
  • LastSend(): Last known message send time.
  • LastPong(): Last received pong message
  • Host(): the host.
  • Port(): the port of the connection
  • Version(): client identity
  • PingTime(): Used to give some kind of pingtime to a node, not very accurate.
  • Connected(): Flag for checking the peer's connectivity state
  • Caps(): getter for the protocolCaps field of a Peer object.

type EthManager interface {
	BlockManager() *BlockManager
	ChainManager() *ChainManager
	TxPool() *TxPool
	Broadcast(msgType wire.MsgType, data []interface{})
	PeerCount() int
	IsMining() bool
	IsListening() bool
	Peers() *list.List
	KeyManager() *crypto.KeyManager
	ClientIdentity() wire.ClientIdentity
	Db() ethutil.Database
	EventMux() *event.TypeMux
}

The EthManager interface is only implemented by the 'Ethereum' object, defined in the package 'eth' (file ethereum.go)

  • BlockManager: Getter for the BlockManager field of the Ethereum object
  • ChainManager: Getter for the ChainManager field of the Ethereum object
  • TxPool: Getter for the TxPool field of the Ethereum object.
  • Broadcast: Used to broacast the 'data' msg to all peers.
  • IsMining: Returns whether the peer is mining.
  • IsListening: Returns whether the peer is listening.
  • Peers: Returns all connected peers.
  • KeyManager: Getter for the KeyManager field of the Ethereum object
  • ClientIdentity: Getter for the ClientIdentity field of the Ethereum object.
    That field is mainly used for communication between peers.
  • Db: Getter for the ethereum database of the Ethereum object.
    That field represents the World State.
  • EventMux: Getter for the EventMux field of the Ethereum object.
    That field is mainly used to dispatch events to registered nodes.

type BlockManager struct {
	mutex              sync.Mutex
	bc                 *ChainManager
	mem                map[string]*big.Int
	Pow                pow.PoW
	txpool             *TxPool
	lastAttemptedBlock *types.Block
	events             event.Subscription
	eventMux           *event.TypeMux
}

The BlockManager data structure is essentially a state manager for processing new blocks and managing the overall state.

  • mutex: Mutex for locking the block processor as Blocks can only be handled one at a time
  • bc: Canonical block chain
  • mem: non-persistent key/value memory storage
  • Pow: Proof of work used for validating
  • txpool: The transaction pool. See TxPool.
  • lastAttemptedBlock: The last attempted block is mainly used for debugging purposes.
    This does not have to be a valid block and will be set during 'Process' & canonical validation.
  • events: Provides a way to subscribe to events.
  • eventMux: event mutex, used to dispatch events to subscribers.


2.4.2 Functions

func NewBlockManager(txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockManager
NewBlockManager creates a new BlockManager object by initializing these fields of a BlockManager object type:
mem, Pow, bc, eventMux, txpool. The Pow object will have it's turbo field set to true when created.
See the type 'EasyPow' of the 'ezp' package for more (file pow/ezp/pow.go)

func (sm *BlockManager) TransitionState(statedb *state.StateDB, parent, block *types.Block) (receipts types.Receipts, err error)
TransitionState returns (receipts, nil) or (nil, error) if an GasLimitErr error has occured.
This function along with the ApplyTransactions function form a recursion algorithm meant to
apply all transactions of the current block to the world state. The main logic/ application happens
in the latter function. However, this function is the one to be called when we want to apply the
transactions of a block. The TransitionState function sets the total gas pool (amount of gas left)
for the coinbase address of the block before calling the ApplyTransactions function which in turn
will call the TransitionState function again, and so on, until all transactions have been applied or a
GasLimitErr error has occured. If no such an error has occured then the 'receipts' object returned by
this function will hold the receipts that are the result of the application of the transactions of the block param.

func (self *BlockManager) ApplyTransactions(
		coinbase *state.StateObject, 
		state *state.StateDB, 
		block *types.Block, 
		txs types.Transactions, 
		transientProcess bool
	)
	(
		types.Receipts, 
		types.Transactions, 
		types.Transactions, 
		types.Transactions, 
		error
	)

The ApplyTransactions function will apply the transactions of a block to the world state and return the results as a tuple.
It gets called by the TransitionState function, then calls the latter again, and so on, to form a recursion algorithm that will apply the transactions one by one. In case where a GasLimitErr error occurs during the application of any transaction, the processing of the transactions stops.

Returns: (receipts, handled, unhandled, erroneous, err)

  • receipts: The receipts up to but not including any transaction that has caused a GasLimitErr error.
  • handled: All transactions that were handled up to but not including any transaction that has caused a GasLimitErr error.
  • unhandled: In case of a GasLimitErr error this object will contain all the transactions that were not applied
    (includes the transaction that caused the error). Otherwise, this object will be nil.
  • erroneous: Any transactions that caused an error other than a GasLimitErr and/or a NonceErr errors.
  • err: The err will be either a GasLimitErr error or nil.

A short description on what this function does follows.

  1. Clear all state logs.

  2. Get (or create a new) coinbase state object and call the TransitionState func.

  3. The latter function will call this function again, forming the recursion.

  4. If an error occured and is a GasLimitErr error then stop the process and set the unhandled variable (to be returned later). If it is a NonceErr error, ignore it. If it is any other error, also ignore it, but also append to the variable erroneous
    (to be returned later) the transaction that caused that error.

  5. Calculate the gas used so far and the current reward for the miner. Update the state.

  6. Create the receipt of the current transaction and set the receipt's logs and Bloom field.

  7. If the parameter transientProcess is false, notify all subscribers about the transaction.

  8. Append receipt, transaction to the receipts, handled variables (to be returned later)

  9. When the processing has ended, set the block's reward and totalUsedGas fields.

  10. Return the results.

func (sm *BlockManager) Process(block *types.Block) (td *big.Int, msgs state.Messages, err error)
Process processes a block. When successful, returns the return result of a call to the ProcessWithParent function.
Otherwise, in case that the hash of the block or the hash of the parent of the block already exist in the ChainManager,
returns the tuple (nil, nil KnownBlockError) or (nil, nil, ParentError) accordingly. Before calling the ProcessWithParent
function, Process takes care of locking the BlockManager with a mutex and only after the ProcessWithParent
function has returned the BlockManager is unlocked.

func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.Int, messages state.Messages, err error)
ProcessWithParent is the main process function of a block. Gets called by the function Process.

Returns a tuple (td, messages, error) where

  • td: total difficulty of the processed block_
  • messages: messages generated by the application of the transactions of the block_
    (and some extra messages like transactions regarding rewarding miners).
  • If an error occured the returned tuple becomes (nil, nil, error).
    If no errors have occured the returned tuple becomes (td, messages, nil).

Below follows a short description of what this function does:

  1. Saves a copy of the state. Also queues a reset of the state after the function's
    return based on that copy. (use of golang's defer)
  2. Validates the block_ with a call to the function ValidateBlock. If errors happened, returns.
  3. Calls TransitionState to attempt to do the state transition. If errors, returns.
  4. Creates the bloom field of the receipts returned from step 2. If for some reason the bloom
    field is different from the bloom field of the provided block_, it returns.
  5. Validates the transactions and the receipts root hashes. If errors, returns.
  6. Calls AccumelateRewards to calculate the miner rewards. If errors, returns.
  7. Sets the state to 0 and makes a call to CalculateTD in order to calculate the total difficulty of the block_.
    If errors, returns. If not, the last step is to remove the block_'s transactions from the BlockManager's txpool,
    sync the state db, cancel the queued state reset, send a message to the chainlogger channel and finally
    return the tuple (td, messages, nil).

func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool)
BlockManager.CalculateTD calculates the total difficulty for a given block. If the calculated total difficulty
is greater than the previous, the tuple (total_difficulty, true) is returned. Otherwise, the tuple (nil, false) is returned.
TD(genesis_block)=0 and TD(block)=TD(block.parent) + sum(u.difficulty for u in block.uncles) + block.difficulty.

func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error
BlockManager.ValidateBlock validates the current block.
Returns an error if the block was invalid, an uncle or anything that isn't on the current block chain.
Validation validates easy over difficult (dagger takes longer time = difficult)

func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent *types.Block) error
BlockManager.AccumelateRewards calculates the reward of the miner.
Returns an error if an error has occured during the validation process.
If no errors have occured, nil is returned. More specifically an error is returned if:

  1. the parent of any of the uncles of the block is nil, or
  2. the (block) number of the parent of any of the uncles of the block and
    the block itself have a difference greater than 6, or
  3. the hash of any of the uncles of the param block matches any of the uncles of the param parent.
  4. the nonce of any of the uncles of the param block is included in the nonce of the block

The reward to be appointed to the miner will be:

  • If the block has 1 uncle:
    r1 = BlockReward + BlockReward/32,
  • If the block has 2 uncles:
    r2 = r1 + r1/32, etc.

Finally, a message is added to the state manifest regarding the value to be transferred to the miner address.
This value will be the sum of the above calculated reward and the block.Reward field.

func (sm *BlockManager) GetMessages(block *types.Block) (messages []*state.Message, err error)
BlockManager.GetMessages returns either the tuple (state.Manifest().Messages, nil) or (nil, error).

If an error is returned it will be a ParentError regarding the parent of the block (the error includes the hash of the parent of the block). This error happens in the case where the the hash of the parent of the block already exists. In essence, the state manifest's messages are the transactions that occured during the world state transition of the addition of a block. To get those messages a simple trick is used: a deferred call on state.Reset() is queued and only then a call of the function TransitionState and following that a call on AccumelateRewards is made.


2.5 chain_manager.go

2.5.1 Data Structures

var chainlogger = logger.NewLogger("CHAIN")
chainlogger is a channel used to log messages regarding the chain.

type ChainManager struct {
	processor       types.BlockProcessor
	eventMux        *event.TypeMux
	genesisBlock    *types.Block
	mu              sync.RWMutex
	td              *big.Int
	lastBlockNumber uint64
	currentBlock    *types.Block
	lastBlockHash   []byte
	transState      *state.StateDB
}

The ChainManager is mainly used for the creation of the Genesis or any other blocks.

  • processor: An interface. A neat way of calling the function Process of a BlockManager object.
  • eventMux: Used to dispatch events to subscribers.
  • genesisBlock: The special genesis block.
  • mu: a mutex for the ChainManager object.
  • td: the total difficulty.
    TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty
  • lastBlockNumber: the last block's number. (the last successfully inserted block on the chain)
  • currentBlock: During the creation of a new block, the currentBlock will point to the parent
    of the block to be created.
  • lastBlockHash: the last block's hash.
  • transState: represents the world state.


2.5.2 Functions

func AddTestNetFunds(block *types.Block)
AddTestNetFunds sets the following accounts with a balance of
1606938044258990275541962092341162602522202 Ether for testing:

  • 1ba59315b3a95761d0863b05ccc7a7f54703d99
  • 4157b34ea9615cfbde6b4fda419828124b70c78
  • 9c015918bdaba24b4ff057a92a3873d6eb201be
  • c386a4b26f73c802f34673f7248bb118f97424a
  • d2a3d9f938e13cd947ec05abc7fe734df8dd826
  • ef47100e0787b915105fd5e3f4ff6752079d5cb
  • 6716f9544a56c530d868e4bfbacb172315bdead
  • a26338f0d905e295fccb71fa9ea849ffa12aaf4

This function gets only called indirectly from a ChainManager object, and more specifically from the functions Reset and setLastBlock.
The latter only calls this function if the chain has 0 blocks so far. As one might have guessed already, when this functions gets called
the block parameter is always set to the Genesis variable.

func CalcDifficulty(block, parent *types.Block) *big.Int
CalcDifficulty calculates the difficulty of a block and returns it. If the block was mined in less than 5 seconds, the difficulty of the block
is increased by 1/1024th of the parent's difficulty. If the block was mined in more than 5 seconds, the difficulty is decreased by 1/1024th
of the parent's difficulty.

func (self *ChainManager) Td() *big.Int
Td returns the total difficulty.
TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty

func (self *ChainManager) LastBlockNumber() uint64
LastBlockNumber returns the last block number.

func (self *ChainManager) LastBlockHash() []byte
LastBlockHash returns the last block's hash.

func (self *ChainManager) CurrentBlock() *types.Block
CurrentBlock returns the current block.

func NewChainManager(mux *event.TypeMux) *ChainManager
NewChainManager creates and returns a new ChainManager object by setting the genesis block
and the eventMux field of the ChainManager. When creating the Genesis block - or any other block -
the RLP-encoding of that block is used and this is the exact purpose of the Genesis variable:
it represents the RLP-encodable fields of the genesis block.

func (self *ChainManager) SetProcessor(proc types.BlockProcessor)
SetProcessor sets the processor field of the caller.

func (self *ChainManager) State() *state.StateDB
State returns the world state. Access on the current state happens through the
CurrentBlock field of the ChainManager object that made the call to this function.

func (self *ChainManager) TransState() *state.StateDB
TransState returns the transState field of the caller.

func (bc *ChainManager) setLastBlock()
setLastBlock is an inner function, that gets called by the NewChainManager function.
If the chain has 0 blocks so far, setLastBlock makes a call to the function AddTestNetFunds
and also sets the currentBlock, lastBlockHash, lastBlockNumber and td fields of the ChainManager.
Otherwise it makes a call to the Reset function. In all cases, a message is sent to the chainlogger
channel which logs the lastBlockNumber and currentBlock.Hash fields of the ChainManager
after the processing has happened.

func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block
NewBlock provides a way of creating a new block through a ChainManager object. It creates a new
block by making a call to the function CreateBlock, sets the created block's difficulty, number and
gaslimit and returns the block. coinbase is the block's beneficiary address. The ChainManager remains
locked starting with the call of this function and until it has returned.

func (bc *ChainManager) Reset()
Reset resets the chain to the point where the chain will only contain the genesis block. This includes
the call of the function AddTestNetFunds. The ChainManager remains locked starting with the call of
this function and until it has returned.

func (self *ChainManager) Export() []byte {
Export returns the RLP-encoding of all blocks of the chain. A message is sent to the chainlogger
channel containing the number of the currentBlock block field of the ChainManager.
The ChainManager remains locked starting with the call of this function and until it has returned.

func (bc *ChainManager) insert(block *types.Block)
insert is an inner function, used to insert a block on the chain.
What actually gets inserted into the chain is the block's rlp-encoding.
This function is called by the InsertChain and the Reset functions.

func (bc *ChainManager) write(block *types.Block)
write is an inner function, used to write a block to the database.
Gets called by the InsertChain and the Reset functions.

func (bc *ChainManager) Genesis() *types.Block
Genesis returns the genesis block of the chain.

func (bc *ChainManager) HasBlock(hash []byte) bool
HasBlock returns whether the given hash param matches the hash of a block of the chain.

func (self *ChainManager) GetChainHashesFromHash(hash []byte, max uint64) (chain [][]byte)
GetChainHashesFromHash returns a list of hashes of the chain starting from the genesis
hash and up to, and including, the max block number. The hash and the max params
should match the hash and the number of a specific block.

func (self *ChainManager) GetBlock(hash []byte) *types.Block
GetBlock returns the block of the chain that has the given hash.

func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block
GetBlockByNumber returns the block of the chain that has the given num.

func (bc *ChainManager) setTotalDifficulty(td *big.Int)
setTotalDifficulty sets the total difficulty of the ChainManager object. Also stores that information on the database.

func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error)
CalcTotalDiff calculates the total difficulty of the ChainManager and returns it in a tuple (td, nil).
If an error occured, then the tuple (nil, error) is returned.
TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty.

func (bc *ChainManager) BlockInfo(block *types.Block) types.BlockInfo
BlockInfo returns the block's BlockInfo object representation.

func (bc *ChainManager) writeBlockInfo(block *types.Block)
writeBlockInfo is an inner function for writing the block's BlockInfo representation to the database.
This is extra information that normally should not be saved in the db.

func (bc *ChainManager) Stop()
Stop sends a stop message to the chain logger channel if and only if the currentBlock
field of the ChainManager caller object is not nil.

func (self *ChainManager) InsertChain(chain types.Blocks) error
InsertChain
iterates over the blocks in the chain param and does the following:

  1. It calls the Process method of the BlockProcessor interface.
  2. writes the block to the database.
  3. sets the total difficulty of the block.
  4. inserts the block into the chain.
  5. posts a NewBlockEvent to the event mux.
  6. posts the messages to the event mux.
    Returns: either nil for success or an error.


2.6 transaction_pool.go

2.6.1 Data Structures

var txplogger = logger.NewLogger("TXP")
txplogger is a channel used to log messages regarding Blocks processing.

const txPoolQueueSize = 50
Used to initialize the queueChan field of a TxPool (which is used as a queue channel to reading and writing transactions)

type TxPoolHook chan *types.Transaction
Although defined, this type is never used in this go-ethereum version.

const (
	minGasPrice = 1000000
)

Although defined, this variable is never used in this go-ethereum version.

var MinGasPrice = big.NewInt(10000000000000)
Although defined, this variable is never used in this go-ethereum version.

type TxMsgTy byte
The only use of a TxMsgTy type is as a field of a TxMsg type. Although it's not clear how this type is supposed to be used,
since there are no other references to it in the whole codebase, we could make a guess based on the fact that there are
3 types of transactions in ethereum:

  1. Regular transactions: a transaction from one wallet to another.
  2. Contract deployment transactions: a transaction without a to address, where the data field is used for the contract code.
  3. Execution of a contract: a transaction that interacts with a deployed smart contract.
    In this case, to address is the smart contract address.

TxMsgTy may had been used to represent the above types of transactions.

type TxMsg struct {
	Tx   *types.Transaction
	Type TxMsgTy
}

TxMsg represents the type of the channel of the subscribers field of a TxPool object.
However, that field is never actually used in the whole codebase of this go-ethereum version.

type TxProcessor interface {
	ProcessTransaction(tx *types.Transaction)
}

The TxProcessor interface, although defined, is not implemented at all in the whole codebase
of this go-ethereum version.

type TxPool struct {
	mutex              sync.Mutex
	queueChan          chan *types.Transaction
	quit               chan bool
	pool               *list.List
	SecondaryProcessor TxProcessor
	subscribers        []chan TxMsg
	broadcaster        types.Broadcaster
	chainManager       *ChainManager
	eventMux           *event.TypeMux
}

TxPool is a thread safe transaction pool handler. In order to guarantee a non blocking pool the queueChan
is used which can be independently read without needing access to the actual pool. If the pool is being drained
or synced for whatever reason, the transactions will simply queue up and be handled when the mutex is freed.
mutex: a mutex for accessing the Tx pool.
queueChan: Queueing channel for reading and writing incoming transactions to.
quit: Quiting channel (quitting is equivalent to emptying the TxPool)
pool: The actual pool, aka the list of transactions.
SecondaryProcessor: This field is actually never used as the TxProcessor interface is not implemented.
subscribers: Although defined, this channel is never used.
broadcaster: used to broadcast messages to all connected peers.
chainManager: the chain to which the TxPool object is attached to.
eventMux: used to dispatch events to subscribers.

2.6.2 Functions

func EachTx(pool *list.List, it func(*types.Transaction, *list.Element) bool)
EachTx is used as a means to iterate over the pool list of transactions.

func FindTx(pool *list.List, finder func(*types.Transaction, *list.Element) bool) *types.Transaction
FindTx searches in the caller's transactions for finder and returns either the matching transaction if found, or nil.
This is a neat way of searching for transactions that match the criteria defined from the finder param. For example,
Add uses the hash of a transaction as a searching criterion.

func NewTxPool(chainManager *ChainManager, broadcaster types.Broadcaster, eventMux *event.TypeMux) *TxPool
NewTxPool creates a new TxPool object and sets it's fields.

  • TxPool.pool will be set to an empty list.
  • TxPool.queueChain wil be set to a Transaction channel with a txPoolQueueSize size.
  • TxPool.quit will be set to a boolean channel.
  • TxPool.chainManager will be assigned the param chainManager.
  • TxPool.eventMux will be assigned the param eventMux.
  • TxPool.broadcaster will be assigned the param broadcaster.

All other fields of the TxPool object that gets created are not set by NewTxPool.

func (pool *TxPool) addTransaction(tx *types.Transaction)
addTransaction is an inner function used to add the Transaction tx to the end of the TxPool. This function also
broadcasts a msg to all peers which contains the rlp-encodable fields of the tx (See RlpData). The TxPool
remains locked starting with the call of this function and until it has returned.

func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error
ValidateTransaction validates the tx Transaction. Returns either an error if tx can not be validated or nil.
These are the cases where tx is not validated:

  1. For some reason, the currentBlock field of the chainManager field of the caller is nil. (aka the chain is empty)
  2. The recipient field (to) of tx is is either nil or != 20 bytes. This means that trying to validate contract creation
    transactions, (for which the recipient to is set to nil) will always return an error.
  3. The v field of tx is neither 28 nor 27. (See Transaction)
  4. The sender account of tx does not have enough Ether to send to the recipient of tx.

func (self *TxPool) Add(tx *types.Transaction) error
Add is the function to be called for adding a Transaction to the TxPool caller. Returns either an error on not successfully
adding tx or nil for success. If tx was added, a message is posted to the subscribed peers, containing the tx from, to, value
and hash fields. An error is returned in any of these cases:

  1. tx's hash already exists in the TxPool caller, aka the transaction to be added is already part of the caller.
  2. tx validation returned an error when calling ValidateTransaction.

If no errors are produced from steps 1 and 2, Add makes a call to the inner function addTransaction to add tx to the current
TxPool.

func (self *TxPool) Size() int
Size returns the number of Transactions of the caller.

func (pool *TxPool) CurrentTransactions() []*types.Transaction
CurrentTransactions returns the transactions of the TxPool caller as a slice.

func (pool *TxPool) RemoveInvalid(state *state.StateDB)
RemoveInvalid removed all transactions from the caller for which either:

  1. the transaction returns an error when validated through the ValidateTransaction function, or
  2. the transaction sender's nonce field is >= to the transaction's nonce field.

func (self *TxPool) RemoveSet(txs types.Transactions)
RemoveSet takes as an argument a set of transactions txs and removes from the caller's transactions set those that
match the ones from txs. Looping over the transactions of the caller happens through the EachTx function.

func (pool *TxPool) Flush() []*types.Transaction
Flush resets the caller's transactions list to an empty list.

func (pool *TxPool) Start()
Although defined, this function does not contain any executable code in this go-ethereum version.

func (pool *TxPool) Stop()
Stop makes a call on Flush to empty the caller's transactions list
and then sends the message "Stopped" to the txplogger channel.


2.7 asm.go

The file contains only one function:

func Disassemble(script []byte) (asm []string)
Disassemble returns a string representation of a sequence of bytes that consist an evm bytecode.
The opcodes are defined in vm/types.go. In case that we have a PUSHi opcode we expect the next i
bytes to be the i items that we want to push to the stack.
script: The evm bytecode.

An example can be found here:
https://rinkeby.etherscan.io/address/0x147b8eb97fd247d06c4006d269c90c1908fb5d54#code

Example: Passing the first series of bytes of the above link to this function as

script := []byte(
					0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 
					0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 
					0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50
				)

will yield the following output which is presented in a more human-readable way.
The first column is only there to show match the bytes of the input with the results.

0x60 --> 0000: PUSH1
0x80 --> 0001: 0x80
0x60 --> 0002: PUSH1 (next value is pushed onto the stack)
0x40 --> 0003: 0x40
0x52 --> 0004: MSTORE
0x34 --> 0005: CALLVALUE
0x80 --> 0006: DUP1
0x15 --> 0007: ISZERO
0x61 --> 0008: PUSH2 (next 2 values are pushed onto the stack)
0x00 --> 0009: 0x00
0x10 --> 0010: 0x10
0x57 --> 0011: JUMPI
0x60 --> 0012: PUSH1
0x00 --> 0013: 0x00
0x80 --> 0014: DUP1
0xfd --> 0015: Missing opcode 0xfd
0x5b --> 0016: JUMPDEST
0x50 --> 0017: POP


2.8 error.go

2.8.1 Data structures
type UncleErr struct {
	Message string
}

UncleErr error. This error is thrown only from the function AccumelateRewards.

type ParentErr struct {
	Message string
}

ParentErr error. In case a parent is unknown this error will be thrown by the block manager.

type ValidationErr struct {
	Message string
}

ValidationErr is a block validation error. If any validation fails, this error will be thrown.

type GasLimitErr struct {
	Message string
	Is, Max *big.Int
}

A GasLimitErr happens when the total gas left for the coinbase address is less than the gas to be bought.

type NonceErr struct {
	Message string
	Is, Exp uint64
}

A NonceErr happens when a transaction's nonce is incorrect.

type OutOfGasErr struct {
	Message string
}

A OutOfGasErr happens when the gas provided runs out before the state transition happens.

type TDError struct {
	a, b *big.Int
}

TDError is defined, but never used in this go-ethereum version. Meant to be used as a total difficulty error.

type KnownBlockError struct {
	number *big.Int
	hash   []byte
}

A KnownBlockError happens when there is already a block in the chain with the same hash.
The number field is the number of the existing block.


2.8.2 Functions

func (self *TDError) Error() string
TDError.Error creates and returns a TDError error.

func (self *KnownBlockError) Error() string
KnownBlockError.Error creates and returns a KnownBlockError error.

func ParentError(hash []byte) error
ParentError creates a ParentError object by setting it's message to a message
that includes the 'hash' and returns it.

func UncleError(str string) error
UncleError creates an UncleErr error by setting it's message to 'str' and returns it.

func ValidationError(format string, v ...interface{}) *ValidationErr
ValidationError creates a ValidationErr error by setting it's message and returns it.

func GasLimitError(is, max *big.Int) *GasLimitErr
GasLimitError creates and returns a GasLimitError given the total gas left
to be bought by a coinbase address and the actual gas.

func NonceError(is, exp uint64) *NonceErr
NonceError creates and returns a NonceError given the transaction's nonce
and the nonce of the sender of the transaction.

func OutOfGasError() *OutOfGasErr
OutOfGasError creates and returns an OutOfGasError error.

func IsParentErr(err error) bool
IsParentErr returns whether 'err' is a ParentErr error.

func IsUncleErr(err error) bool
IsUncleErr returns whether 'err' is an UncleErr error.

func IsValidationErr(err error) bool
IsValidationErr returns whether 'err' is a ValidationErr error.

func IsGasLimitErr(err error) bool
IsGasLimitErr returns whether 'err' is a GasLimitErr error.

func IsNonceErr(err error) bool
IsNonceErr returns whether 'err' is a NonceErr error.

func IsOutOfGasErr(err error) bool
IsOutOfGasErr returns whether 'err' is an OutOfGasErr error.

func IsTDError(e error) bool
IsTDError returns whether 'e' is a TDError error.

func IsKnownBlockErr(e error) bool
IsKnownBlockErr returns whether 'e' is a KnownBlockErr error.

func (err *ParentErr) Error() string
ParentErr.Error returns the error message of the caller.

func (err *UncleErr) Error() string
UncleErr.Error returns the error message of an UncleErr error.

func (err *ValidationErr) Error() string
ValidationErr.Error returns the error message of a ValidationErr error.

func (err *GasLimitErr) Error() string
GasLimitErr.Error returns the error message of a GasLimitErr error.

func (err *NonceErr) Error() string
returns the error message of a NonceErr error.

func (self *OutOfGasErr) Error() string
OutOfGasErr.Error returns the error message of an OutOfGasError error.


2.9 event.go

2.9.1 Data Structures

type TxPreEvent struct{ Tx *types.Transaction }
A TxPreEvent is posted when a transaction enters the transaction pool.

type TxPostEvent struct{ Tx *types.Transaction }
A TxPostEvent is posted when a transaction has been processed.

type NewBlockEvent struct{ Block *types.Block }
A NewBlockEvent is posted when a block has been imported.


2.10 dagger.go

Dagger is the consensus algorithm.

Dagger was proven to be vulnerable to shared memory hardware acceleration:
https://bitslog.com/2014/01/17/ethereum-dagger-pow-is-flawed/

The consensus algorithm for Ethereum 1.0 is Ethash (PoW algorithm):
https://eth.wiki/en/concepts/ethash/ethash


Essentially, the Dagger algorithm works by creating a directed acyclic graph with ten levels
including the root and a total of 225 - 1 values. In levels 1 through 8, the value of each node
depends on three nodes in the level above it, and the number of nodes in each level is eight
times larger than in the previous. In level 9, the value of each node depends on 16 of its
parents, and the level is only twice as large as the previous; the purpose of this is to make the
natural time-memory tradeoff attack be artificially costly to implement at the first level, so that
it would not be a viable strategy to implement any time-memory tradeoff optimizations at all.
Finally, the algorithm uses the underlying data, combined with a nonce, to pseudorandomly select
eight bottom-level nodes in the graph, and computes the hash of all of these nodes put together.
If the miner finds a nonce such that this resulting hash is below 2^256 divided by the difficulty
parameter, the result is a valid proof of work.

Here is the breakdown of the algorithm that the below functions implement:

  • D: block header
  • N: nonce
  • ||: string concatenation operator.
if L==9
	dependsOn(L)=16
else
	dependsOn(L)=3

Node(D,xn,0,0)=D
Node(D,xn,L,i) =
	for k in [0...dependsOn(L)-1]
		p[k] = sha256(D || xn || L || i || k) mod 8^(L-1)
		sha256(node(L-1,p[0]) || node(L-1,p[1]) ... || node(L-1,p[dependsOn(L)-1]))

eval(D,N) =
	for k in [0...3]
		p[k] = 	sha256( D  || floor(n / 2^26) || i || k ) mod 8^8 * 2 
	
		sha256(	node( D,floor(n / 2^26),9,p[0])  ||  node(D,floor(n / 2^26),9,p[1]) ... 
			... || node(D,floor(n / 2^26),9,p[3])))

Objective: find k such that eval(D,k) < 2^256 / diff

2.10.1 Functions

func (dag *Dagger) Find(obj *big.Int, resChan chan int64)

func (dag *Dagger) Search(hash, diff *big.Int) *big.Int

func (dag *Dagger) Verify(hash, diff, nonce *big.Int) bool

func DaggerVerify(hash, diff, nonce *big.Int) bool

func (dag *Dagger) Node(L uint64, i uint64) *big.Int

func Sum(sha hash.Hash) []byte

func (dag *Dagger) Eval(N *big.Int) *big.Int


2.11 state_transition.go

2.11.1 Data Structures
type StateTransition struct {
	coinbase, receiver []byte
	msg                Message
	gas, gasPrice      *big.Int
	initialGas         *big.Int
	value              *big.Int
	data               []byte
	state              *state.StateDB
	block              *types.Block

	cb, rec, sen *state.StateObject

	Env vm.Environment
}

A StateTransition. A state transition is a change made when a transaction is applied
to the current world state. The state transitioning model does all
the necessary work to work out a valid new state root:

  1. Nonce handling
  2. Pre pay / buy gas of the coinbase (miner)
  3. Create a new state object if the recipient is 0, aka contract creation.
  4. Value transfer
    == If contract creation ==
    4a. Attempt to run transaction data
    4b. If valid, use result as code for the new state object
    == end ==
  1. Run Script section
  2. Derive the new state root

  • coinbase: The miner state object.
  • receiver: The receiver state object (in case of Ether transfer)
  • msg: Representation of the transaction to be applied.
  • gas: The gas limit equal to the maximum amount of gas that should be
    used when executing the msg/transaction.
  • gasPrice: This is equal to the number of Wei to be paid per unit of gas for
    all computation costs incurred as a result of the execution of the msg/transaction.
  • initialGas: The gas that has been supplied for the execution of the msg/transaction.
  • value: The amount of Wei to be transferred.
  • data: An unlimited size byte array specifying the input data of the msg/transaction.
    The first 4 bytes of this field specify which function to call when the msg/transaction
    will execute by using the hash of the function's name to be called and it's arguments.
    The rest of the data field are the arguments passed to the function.
    If the data field is empty, it means a msg/transaction is for a payment and not an execution of the contract.
  • state: The current world state before the execution of the msg/transaction.
  • block: The block (to be added to the chain) that contains the msg to be executed.
  • cb: The miner's address.
  • rec: The receiver's address.
  • sen: The sender's address.


type Message interface {
	Hash() 			[]byte
	From() 			[]byte
	To() 			[]byte
	GasPrice() 		*big.Int
	Gas() 			*big.Int
	Value() 		*big.Int
	Nonce() 		uint64
	Data() 			[]byte
}

A Message represents a transaction. All functions of this interface are
getter functions for the relevant fields of the msg/transaction.


2.11.2 Functions

func AddressFromMessage(msg Message) []byte
AddressFromMessage creates and returns a new address based on the msg sender and nonce fields.

func MessageCreatesContract(msg Message) bool
MessageCreatesContract returns whether the msg is a contract creation aka whether the msg recipient is 0.

func MessageGasValue(msg Message) *big.Int
MessageGasValue returns the amount of Wei based on the msg gas and gasPrice fields.
gasValue = gas * gasPrice

func NewStateTransition(coinbase *state.StateObject, msg Message, state *state.StateDB, block *types.Block) *StateTransition
NewStateTransition creates and returns a StateTransition object.
The fields gas and initialGas are set to 0.
The fields rec, sen and Env are set to nil.
The field coinbase is set to the address of the coinbase param.
The field cb is set to the param coinbase.
All other fields are set to the corresponding params.

func (self *StateTransition) VmEnv() vm.Environment
VmEnv is a getter method for the Env field of a StateTransition object.
If the Env field of the caller is nil, a new Env is created by calling the function NewEnv.

func (self *StateTransition) Coinbase() *state.StateObject
Coinbase returns the miner of the msg's block. If the miner does not exist in the current world state, it's created.

func (self *StateTransition) From() *state.StateObject
From returns the from field of the msg. If from does not exist in the current world state, it's created.

func (self *StateTransition) To() *state.StateObject
To returns the to field of the msg. If to does not exist in the current world state, it's created.
This function will return nil in the case where the msg is about a contract creation (aka if to is 0)

func (self *StateTransition) UseGas(amount *big.Int) error
UseGas attempts to use amount gas of the caller's gas. If the caller's gas is less than the amount provided,
an OutOfGasError is returned. Otherwise, nil is returned for success. In case of success, the new
gas of the caller will become:
newGas = prevGas - amount.

func (self *StateTransition) AddGas(amount *big.Int)
AddGas adds amount gas to the caller's gas. Helps in keeping track of the altogether used gas of a list of transactions.

func (self *StateTransition) BuyGas() error
BuyGas attempts to reward the miner with the gas of the transaction. If the sender's balance is less than the calculated gas in Wei (gas*gasPrice of caller), an error is returned. Buying the gas does not directly happen in this function. Instead, the BuyGas function of the miner (StateObject) is called through this function. If the latter does not return an error, this function will increase the gas field of the caller, set the caller's initialGas field and decrease the sender's balance by an amount of gas *gasPrice

func (self *StateTransition) preCheck() (err error)
preCheck is an inner function, used by the TransitionState function and does 2 things:

  1. Checks whether the caller's msg sender nonce is the same as the caller's msg nonce. If not, it returns an error.
  2. Calls BuyGas in order to reward the miner. If BuyGas returns an error, this function returns that error.
    If everything went well, this function returns nil.

func (self *StateTransition) TransitionState() (ret []byte, err error)
TransitionState attempts to alter the world state by applying the msg/transaction of the caller.

  1. Calls preCheck for nonce validation and to reward the miner.
  2. Schedules a gas refund (to return the unused gas)
  3. increases nonce of the msg sender.
  4. uses the TxGas. (defined as Gtransaction in the Ethereum Yellow Paper) TxGas is a constant value set to 500 Wei. (see the GasTx variable defined in vm/common.go) On the Ethereum Yellow Paper this value is set to 21000 Wei.
  5. uses the GasData. This is the gas that must be payed for every byte of the log field of the msg. On the Ethereum Yellow Paper this value is set to 8 Wei per byte.
  6. If the msg is about a contract creation (msg recipient is 0) this function makes a call to the MakeContract, uses the appropriate gas needed and sets the code of the to-be-deployed contract.
  7. If the msg is not a contract creation msg, a call to the vm's Call function is made. The vm takes care of executing the transaction and may return an error.
  8. In case where none of the above operations returned an error, a call on UseGas is made.
  9. As usual, in case of any errors the returned tuple will be (nil, error) or in case of no errors, the error returned will be nil and the ret field of the tuple will contain the returned result of the vm of steps 6 or 7.

func MakeContract(msg Message, state *state.StateDB) *state.StateObject
MakeContract converts an transaction in to a state object. The stateObject that this function creates and returns may then be used (as a param) to actually deploy the contract through the vm Create function.

func (self *StateTransition) RefundGas()
RefundGas takes care of refunding gas any remaining gas in case of a successful msg/transaction execution.

func (self *StateTransition) GasUsed() *big.Int
GasUsed returns how much gas has been used by the execution of the msg/transaction


2.12 vm_env.go

2.12.1 Data Structures
type VMEnv struct {
	state 	*state.StateDB
	block 	*types.Block
	msg   	Message
	depth 	int
}

The VMEnv represents the Ethereum Virtual Machine.

  • state: The current world state.
  • block: The block to which the msg/transaction to be executed belongs to.
  • msg: The msg/transaction to be executed.
  • depth: The EVM operates as a stack machine. This variable is the maximum number of items the stack can hold.

2.12.2 Functions

func NewEnv(state *state.StateDB, msg Message, block *types.Block) *VMEnv
creates and returns a new VMEnv object.

The VMEnv implements the Environment interface. For that reason, the following functions are implemented:

func (self *VMEnv) Origin() []byte { return self.msg.From() }
Origin is defined as part of the implementation of the Environment interface for a VMEnv object,
which returns the origin of the msg to be executed.

func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number }
BlockNumber is defined as part of the implementation of the Environment interface for a VMEnv object,
which returns the block number of the block to which the msg to executed belongs to.

func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash }
PrevHash is defined as part of the implementation of the Environment interface for a VMEnv object,
which returns the hash of the parent of the block that contains the msg to be executed.

func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase }
Coinbase is defined as part of the implementation of the Environment interface for a VMEnv object,
which returns the miner's address of the block that contains the msg to be executed.

func (self *VMEnv) Time() int64 { return self.block.Time }
Time is defined as part of the implementation of the Environment interface for a VMEnv object,
which returns the time that the block that contains the msg to be executed will be/is created.

func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty }
Difficulty is defined as part of the implementation of the Environment interface for a VMEnv object,
which returns the difficulty of the block that contains the msg to be executed.

func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
BlockHash is defined as part of the implementation of the Environment interface for a VMEnv object,
which returns the hash of the block that contains the msg to be executed.

func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
Value is defined as part of the implementation of the Environment interface for a VMEnv object,
which returns the value in Wei of the msg to be executed.

func (self *VMEnv) State() *state.StateDB { return self.state }
State is defined as part of the implementation of the Environment interface for a VMEnv object,
which returns the current world state.

func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit }
GasLimit is defined as part of the implementation of the Environment interface for a VMEnv object,
which returns the gasLimit field of the block that contains the msg to be executed.

func (self *VMEnv) Depth() int { return self.depth }
Depth is defined as part of the implementation of the Environment interface for a VMEnv object,
which returns the maximum number of items of the EVM stack.

func (self *VMEnv) SetDepth(i int) { self.depth = i }
SetDepth is defined as part of the implementation of the Environment interface for a VMEnv object,
which sets the maximum number of items of the EVM stack.

func (self *VMEnv) AddLog(log state.Log) { self.state.AddLog(log) }
AddLog is defined as part of the implementation of the Environment interface for a VMEnv object,
which adds a log to the world state through the function AddLog of a StateDB object (defined in the file state/state.go).

func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error
Transfer makes use of the generic function Transfer defined in the file vm/environment.go to
make the transfer of amount Wei from the from to the to accounts. Returns nil on success or an error if there is not sufficient balance in the from account.

func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *Execution
vm is an inner function that creates and returns a new Execution object.

func (self *VMEnv) Call(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error)
Call is defined as part of the implementation of the Environment interface for a VMEnv object, which executes the contract associated at addr with the given data. This happens through a call on the inner function exec.

func (self *VMEnv) CallCode(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error)
CallCode is defined as part of the implementation of the Environment interface for a VMEnv object, which executes the contract associated at addr with the given data. This happens through a call on the inner function exec. The only diffference between Call and CallCode is that the latter executes the given address' code with the caller as context (aka CallCode is used when a function calls another function with the 1st function being the caller).

func (self *VMEnv) Create(me vm.ClosureRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ClosureRef)
Create is defined as part of the implementation of the Environment interface for a VMEnv object, which creates a contract through the function Create</a.


2.13 execution.go

2.13.1 Data Structures
type Execution struct {
	env               vm.Environment
	address, input    []byte
	Gas, price, value *big.Int
	SkipTransfer      bool
}

The EVM always creates an Execution object and then calls upon it's functions in order to execute any transaction. In other words, this is the core object through which any code on the blockchain is executed.

  • env: The Execution object needs to be "attached" to an EVM.
  • address: The address of the Execution. This should be a contract's address as it refers to an address which contains the code to be executed.
  • input: The code to be executed. This param should be of the form {hash, params}, where hash is the hash of the function's signature to be executed and params are 32-byte words which are passed as params to the function. This is where the stack comes into play.
  • Gas: The gas that has been supplied for the the msg/transaction.
  • price: The gas price.
  • value: Amount of Wei to be transferred throught the execution of the transaction.
  • SkipTransfer: Used only for testing.


2.13.2 Functions

func NewExecution(env vm.Environment, address, input []byte, gas, gasPrice, value *big.Int) *Execution
NewExecution is a contructor for an Execution object. This function gets mainly called from the EVM to create an Execution object through which (the EVM) will call either Call or Create in order to execute code or create a contract accordingly.

func (self *Execution) Addr() []byte
Addr returns the address of the Execution.

func (self *Execution) Call(codeAddr []byte, caller vm.ClosureRef) ([]byte, error)
Call is the function to be called when a msg/transaction is not about contract creation. It does nothing more than retrieving the code of the codeAddr (to be executed) and makes a call to the inner function exec which takes care of the execution. This function gets called from both CallCode and Call functions of the EVM.

func (self *Execution) exec(code, contextAddr []byte, caller vm.ClosureRef) (ret []byte, err error)
exec is the most important function of the whole core package and one of the most important ones of the whole go-ethereum codebase. First of all, it's an inner function, called by Call and/or Create. exec executes the code from the contract codeAddr. It handles any necessary value transfer required and takes the necessary steps to create accounts and reverses the state in case of an execution error or failed value transfer.

  • caller: In cases where eg. a function A calls function B, the caller param will point to the the contract's address that made the call to B.
  • contextAddr: The address of the contract that includes the code to be executed.

func (self *Execution) Create(caller vm.ClosureRef) (ret []byte, err error, account *state.StateObject)
Create creates a new contract and returns it's bytecode and the account created as a StateObject.


Documentation

Index

Constants

View Source
const (

	// Current protocol version
	ProtocolVersion = 49
	// Current P2P version
	P2PVersion = 2
	// Ethereum network version
	NetVersion = 0
)

Variables

This section is empty.

Functions

func PastPeers

func PastPeers() []string

Types

type BlockPool

type BlockPool struct {
	ChainLength, BlocksProcessed int
	// contains filtered or unexported fields
}

func NewBlockPool

func NewBlockPool(eth *Ethereum) *BlockPool

func (*BlockPool) Add

func (self *BlockPool) Add(b *types.Block, peer *Peer)

func (*BlockPool) AddHash

func (self *BlockPool) AddHash(hash []byte, peer *Peer)

func (*BlockPool) AddNew

func (self *BlockPool) AddNew(b *types.Block, peer *Peer)

func (*BlockPool) Blocks

func (self *BlockPool) Blocks() (blocks types.Blocks)

func (*BlockPool) DistributeHashes

func (self *BlockPool) DistributeHashes()

func (*BlockPool) FetchHashes

func (self *BlockPool) FetchHashes(peer *Peer) bool

func (*BlockPool) HasCommonHash

func (self *BlockPool) HasCommonHash(hash []byte) bool

func (*BlockPool) HasLatestHash

func (self *BlockPool) HasLatestHash() bool

func (*BlockPool) Len

func (self *BlockPool) Len() int

func (*BlockPool) Remove

func (self *BlockPool) Remove(hash []byte)

func (*BlockPool) Reset

func (self *BlockPool) Reset()

func (*BlockPool) Start

func (self *BlockPool) Start()

func (*BlockPool) Stop

func (self *BlockPool) Stop()

type Caps

type Caps byte

Peer capabilities

const (
	CapPeerDiscTy Caps = 1 << iota
	CapTxTy
	CapChainTy

	CapDefault = CapChainTy | CapTxTy | CapPeerDiscTy
)

func (Caps) IsCap

func (c Caps) IsCap(cap Caps) bool

func (Caps) String

func (c Caps) String() string

type ChainSyncEvent

type ChainSyncEvent struct {
	InSync bool
}

type DiscReason

type DiscReason byte
const (
	// Values are given explicitly instead of by iota because these values are
	// defined by the wire protocol spec; it is easier for humans to ensure
	// correctness when values are explicit.
	DiscRequested DiscReason = iota
	DiscReTcpSysErr
	DiscBadProto
	DiscBadPeer
	DiscTooManyPeers
	DiscConnDup
	DiscGenesisErr
	DiscProtoErr
	DiscQuitting
)

func (DiscReason) String

func (d DiscReason) String() string

type Ethereum

type Ethereum struct {

	// Nonce
	Nonce uint64

	Addr net.Addr
	Port string

	// Specifies the desired amount of maximum peers
	MaxPeers int

	Mining bool

	RpcServer *rpc.JsonRpcServer
	// contains filtered or unexported fields
}

func New

func New(db ethutil.Database, clientIdentity wire.ClientIdentity, keyManager *crypto.KeyManager, caps Caps, usePnp bool) (*Ethereum, error)

func (*Ethereum) AddPeer

func (s *Ethereum) AddPeer(conn net.Conn)

func (*Ethereum) BlacklistPeer

func (self *Ethereum) BlacklistPeer(peer *Peer)

func (*Ethereum) BlockManager

func (s *Ethereum) BlockManager() *core.BlockManager

func (*Ethereum) BlockPool

func (s *Ethereum) BlockPool() *BlockPool

func (*Ethereum) Broadcast

func (s *Ethereum) Broadcast(msgType wire.MsgType, data []interface{})

func (*Ethereum) BroadcastMsg

func (s *Ethereum) BroadcastMsg(msg *wire.Msg)

func (*Ethereum) ChainManager

func (s *Ethereum) ChainManager() *core.ChainManager

func (*Ethereum) ClientIdentity

func (s *Ethereum) ClientIdentity() wire.ClientIdentity

func (*Ethereum) ConnectToPeer

func (s *Ethereum) ConnectToPeer(addr string) error

func (*Ethereum) Db

func (self *Ethereum) Db() ethutil.Database

func (*Ethereum) EventMux

func (s *Ethereum) EventMux() *event.TypeMux

func (*Ethereum) GetFilter

func (self *Ethereum) GetFilter(id int) *core.Filter

GetFilter retrieves a filter installed using InstallFilter. The filter may not be modified.

func (*Ethereum) HighestTDPeer

func (s *Ethereum) HighestTDPeer() (td *big.Int)

func (*Ethereum) InOutPeers

func (s *Ethereum) InOutPeers() []*Peer

func (*Ethereum) InboundPeers

func (s *Ethereum) InboundPeers() []*Peer

func (*Ethereum) InstallFilter

func (self *Ethereum) InstallFilter(filter *core.Filter) (id int)

InstallFilter adds filter for blockchain events. The filter's callbacks will run for matching blocks and messages. The filter should not be modified after it has been installed.

func (*Ethereum) IsListening

func (s *Ethereum) IsListening() bool

func (*Ethereum) IsMining

func (s *Ethereum) IsMining() bool

func (*Ethereum) IsUpToDate

func (s *Ethereum) IsUpToDate() bool

func (*Ethereum) KeyManager

func (s *Ethereum) KeyManager() *crypto.KeyManager

func (*Ethereum) OutboundPeers

func (s *Ethereum) OutboundPeers() []*Peer

func (*Ethereum) PeerCount

func (s *Ethereum) PeerCount() int

func (*Ethereum) Peers

func (s *Ethereum) Peers() *list.List

func (*Ethereum) ProcessPeerList

func (s *Ethereum) ProcessPeerList(addrs []string)

func (*Ethereum) PushPeer

func (s *Ethereum) PushPeer(peer *Peer)

func (*Ethereum) RemovePeer

func (s *Ethereum) RemovePeer(p *Peer)

func (*Ethereum) Seed

func (s *Ethereum) Seed()

func (*Ethereum) ServerCaps

func (s *Ethereum) ServerCaps() Caps

func (*Ethereum) Start

func (s *Ethereum) Start(seed bool)

Start the ethereum

func (*Ethereum) Stop

func (s *Ethereum) Stop()

func (*Ethereum) TxPool

func (s *Ethereum) TxPool() *core.TxPool

func (*Ethereum) UninstallFilter

func (self *Ethereum) UninstallFilter(id int)

func (*Ethereum) WaitForShutdown

func (s *Ethereum) WaitForShutdown()

This function will wait for a shutdown and resumes main thread execution

type NAT

type NAT interface {
	GetExternalAddress() (addr net.IP, err error)
	AddPortMapping(protocol string, externalPort, internalPort int, description string, timeout int) (mappedExternalPort int, err error)
	DeletePortMapping(protocol string, externalPort, internalPort int) (err error)
}

protocol is either "udp" or "tcp"

func Discover

func Discover() (nat NAT, err error)

func NewNatPMP

func NewNatPMP(gateway net.IP) (nat NAT)

type Peer

type Peer struct {
	// contains filtered or unexported fields
}

func NewOutboundPeer

func NewOutboundPeer(addr string, ethereum *Ethereum, caps Caps) *Peer

func NewPeer

func NewPeer(conn net.Conn, ethereum *Ethereum, inbound bool) *Peer

func (*Peer) Caps

func (self *Peer) Caps() *ethutil.Value

func (*Peer) Connect

func (self *Peer) Connect(addr string) (conn net.Conn, err error)

func (*Peer) Connected

func (p *Peer) Connected() *int32

func (*Peer) FetchBlocks

func (self *Peer) FetchBlocks(hashes [][]byte)

func (*Peer) FetchHashes

func (self *Peer) FetchHashes() bool

func (*Peer) FetchingHashes

func (self *Peer) FetchingHashes() bool

func (*Peer) HandleInbound

func (p *Peer) HandleInbound()

Inbound handler. Inbound messages are received here and passed to the appropriate methods

func (*Peer) HandleOutbound

func (p *Peer) HandleOutbound()

Outbound message handler. Outbound messages are handled here

func (*Peer) Host

func (p *Peer) Host() []byte

func (*Peer) Inbound

func (p *Peer) Inbound() bool

func (*Peer) IsCap

func (self *Peer) IsCap(cap string) bool

func (*Peer) LastPong

func (p *Peer) LastPong() int64

func (*Peer) LastSend

func (p *Peer) LastSend() time.Time

func (*Peer) PingTime

func (p *Peer) PingTime() string

Getters

func (*Peer) Port

func (p *Peer) Port() uint16

func (*Peer) QueueMessage

func (p *Peer) QueueMessage(msg *wire.Msg)

Outputs any RLP encoded data to the peer

func (*Peer) RlpData

func (p *Peer) RlpData() []interface{}

func (*Peer) SetVersion

func (p *Peer) SetVersion(version string)

Setters

func (*Peer) Start

func (p *Peer) Start()

func (*Peer) Stop

func (p *Peer) Stop()

func (*Peer) StopWithReason

func (p *Peer) StopWithReason(reason DiscReason)

func (*Peer) String

func (p *Peer) String() string

func (*Peer) Version

func (p *Peer) Version() string

type PeerListEvent

type PeerListEvent struct {
	Peers *list.List
}

Directories

Path Synopsis
cmd
evm
compression
rle
Package event implements an event multiplexer.
Package event implements an event multiplexer.
Package logger implements a multi-output leveled logger.
Package logger implements a multi-output leveled logger.
pow
ar
ezp
Package rlp implements the RLP serialization format.
Package rlp implements the RLP serialization format.
tests
ui
qt
Package wire provides low level access to the Ethereum network and allows you to broadcast data over the network.
Package wire provides low level access to the Ethereum network and allows you to broadcast data over the network.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL