-
Notifications
You must be signed in to change notification settings - Fork 603
Code Walkthrough
Following a block from the network socket to the hard drive
Note: All links to the code are based on a fixed revision, so we can link line numbers. Code might have changed by now, nonetheless use these revisions when doing updates to this document.
- the app was configured and started
- all services registered
- the discovery protocol discovered some nodes
- the peermanager successfully connected a node
- established an encrypted multiplexed session
- and created a ETHProtocol instance for this peer
- we are waiting for ingress data in the peer connection
Wait for data on the socket: devp2p/peer.py#L208
add the (partial) message to the MultiplexedSession: devp2p/peer.py#L223
try to decode packets (objects representing the equivalent to a rpc cmd): devp2p/muxsession.py#L66
decode if there is enough data in the buffer devp2p/multiplexer.py#L520 devp2p/multiplexer.py#L426
decrypt devp2p/multiplexer.py#L442
using the cipher devp2p/muxsession.py#L17
which we have in the RLPx session devp2p/rlpxcipher.py#L41
decoded packets are put in a queue which are processed by a greenlet devp2p/peer.py#L197
which was spawned by devp2p/peer.py#L203
the Peer instance which is another greenlet devp2p/peer.py#L22
the protocol for handling the packet is resolved devp2p/peer.py#L164
and given the packet devp2p/peer.py#L174 devp2p/protocol.py#L160
in our case we assume the packet is for the "eth" protocol pyethapp/eth_protocol.py#L15
The ETHProtocol instance was linked to the ChainService instance on creation, which registered callbacks pyethapp/eth_service.py#L334
which are called devp2p/protocol.py#L68
after the Packet.cmd_id is resolved to a handling command class devp2p/protocol.py#L160 devp2p/protocol.py#L44
in our case eth_protocol.NewBlock: pyethapp/eth_protocol.py#L143
which decodes the payload: pyethapp/eth_protocol.py#L157
the registered callback function is called and handles the message: pyethapp/eth_service.py#L461
new blocks are handled by the synchronizer which knows the state of the synchronization: pyethapp/synchronizer.py#L283
if the block is unknown pyethapp/synchronizer.py#L294
and pow is valid pyethapp/synchronizer.py#L299
and chain difficulty sufficient pyethapp/synchronizer.py#L304
and we have a parent for the block pyethapp/synchronizer.py#L304
the block is added to a queue pyethapp/synchronizer.py#L304 pyethapp/eth_service.py#L202
which is processed by a greenlet pyethapp/eth_service.py#L207
which pop blocks from the queue and tries to add them to the chain: pyethapp/eth_service.py#L228
so far we had a transient block (t_block) which was not yet connected to the database, i.e. it could not access its ancestors or access state.
it is now deserialized to a block.Block pyethapp/eth_service.py#L252 pyethapp/eth_protocol.py#L220
blocks.Block and blocks.BlockHeader are subclasses of rlp.Serializable ethereum/blocks.py#L378 sedes/lists.py#L89
on blocks.Block init ethereum/blocks.py#L404
the block is checked for consistency ethereum/blocks.py#L436
the transactions are executed to update the state ethereum/blocks.py#L481 ethereum/processblock.py#L119
transactions are validated ethereum/processblock.py#L86
sender account nonce increased ethereum/processblock.py#L124
gas is checked and handled ethereum/processblock.py#L127
a message to the account and call data are prepared ethereum/processblock.py#L132
the message is applied ethereum/processblock.py#L137 ethereum/processblock.py#L221
value is transfered ethereum/processblock.py#L237
the vm invoked ethereum/processblock.py#L245 ethereum/vm.py#L151
read / writes to the state and limited access to the external environment is provided by the VmExt class ethereum/vm.py#L151 ethereum/processblock.py#L185
writes (state updates) are cached and journaled, so they can be reverted if the tx is invalid ethereum/processblock.py#L195 ethereum/blocks.py#L975 ethereum/blocks.py#L754
if the message could successfully be applied, the transaction is valid ethereum/processblock.py#L157
the state is committed ethereum/processblock.py#L174 ethereum/blocks.py#L1002
the transaction added to the list of txs of the block: ethereum/processblock.py#L180
after all transactions are applied, the block is finalized: ethereum/blocks.py#L483 ethereum/blocks.py#L1158
the block with its resulting state is verified ethereum/blocks.py#L497 pyethapp/eth_service.py#L266
If everything worked, we are back in ChainService and add the block to the chain pyethapp/eth_service.py#L279 pyethapp/eth_service.py#L281 ethereum/chain.py#L274
here we validate the uncles: ethereum/chain.py#L282 ethereum/blocks.py#L642
do another verification: ethereum/chain.py#L296
update the index: ethereum/chain.py#L307 ethereum/chain.py#L35 ethereum/chain.py#L86 ethereum/chain.py#L67
store the block: ethereum/chain.py#L308 ethereum/chain.py#L265 ethereum/refcount_db.py#L154 ethereum/refcount_db.py#L23 ethereum/refcount_db.py#L32 pyethapp/leveldb_service.py#L74
update the head of the chain: ethereum/chain.py#L310 ethereum/chain.py#L313 ethereum/chain.py#L153
update the head candidate (i.e. the block we are mining on and are adding new txs to): ethereum/chain.py#L193 ethereum/chain.py#L197 ethereum/chain.py#L222
finally commit: ethereum/chain.py#L320 ethereum/refcount_db.py#L101 pyethapp/leveldb_service.py#L78
Et, voilà! The block made it to the harddrive :)
Next up: Code Walkthrough - from the JSONRPC socket through the blockchain to the network.