-
Notifications
You must be signed in to change notification settings - Fork 3
Parity ethereum code walkthrough 1
parity-ethereum/parity/main.rs
Function main
either starts another executable (it is called 'hypervised mode' and is called via run_parity
function), or directly executes parity in the current process via main_direct
function.
Function main_direct
gathers configuration from command line arguments (conf
), sets up logging (logger
) and eventually invokes start
function.
parity-ethereum/parity/lib.rs
Function start
is a wrapper around execute
function with an extra functionality that it prints out deprecated command line arguments.
Function execute
can optionally start deadlock detection thread, and then executes one of the specified commands:
- Run
- Version
- Hash
- Account
- Import Presale Wallet
- Blockchain
- Signer Token
- Signer Sign
- Signer List
- Signer Reject
- Snapshot
- Export Hardcoded Sync
Presumably, we are interested in the Run
command.
parity-ethereum/parity/run.rs
Function execute
executes either light client or full client depending on the option cmd.light
(where cmd is the instance of RunCmd
). We are currently interested in the full client, so the function invoked in this case is execute_impl
.
Function execute_impl
first assembles all configuration parameters and then create client service by invoking ClientService::start
.
parity-ethereum/ethcore/service/src/service.rs
Function start
in ClientService
implementation creates a new client via Client::new
, passing the handle to blockchain_db
parity-ethereum/ethcore/src/client/client.rs
Function new
of type Client
creates a trie factory. It also create VM factory, presumable for creating instances of EVM to execute transactions. And accountdb
is also wrapped into Factories
together with the trie factory and VM factory.
The database (db
) passed into this constructor new
, is treated as a key-value store. First, it is wrapped into a journal_db
, which has settings related to pruning and selects the column ::db::COL_STATE
(presumably the column used to store the Ethereum state). Journal db takes care of the history of the state.
Next, the journal_db
is further wrapped into StateDB
, using StateDB::new
, which has a setting related to the state cache size.
The same database handle, db
, is cloned two times and is used to create a blockchain db instance via BlockChain::new
, and trace db instance, via TraceDB::new
.
As a part of creating the Client
, another object is created, of the type Importer
(defined in the same file). This type is the entry point for block importing operations. Interestingly, the block importer does not hold any direct or indirect references to the database, therefore all the functions that require access to the database, always have the client
passed as a parameter. Importer then uses one of the state_db
, chain
, or trace_db
properties of the client
to get access to the corresponding database wrapper.
parity-ethereum/ethcore/state-db/src/lib.rs
Here we have the definition of StateDB
parity-ethereum/ethcore/evm
EVM implementation
parity-ethereum/ethcore/trie-vm-factories/src/lib.rs
This file defines Factories
, which is tuple of 3 factories:
- Trie factory
- VM factory
- Account factory
trie/trie-db/src/lib.rs
This is where TrieFactory
is defined. Note that this is a separate repo, and not part of Parity-Ethereum. A factory can create 3 types of tries: Generic, Secure, and Fat.
Parameter Layout
defines the parameterisation of more generic trie implementation to specifics of Ethereum. It is in the file parity-ethereum/util/patricia-trie-ethereum/src/lib.rs
Depending on the configuration options, either Secure
or Fat
variant is instantiated. Both secure and fat dbs are wrappers around TrieDb
, which is the database representation of particia trie with a cache. Secure db applies hash function to all the keys before inserting or removing. Fat db additionally maintains the set of preimages.
trie/trie-db/src/triedbmut.rs
This is where most of the trie modification and lookup logic resides. Interestingly, nodes of the trie reference each other not via pointers (like in go-ethereum, for example), but via "handles", which are indices in one big vector of nodes, encapsulate into NodeStorage
. Node storage also maintains a "free list", which essentially turns it into a heap allocator.
Looks like there is no limitation on how many trie nodes are kept in memory, which leads me to believe that tries are created only for the processing of one block. That explains the "factory" approach.