|
1 | 1 | Understanding the mining process
|
2 | 2 | ================================
|
3 | 3 |
|
4 |
| -In the :doc:`Building Chains Guide <building_chains>` we already learned how to |
5 |
| -use the :class:`~eth.chains.base.MiningChain` class to create a single |
| 4 | +From the :ref:`EVM Cookbook<evm_cookbook>` we can already learn how to |
| 5 | +use the :class:`~eth.chains.base.Chain` class to create a single |
6 | 6 | blockchain as a combination of different virtual machines for different spans
|
7 | 7 | of blocks.
|
8 | 8 |
|
@@ -38,7 +38,9 @@ block first because, after all, one primary use case for the Ethereum blockchain
|
38 | 38 | For the sake of simplicity though, we'll mine an empty block as a first example (meaning the block
|
39 | 39 | will not contain any transactions)
|
40 | 40 |
|
41 |
| -As a refresher, he's where we left of as part of the :doc:`Building Chains Guide </guides/eth/building_chains>`. |
| 41 | +As a refresher, he's how we create a chain as demonstrated in the |
| 42 | +:ref:`Using the chain object recipe<evm_cookbook_recipe_using_the_chain_object>` from the |
| 43 | +cookbook. |
42 | 44 |
|
43 | 45 | ::
|
44 | 46 |
|
@@ -308,74 +310,76 @@ Finally, we can call :func:`~eth.chains.base.MiningChain.apply_transaction` and
|
308 | 310 | What follows is the complete script that demonstrates how to mine a single block with one simple
|
309 | 311 | zero value transfer transaction.
|
310 | 312 |
|
311 |
| -:: |
312 |
| - |
313 |
| - from eth_keys import keys |
314 |
| - from eth_utils import decode_hex |
315 |
| - from eth_typing import Address |
316 |
| - |
317 |
| - from eth.consensus.pow import mine_pow_nonce |
318 |
| - from eth import constants, MiningChain |
319 |
| - from eth.vm.forks.byzantium import ByzantiumVM |
320 |
| - from eth.db.backends.memory import MemoryDB |
321 |
| - |
322 |
| - |
323 |
| - GENESIS_PARAMS = { |
324 |
| - 'parent_hash': constants.GENESIS_PARENT_HASH, |
325 |
| - 'uncles_hash': constants.EMPTY_UNCLE_HASH, |
326 |
| - 'coinbase': constants.ZERO_ADDRESS, |
327 |
| - 'transaction_root': constants.BLANK_ROOT_HASH, |
328 |
| - 'receipt_root': constants.BLANK_ROOT_HASH, |
329 |
| - 'difficulty': 1, |
330 |
| - 'block_number': constants.GENESIS_BLOCK_NUMBER, |
331 |
| - 'gas_limit': constants.GENESIS_GAS_LIMIT, |
332 |
| - 'timestamp': 1514764800, |
333 |
| - 'extra_data': constants.GENESIS_EXTRA_DATA, |
334 |
| - 'nonce': constants.GENESIS_NONCE |
335 |
| - } |
336 |
| - |
337 |
| - SENDER_PRIVATE_KEY = keys.PrivateKey( |
338 |
| - decode_hex('0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8') |
339 |
| - ) |
340 |
| - |
341 |
| - SENDER = Address(SENDER_PRIVATE_KEY.public_key.to_canonical_address()) |
342 |
| - |
343 |
| - RECEIVER = Address(b'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02') |
344 |
| - |
345 |
| - klass = MiningChain.configure( |
346 |
| - __name__='TestChain', |
347 |
| - vm_configuration=( |
348 |
| - (constants.GENESIS_BLOCK_NUMBER, ByzantiumVM), |
349 |
| - )) |
350 |
| - |
351 |
| - chain = klass.from_genesis(MemoryDB(), GENESIS_PARAMS) |
352 |
| - vm = chain.get_vm() |
353 |
| - |
354 |
| - nonce = vm.get_transaction_nonce(SENDER) |
355 |
| - |
356 |
| - tx = vm.create_unsigned_transaction( |
357 |
| - nonce=nonce, |
358 |
| - gas_price=0, |
359 |
| - gas=100000, |
360 |
| - to=RECEIVER, |
361 |
| - value=0, |
362 |
| - data=b'', |
363 |
| - ) |
364 |
| - |
365 |
| - signed_tx = tx.as_signed_transaction(SENDER_PRIVATE_KEY) |
366 |
| - |
367 |
| - chain.apply_transaction(signed_tx) |
368 |
| - |
369 |
| - # We have to finalize the block first in order to be able read the |
370 |
| - # attributes that are important for the PoW algorithm |
371 |
| - block = chain.get_vm().finalize_block(chain.get_block()) |
372 |
| - |
373 |
| - # based on mining_hash, block number and difficulty we can perform |
374 |
| - # the actual Proof of Work (PoW) mechanism to mine the correct |
375 |
| - # nonce and mix_hash for this block |
376 |
| - nonce, mix_hash = mine_pow_nonce( |
377 |
| - block.number, |
378 |
| - block.header.mining_hash, |
379 |
| - block.header.difficulty) |
380 |
| - |
381 |
| - block = chain.mine_block(mix_hash=mix_hash, nonce=nonce) |
| 313 | +.. doctest:: |
| 314 | + |
| 315 | + >>> from eth_keys import keys |
| 316 | + >>> from eth_utils import decode_hex |
| 317 | + >>> from eth_typing import Address |
| 318 | + >>> from eth import constants |
| 319 | + >>> from eth.chains.base import MiningChain |
| 320 | + >>> from eth.consensus.pow import mine_pow_nonce |
| 321 | + >>> from eth.vm.forks.byzantium import ByzantiumVM |
| 322 | + >>> from eth.db.backends.memory import MemoryDB |
| 323 | + |
| 324 | + |
| 325 | + >>> GENESIS_PARAMS = { |
| 326 | + ... 'parent_hash': constants.GENESIS_PARENT_HASH, |
| 327 | + ... 'uncles_hash': constants.EMPTY_UNCLE_HASH, |
| 328 | + ... 'coinbase': constants.ZERO_ADDRESS, |
| 329 | + ... 'transaction_root': constants.BLANK_ROOT_HASH, |
| 330 | + ... 'receipt_root': constants.BLANK_ROOT_HASH, |
| 331 | + ... 'difficulty': 1, |
| 332 | + ... 'block_number': constants.GENESIS_BLOCK_NUMBER, |
| 333 | + ... 'gas_limit': constants.GENESIS_GAS_LIMIT, |
| 334 | + ... 'timestamp': 1514764800, |
| 335 | + ... 'extra_data': constants.GENESIS_EXTRA_DATA, |
| 336 | + ... 'nonce': constants.GENESIS_NONCE |
| 337 | + ... } |
| 338 | + |
| 339 | + >>> SENDER_PRIVATE_KEY = keys.PrivateKey( |
| 340 | + ... decode_hex('0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8') |
| 341 | + ... ) |
| 342 | + |
| 343 | + >>> SENDER = Address(SENDER_PRIVATE_KEY.public_key.to_canonical_address()) |
| 344 | + |
| 345 | + >>> RECEIVER = Address(b'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02') |
| 346 | + |
| 347 | + >>> klass = MiningChain.configure( |
| 348 | + ... __name__='TestChain', |
| 349 | + ... vm_configuration=( |
| 350 | + ... (constants.GENESIS_BLOCK_NUMBER, ByzantiumVM), |
| 351 | + ... )) |
| 352 | + |
| 353 | + >>> chain = klass.from_genesis(MemoryDB(), GENESIS_PARAMS) |
| 354 | + >>> vm = chain.get_vm() |
| 355 | + |
| 356 | + >>> nonce = vm.state.account_db.get_nonce(SENDER) |
| 357 | + |
| 358 | + >>> tx = vm.create_unsigned_transaction( |
| 359 | + ... nonce=nonce, |
| 360 | + ... gas_price=0, |
| 361 | + ... gas=100000, |
| 362 | + ... to=RECEIVER, |
| 363 | + ... value=0, |
| 364 | + ... data=b'', |
| 365 | + ... ) |
| 366 | + |
| 367 | + >>> signed_tx = tx.as_signed_transaction(SENDER_PRIVATE_KEY) |
| 368 | + |
| 369 | + >>> chain.apply_transaction(signed_tx) |
| 370 | + (<ByzantiumBlock(#Block #1...) |
| 371 | + >>> # We have to finalize the block first in order to be able read the |
| 372 | + >>> # attributes that are important for the PoW algorithm |
| 373 | + >>> block = chain.get_vm().finalize_block(chain.get_block()) |
| 374 | + |
| 375 | + >>> # based on mining_hash, block number and difficulty we can perform |
| 376 | + >>> # the actual Proof of Work (PoW) mechanism to mine the correct |
| 377 | + >>> # nonce and mix_hash for this block |
| 378 | + >>> nonce, mix_hash = mine_pow_nonce( |
| 379 | + ... block.number, |
| 380 | + ... block.header.mining_hash, |
| 381 | + ... block.header.difficulty |
| 382 | + ... ) |
| 383 | + |
| 384 | + >>> chain.mine_block(mix_hash=mix_hash, nonce=nonce) |
| 385 | + <ByzantiumBlock(#Block #1)> |
0 commit comments