|
| 1 | +This is the Python core library of the Ethereum project. |
| 2 | + |
| 3 | +For the python based command line client see: |
| 4 | +https://github.com/ethereum/pyethapp |
| 5 | + |
| 6 | +## Installation: |
| 7 | + |
| 8 | +``git clone https://github.com/ethereum/pyethereum/`` |
| 9 | + |
| 10 | +``cd pyethereum`` |
| 11 | + |
| 12 | +``python setup.py install`` |
| 13 | + |
| 14 | + |
| 15 | +## Components |
| 16 | + |
| 17 | +### ethereum.pow.chain |
| 18 | + |
| 19 | +Contains the Chain class, which can be used to manage a blockchain. Main methods are: |
| 20 | + |
| 21 | +* `__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: |
| 22 | + * 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. |
| 23 | + * A `State` object |
| 24 | + * A genesis declaration |
| 25 | + * A state snapshot (`State.snapshot()`) |
| 26 | + * An allocation (ie. dict `{address: {balance: 1, nonce: 2, code: b'\x03\x04\x05', storage: {"0x06": "0x07"}}}`) |
| 27 | +* `add_block(block)` - adds a block to the chain |
| 28 | +* `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" |
| 29 | +* `get_blockhash_by_number(num)` - get the block hash of a block at the given block number |
| 30 | +* `get_block(hash)` - gets the block with the given blockhash |
| 31 | +* `get_block_by_number(num)` - equivalent to `get_block(get_blockhash_by_number(num))` |
| 32 | +* `get_parent(block)` - gets the parent of a block |
| 33 | +* `get_children(block)` - gets the children of a block |
| 34 | +* `head` (property) - gets the block at the head of the chain |
| 35 | +* `state` (property) - gets the state at the head of the chain |
| 36 | +* `mk_poststate_of_blockhash(hash)` - creates a state object after a given block |
| 37 | +* `has_block(block)` - is that block in the chain? Returns True/False |
| 38 | +* `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. |
| 39 | +* `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 |
| 40 | + |
| 41 | +### ethereum.state |
| 42 | + |
| 43 | +Contains the State class, which is used to manage a state. Main methods are: |
| 44 | + |
| 45 | +* `__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: |
| 46 | + * `txindex` - the transaction index |
| 47 | + * `gas_used` - amount of gas used |
| 48 | + * `gas_limit` - block gas limit |
| 49 | + * `block_number` - block number |
| 50 | + * `block_coinbase` - block coinbase address |
| 51 | + * `block_difficulty` - block difficulty |
| 52 | + * `timestamp` - timestamp |
| 53 | + * `logs` - logs created so far |
| 54 | + * `receipts` - receipts created so far (from previous transactions in the current block) |
| 55 | + * `bloom` - the bloom filter |
| 56 | + * `suicides` - suicides (or selfdestructs, the newer more politically correct synonym) |
| 57 | + * `recent_uncles` - recent uncle blocks in the chain |
| 58 | + * `prev_headers` - previous block headers |
| 59 | + * `refunds` - suicide/selfdestruct refund counter |
| 60 | + |
| 61 | +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)`. |
| 62 | + |
| 63 | +* `get_balance`- gets the balance of an account |
| 64 | +* `get_code` - gets the code of an account |
| 65 | +* `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). |
| 66 | +* `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. |
| 67 | +* `from_snapshot(snapshot, env)` (classmethod) - creates a state from the given snapshot with the given `env`. |
| 68 | +* `ephemeral_clone()` - creates a clone of the state that you can work with without affecting the original |
| 69 | + |
| 70 | +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`. |
| 71 | + |
| 72 | +### ethereum.meta |
| 73 | + |
| 74 | +This file contains two functions: |
| 75 | + |
| 76 | +* `apply_block(state, block)` - takes a state and processes a block onto that state |
| 77 | +* `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 |
| 78 | + |
| 79 | +### ethereum.messages |
| 80 | + |
| 81 | +The main function that should be called from here is `apply_transaction(state, tx)`. |
| 82 | + |
| 83 | +### ethereum.utils |
| 84 | + |
| 85 | +Contains a bunch of utility functions, including: |
| 86 | + |
| 87 | +#### Numerical and hex conversions |
| 88 | + |
| 89 | +* `encode_int(i)` - converts an integer into big-endian binary representation |
| 90 | +* `zpad(data, length)` - pads the data up to the desired length by adding zero bytes on the left |
| 91 | +* `encode_int32(i)` - equivalent to `zpad(encode_int(i), 32)` but faster |
| 92 | +* `big_endian_to_int(d)` - converts binary data into an integer |
| 93 | +* `encode_hex(b)` - converts bytes to hex |
| 94 | +* `decode_hex(h)` - converts hex to bytes |
| 95 | +* `int_to_addr(i)` - converts integer to address |
| 96 | +* `is_numeric(i)` - returns True if the value is int or long, otherwise False |
| 97 | + |
| 98 | +#### Cryptography |
| 99 | + |
| 100 | +* `sha3(data)` - computes the SHA3 (or more precisely, keccak256) hash |
| 101 | +* `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. |
| 102 | +* `ecsign(hash, key)` - returns the v, r, s values of a signature |
| 103 | +* `normalize_key(key)` - converts a key from many formats into 32-byte binary |
| 104 | +* `privtoaddr(key)` - converts a key to an address |
| 105 | + |
| 106 | +#### Addresses |
| 107 | + |
| 108 | +* `normalize_address(addr)` - converts an address into 20-byte binary form |
| 109 | +* `check_checksum(addr)` - returns True if the address checksum passes, otherwise False |
| 110 | +* `checksum_encode(addr)` - converts an address into hex form with a checksum |
| 111 | +* `mk_contract_address(addr, nonce)` - creates the address of a contract created by the given address with the given nonce |
| 112 | + |
| 113 | +#### Miscellaneous |
| 114 | + |
| 115 | +* `denoms` - contains the denominations of ether, eg. `denoms.finney = 10**15`, `denoms.shannon = 10**9`, `denoms.gwei = 10**9` |
| 116 | + |
| 117 | +### ethereum.block |
| 118 | + |
| 119 | +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: |
| 120 | + |
| 121 | +* `block.transactions` - transactions in a block |
| 122 | +* `block.uncles` - uncles in a block |
| 123 | +* `block.header` - header of a block |
| 124 | + |
| 125 | +And in the header: |
| 126 | + |
| 127 | +* `header.hash` - the hash (also the block hash) |
| 128 | +* `header.mining_hash` - the hash used for proof of work mining |
| 129 | +* `header.to_dict()` - serializes into a human-readable dict |
| 130 | +* `header.prevhash` - previous block hash |
| 131 | +* `header.uncles_hash` - hash of the uncle list |
| 132 | +* `header.coinbase` - coinbase (miner) address |
| 133 | +* `header.state_root` - root hash of the post-state |
| 134 | +* `header.tx_list_root` - hash of the transactions in the block |
| 135 | +* `header.receipts_root` - hash of the receipt trie |
| 136 | +* `header.bloom` - bloom filter |
| 137 | +* `header.difficulty` - block difficulty |
| 138 | +* `header.number` - block number |
| 139 | +* `header.gas_limit` - gas limit |
| 140 | +* `header.gas_used` - gas used |
| 141 | +* `header.timestamp` - timestamp |
| 142 | +* `header.extra_data` - block extra data |
| 143 | +* `header.mixhash` and `header.nonce` - Ethash proof of work values |
| 144 | + |
| 145 | +### ethereum.transactions |
| 146 | + |
| 147 | +Contains the Transaction class, with the following methods and values: |
| 148 | + |
| 149 | +* `__init__(nonce, gasprice, startgas, to, value, data, (v, r, s optional))` - constructor |
| 150 | +* `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!) |
| 151 | +* `sender` - the sender address of the transaction |
| 152 | +* `network_id` - the EIP155 chain ID of the transaction |
| 153 | +* `hash` - the hash of the transaction |
| 154 | +* `to_dict()` - serializes into a human-readable dict |
| 155 | +* `intrinsic_gas_used` - the amount of gas consumed by the transaction, including the cost of the tx data |
| 156 | +* `creates` - if the transaction creates a contract, returns the contract address |
| 157 | +* `nonce`, `gasprice`, `startgas`, `to`, `value`, `data`, `v`, `r`, `s` - parameters in the transaction |
| 158 | + |
| 159 | +### ethereum.tools.keys |
| 160 | + |
| 161 | +Creates encrypted private key storaes |
| 162 | + |
| 163 | +* `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')` |
| 164 | +* `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. |
| 165 | + |
| 166 | +### ethereum.abi |
| 167 | + |
| 168 | +Most compilers for HLLs (solidity, serpent, viper, etc) on top of Ethereum have the option to output an ABI declaration for a program. This is a json object that looks something like this: |
| 169 | + |
| 170 | + [{"name": "ecrecover(uint256,uint256,uint256,uint256)", "type": "function", "constant": false, |
| 171 | + "inputs": [{"name": "h", "type": "uint256"}, {"name": "v", "type": "uint256"}, {"name": "r", "type": "uint256"}, {"name": "s", "type": "uint256"}], |
| 172 | + "outputs": [{"name": "out", "type": "int256[]"}]}, |
| 173 | + {"name": "PubkeyTripleLogEvent(uint256,uint256,uint256)", "type": "event", |
| 174 | + "inputs": [{"name": "x", "type": "uint256", "indexed": false}, {"name": "y", "type": "uint256", "indexed": false}, {"name": "z", "type": "uint256", "indexed": false}]}] |
| 175 | + |
| 176 | +You can initialize an `abi.ContractTranslator` object to encode and decode data for contracts as follows: |
| 177 | + |
| 178 | + true, false = True, False |
| 179 | + ct = abi.ContractTranslator(<json here>) |
| 180 | + txdata = ct.encode('function_name', [arg1, arg2, arg3]) |
| 181 | + |
| 182 | +You can also call `ct.decode_event([topic1, topic2...], logdata)` to decode a log. |
| 183 | + |
| 184 | +### RLP encoding and decoding |
| 185 | + |
| 186 | +For any transaction or block, you can simply do: |
| 187 | + |
| 188 | + import rlp |
| 189 | + bindata = rlp.encode(<tx or block>) |
| 190 | + |
| 191 | +To decode: |
| 192 | + |
| 193 | + import rlp |
| 194 | + from ethereum.transactions import Transaction |
| 195 | + rlp.decode(blob, Transaction) |
| 196 | + |
| 197 | +Or: |
| 198 | + |
| 199 | + import rlp |
| 200 | + from ethereum.blocks import Block |
| 201 | + rlp.decode(blob, Block) |
| 202 | + |
| 203 | +### Consensus abstraction |
| 204 | + |
| 205 | +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: |
| 206 | + |
| 207 | +* 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). |
| 208 | +* Add an entry to `consensus_strategy.py`. You will need to implement: |
| 209 | + * `check_seal` - check that a block is correctly "sealed" (mined, signed, etc) |
| 210 | + * `validate_uncles(state, block)` - check that uncles are valid |
| 211 | + * `initialize(state, block)` - called in `apply_block` before transactions are processed |
| 212 | + * `finalize(state, block)` - called in `apply_block` after transactions are processed |
| 213 | + * `get_uncle_candidates(chain, state)` - called in `mk_head_candidate` to include uncles in a block |
| 214 | +* Create a chain config with the `CONSENSUS_STRATEGY` set to whatever you named your new consensus strategy |
| 215 | + |
| 216 | +## Tester module |
| 217 | + |
| 218 | +See https://github.com/ethereum/pyethereum/wiki/Using-pyethereum.tester |
| 219 | + |
| 220 | +## Tests |
| 221 | + |
| 222 | +Run `python3.6 -m pytest ethereum/tests/<filename>` for any .py file in that directory. Currently all tests are passing except for a few Metropolis-specific state tests and block tests. |
| 223 | + |
| 224 | +To make your own state tests, use the tester module as follows: |
| 225 | + |
| 226 | +``` |
| 227 | +from ethereum.tools import tester as t |
| 228 | +import json |
| 229 | +c = t.Chain() |
| 230 | +x = c.contract(<code>, language=<language>) |
| 231 | +pre = t.mk_state_test_prefill(c) |
| 232 | +x.foo(<args>) |
| 233 | +post = t.mk_state_test_postfill(c, pre) |
| 234 | +open('output.json', 'w').write(json.dumps(post, indent=4)) |
| 235 | +``` |
| 236 | + |
| 237 | +To make a test filler file instead, do `post = t.mk_state_test_postfill(c, pre, True)`. |
| 238 | + |
| 239 | +## Licence |
| 240 | + |
| 241 | +See LICENCE |
0 commit comments