Skip to content
This repository was archived by the owner on May 23, 2023. It is now read-only.

Commit 2e53bf3

Browse files
committed
Did a bit of refactoring and added documentation
1 parent 7adb2e1 commit 2e53bf3

21 files changed

+555
-1643
lines changed

README.rst

Lines changed: 180 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,6 @@ This is the Python core library of the Ethereum project.
1414
For the python based command line client see:
1515
https://github.com/ethereum/pyethapp
1616

17-
18-
+-----------+------------------+------------------+--------------------+--------------------+
19-
| | Linux | OSX | Travis | Coverage |
20-
+-----------+------------------+------------------+--------------------+--------------------+
21-
| develop | |Linux develop| | |OSX develop| | |Travis develop| | |Coverage develop| |
22-
+-----------+------------------+------------------+--------------------+--------------------+
23-
| master | |Linux master| | |OSX master| | |Travis master| | |Coverage master| |
24-
+-----------+------------------+------------------+--------------------+--------------------+
25-
26-
Quickstart
27-
-------------
28-
2917
Installation:
3018
++++++++++++++
3119

@@ -38,11 +26,189 @@ Installation:
3826

3927

4028

41-
For developers
29+
Components
4230
---------------
4331

44-
See our `developer notes <https://github.com/ethereum/pyethereum/wiki/Developer-Notes>`_
32+
### ethereum.pow.chain
33+
34+
Contains the Chain class, which can be used to manage a blockchain. Main methods are:
35+
36+
* `__init__(genesis=None, env=None, new_head_cb=None, reset_genesis=False, localtime=None)` - initializes with the given genesis. `env` specifies the _environment_ (including chain config and database), `new_head_cb` is a callback called when a new head is added, and `localtime` is what the chain assumes is the current timestamp. The genesis can be:
37+
* None - in which case it assumes `env` is given, and creates a Chain object with the data saved in `env.db`. If `reset_genesis` is set, it re-initializes the chain.
38+
* A `State` object
39+
* A genesis declaration
40+
* A state snapshot (`State.snapshot()`)
41+
* An allocation (ie. dict `{address: {balance: 1, nonce: 2, code: b'\x03\x04\x05', storage: {"0x06": "0x07"}}}`)
42+
* `add_block(block)` - adds a block to the chain
43+
* `process_time_queue(timestamp)` - tells the chain that the current time has increased to the new timestamp. The chain will then process any blocks that were unprocessed because they appeared too "early"
44+
* `get_blockhash_by_number(num)` - get the block hash of a block at the given block number
45+
* `get_block(hash)` - gets the block with the given blockhash
46+
* `get_block_by_number(num)` - equivalent to `get_block(get_blockhash_by_number(num))`
47+
* `get_parent(block)` - gets the parent of a block
48+
* `get_children(block)` - gets the children of a block
49+
* `head` (property) - gets the block at the head of the chain
50+
* `state` (property) - gets the state at the head of the chain
51+
* `mk_poststate_of_blockhash(hash)` - creates a state object after a given block
52+
* `has_block(block)` - is that block in the chain? Returns True/False
53+
* `get_chain(from, to)` - roughly equivalent to `[get_block_by_number(i) for i in range(from, to)]`, though automatically stops if it reaches the head. `from` can be elided to start from genesis, `to` can be elided to go up to the head.
54+
* `get_tx_position(tx)` - if the transaction is in the chain, returns `(blknum, index)` where `blknum` is the block number of the block that contains the transaction and `index` is its position in the block
55+
56+
### ethereum.state
57+
58+
Contains the State class, which is used to manage a state. Main methods are:
59+
60+
* `__init__(root_hash, env, **kwargs)` - initializes a state with the given root hash, the given env (which includes a config and database) and the given auxiliary arguments. These include:
61+
* `txindex` - the transaction index
62+
* `gas_used` - amount of gas used
63+
* `gas_limit` - block gas limit
64+
* `block_number` - block number
65+
* `block_coinbase` - block coinbase address
66+
* `block_difficulty` - block difficulty
67+
* `timestamp` - timestamp
68+
* `logs` - logs created so far
69+
* `receipts` - receipts created so far (from previous transactions in the current block)
70+
* `bloom` - the bloom filter
71+
* `suicides` - suicides (or selfdestructs, the newer more politically correct synonym)
72+
* `recent_uncles` - recent uncle blocks in the chain
73+
* `prev_headers` - previous block headers
74+
* `refunds` - suicide/selfdestruct refund counter
75+
76+
Pyethereum follows a **maximally state-centric model**; the ONLY information needed to process a transaction or a block is located within the state itself, allowing the actual state transition logic to be a very clean `apply_transaction(state, tx)` and `apply_block(state, block)`.
77+
78+
* `get_balance`- gets the balance of an account
79+
* `get_code` - gets the code of an account
80+
* `get_storage_data(addr, k)` - gets the storage at the given key of the given address. Expects a key in **numerical** form (eg. b"cow" or "0x636f77" is represented as 6516599).
81+
* `to_snapshot(root_only=False, no_prevblocks=False)` - creates a snapshot for the current state. If `root_only` is set, only adds the state root, not the entire state. If `no_prevblocks` is set, does not add previous headers and uncles. Setting either of those flags means that the same database would be required to recover from the snapshot.
82+
* `from_snapshot(snapshot, env)` (classmethod) - creates a state from the given snapshot with the given `env`.
83+
* `ephemeral_clone()` - creates a clone of the state that you can work with without affecting the original
84+
85+
There are also many methods that modify the state, eg. `set_code`, `set_storage_data`, but it is generally recommended to avoid using these, and instead modify the state ONLY through `apply_transaction` and `apply_block`.
86+
87+
### ethereum.meta
88+
89+
This file contains two functions:
90+
91+
* `apply_block(state, block)` - takes a state and processes a block onto that state
92+
* `make_head_candidate(chain, txqueue=None, parent=None, timestamp, coinbase, extra_data, min_gasprice=0)` - creates a candidate block for the chain on top of the given parent block (default: head of the chain). Gets transactions from the given `txqueue` object with the given `mingasprice` (otherwise does not add transactions). `timestamp`, `coinbase` and `extra_data` can be used to specify those parameters in the block; otherwise defaults are used
93+
94+
### ethereum.messages
95+
96+
The main function that should be called from here is `apply_transaction(state, tx)`.
97+
98+
### ethereum.utils
99+
100+
Contains a bunch of utility functions, including:
101+
102+
#### Numerical and hex conversions
103+
104+
* `encode_int(i)` - converts an integer into big-endian binary representation
105+
* `zpad(data, length)` - pads the data up to the desired length by adding zero bytes on the left
106+
* `encode_int32(i)` - equivalent to `zpad(encode_int(i), 32)` but faster
107+
* `big_endian_to_int(d)` - converts binary data into an integer
108+
* `encode_hex(b)` - converts bytes to hex
109+
* `decode_hex(h)` - converts hex to bytes
110+
* `int_to_addr(i)` - converts integer to address
111+
* `is_numeric(i)` - returns True if the value is int or long, otherwise False
112+
113+
#### Cryptography
114+
115+
* `sha3(data)` - computes the SHA3 (or more precisely, keccak256) hash
116+
* `ecrecover_to_pub(hash, v, r, s)` - recovers the public key that made the signature as a 64-byte binary blob of `encode_int32(x) + encode_int32(y)`. Hashing this and taking the last 20 bytes gives the _address_ that signed a message.
117+
* `ecsign(hash, key)` - returns the v, r, s values of a signature
118+
* `normalize_key(key)` - converts a key from many formats into 32-byte binary
119+
* `privtoaddr(key)` - converts a key to an address
120+
121+
#### Addresses
122+
123+
* `normalize_address(addr)` - converts an address into 20-byte binary form
124+
* `check_checksum(addr)` - returns True if the address checksum passes, otherwise False
125+
* `checksum_encode(addr)` - converts an address into hex form with a checksum
126+
* `mk_contract_address(addr, nonce)` - creates the address of a contract created by the given address with the given nonce
127+
128+
#### Miscellaneous
129+
130+
* `denoms` - contains the denominations of ether, eg. `denoms.finney = 10**15`, `denoms.shannon = 10**9`, `denoms.gwei = 10**9`
131+
132+
### ethereum.block
133+
134+
Contains the `Block` and `BlockHeader` classes. Generally recommended to avoid creating blocks and block headers directly, instead using `mk_head_candidate`. The member variables are straightforward:
135+
136+
* `block.transactions` - transactions in a block
137+
* `block.uncles` - uncles in a block
138+
* `block.header` - header of a block
139+
140+
And in the header:
141+
142+
* `header.hash` - the hash (also the block hash)
143+
* `header.mining_hash` - the hash used for proof of work mining
144+
* `header.to_dict()` - serializes into a human-readable dict
145+
* `header.prevhash` - previous block hash
146+
* `header.uncles_hash` - hash of the uncle list
147+
* `header.coinbase` - coinbase (miner) address
148+
* `header.state_root` - root hash of the post-state
149+
* `header.tx_list_root` - hash of the transactions in the block
150+
* `header.receipts_root` - hash of the receipt trie
151+
* `header.bloom` - bloom filter
152+
* `header.difficulty` - block difficulty
153+
* `header.number` - block number
154+
* `header.gas_limit` - gas limit
155+
* `header.gas_used` - gas used
156+
* `header.timestamp` - timestamp
157+
* `header.extra_data` - block extra data
158+
* `header.mixhash` and `header.nonce` - Ethash proof of work values
159+
160+
### ethereum.transactions
161+
162+
Contains the Transaction class, with the following methods and values:
163+
164+
* `__init__(nonce, gasprice, startgas, to, value, data, (v, r, s optional))` - constructor
165+
* `sign(key, network_id=None)` - signs the transaction with the given key, and with the given EIP155 chain ID (leaving as None will create a pre-EIP155 tx, be warned of replay attacks if you do this!)
166+
* `sender` - the sender address of the transaction
167+
* `network_id` - the EIP155 chain ID of the transaction
168+
* `hash` - the hash of the transaction
169+
* `to_dict()` - serializes into a human-readable dict
170+
* `intrinsic_gas_used` - the amount of gas consumed by the transaction, including the cost of the tx data
171+
* `creates` - if the transaction creates a contract, returns the contract address
172+
* `nonce`, `gasprice`, `startgas`, `to`, `value`, `data`, `v`, `r`, `s` - parameters in the transaction
173+
174+
### ethereum.tools.keys
175+
176+
Creates encrypted private key storaes
177+
178+
* `decode_keystore_json(jsondata, password)` - returns the private key from an encrypted keystore object. NOTE: if you are loading from a file, the most convenient way to do this is `import json; key = decode_keystore_json(json.load(open('filename.json')), 'password')`
179+
* `make_keystore_json(key, pw, kdf='pbkdf2', cipher='aes-128-ctr')` - creates an encrypted keystore object for the key. Keeping `kdf` and `cipher` at their default values is recommended.
180+
181+
### RLP encoding and decoding
182+
183+
For any transaction or block, you can simply do:
184+
185+
import rlp
186+
bindata = rlp.encode(<tx or block>)
187+
188+
To decode:
189+
190+
import rlp
191+
from ethereum.transactions import Transaction
192+
rlp.decode(blob, Transaction)
193+
194+
Or:
195+
196+
import rlp
197+
from ethereum.blocks import Block
198+
rlp.decode(blob, Block)
199+
200+
### Consensus abstraction
201+
202+
The pyethereum codebase is designed to be maximally friendly for use across many different consensus algorithms. If you want to add a new consensus algo, you'll need to take the following steps:
45203

204+
* Add a directory alongside `pow`, and in it create a `chain.py` class that implements a `Chain` module. This may have a totally different fork choice rule for proof of work (GHOST, signature counting, Casper, etc).
205+
* Add an entry to `consensus_strategy.py`. You will need to implement:
206+
* `check_seal` - check that a block is correctly "sealed" (mined, signed, etc)
207+
* `validate_uncles(state, block)` - check that uncles are valid
208+
* `initialize(state, block)` - called in `apply_block` before transactions are processed
209+
* `finalize(state, block)` - called in `apply_block` after transactions are processed
210+
* `get_uncle_candidates(chain, state)` - called in `mk_head_candidate` to include uncles in a block
211+
* Create a chain config with the CONSENSUS_STRATEGY set to whatever you named your new consensus strategy
46212

47213
Licence
48214
========

ethereum/abi.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,10 @@ def encode_single(typ, arg): # pylint: disable=too-many-return-statements,too-m
343343

344344
if base == 'bytes':
345345
if not is_string(arg):
346-
raise EncodingError('Expecting string: %r' % arg)
346+
if isinstance(arg, str):
347+
arg = bytes(arg, 'utf8')
348+
else:
349+
raise EncodingError('Expecting string: %r' % arg)
347350

348351
arg = utils.to_string(arg) # py2: force unicode into str
349352

ethereum/genesis_helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from ethereum.new_state import State
1+
from ethereum.state import State
22
from ethereum.block import Block, BlockHeader, BLANK_UNCLES_HASH
33
from ethereum.utils import decode_hex, big_endian_to_int, encode_hex, \
44
parse_as_bin, parse_as_int, normalize_address

ethereum/messages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from ethereum import opcodes
1717
from ethereum.transactions import Transaction
1818
from ethereum.consensus_strategy import get_consensus_strategy
19-
from ethereum import new_vm as vm
19+
from ethereum import vm
2020
from ethereum.specials import specials as default_specials
2121
from ethereum.config import Env, default_config
2222
from ethereum.db import BaseDB, EphemDB

0 commit comments

Comments
 (0)