Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adopt the TurboGeth database layout #1879

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 34 additions & 13 deletions eth/chains/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from eth.db.header import (
HeaderDB,
)
from eth.db.schema import Schemas

from eth.estimators import (
get_gas_estimator,
Expand Down Expand Up @@ -402,7 +403,10 @@ def from_genesis(cls,
genesis_vm_class = cls.get_vm_class_for_block_number(BlockNumber(0))

pre_genesis_header = BlockHeader(difficulty=0, block_number=-1, gas_limit=0)
state = genesis_vm_class.build_state(base_db, pre_genesis_header)
state = genesis_vm_class.build_state(
base_db, pre_genesis_header,
expected_schema=Schemas.DEFAULT,
)

if genesis_state is None:
genesis_state = {}
Expand Down Expand Up @@ -580,7 +584,11 @@ def build_block_with_transactions(
:param parent_header: parent of the new block -- or canonical head if ``None``
:return: (new block, receipts, computations)
"""
base_header = self.ensure_header(parent_header)
if parent_header is None:
base_header = self.ensure_header()
else:
base_header = self.create_header_from_parent(parent_header)

vm = self.get_vm(base_header)

new_header, receipts, computations = vm.apply_all_transactions(transactions, base_header)
Expand Down Expand Up @@ -680,8 +688,6 @@ def estimate_gas(
Returns an estimation of the amount of gas the given transaction will
use if executed on top of the block specified by the given header.
"""
if at_header is None:
at_header = self.get_canonical_head()
with self.get_vm(at_header).state_in_temp_block() as state:
return self.gas_estimator(state, transaction)

Expand Down Expand Up @@ -869,10 +875,12 @@ def _extract_uncle_hashes(blocks: Iterable[BaseBlock]) -> Iterable[Hash32]:

class MiningChain(Chain):
header: BlockHeader = None
vm: BaseVM = None

def __init__(self, base_db: BaseAtomicDB, header: BlockHeader=None) -> None:
super().__init__(base_db)
self.header = self.ensure_header(header)
self.vm = super().get_vm(self.header)

def apply_transaction(self,
transaction: BaseTransaction
Expand All @@ -883,23 +891,33 @@ def apply_transaction(self,
WARNING: Receipt and Transaction trie generation is computationally
heavy and incurs significant performance overhead.
"""
vm = self.get_vm(self.header)
base_block = vm.get_block()
base_block = self.vm.get_block()

receipt, computation = vm.apply_transaction(base_block.header, transaction)
header_with_receipt = vm.add_receipt_to_header(base_block.header, receipt)
receipt, computation = self.vm.apply_transaction(base_block.header, transaction)
header_with_receipt = self.vm.add_receipt_to_header(base_block.header, receipt)

# since we are building the block locally, we have to persist all the incremental state
vm.state.persist()
new_header = header_with_receipt.copy(state_root=vm.state.state_root)
self.vm.state.persist()
new_header = header_with_receipt.copy(state_root=self.vm.state.state_root)

transactions = base_block.transactions + (transaction, )
receipts = base_block.get_receipts(self.chaindb) + (receipt, )

new_block = vm.set_block_transactions(base_block, new_header, transactions, receipts)
new_block = self.vm.set_block_transactions(
base_block, new_header, transactions, receipts
)

self.header = new_block.header

# We need to create a new VM so that the next transaction to be processed builds
# on top of the result of processing this transaction. However, in order to save
# block diffs, we need to have a single instance of _state which is reused between
# all calls to `apply_transaction`. This is a bit of a kludge but it works.
new_vm_class = self.get_vm_class_for_block_number(self.header.block_number)
new_vm = new_vm_class(header=self.header, chaindb=self.vm.chaindb)
new_vm._state = self.vm._state
self.vm = new_vm

return new_block, receipt, computation

def import_block(self,
Expand All @@ -910,23 +928,26 @@ def import_block(self,
block, perform_validation)

self.header = self.ensure_header()
self.vm = super().get_vm(self.header)

return imported_block, new_canonical_blocks, old_canonical_blocks

def mine_block(self, *args: Any, **kwargs: Any) -> BaseBlock:
"""
Mines the current block. Proxies to the current Virtual Machine.
See VM. :meth:`~eth.vm.base.VM.mine_block`
"""
mined_block = self.get_vm(self.header).mine_block(*args, **kwargs)
mined_block = self.vm.mine_block(*args, **kwargs)

self.validate_block(mined_block)

self.chaindb.persist_block(mined_block)
self.header = self.create_header_from_parent(mined_block.header)
self.vm = super().get_vm(self.header)
return mined_block

def get_vm(self, at_header: BlockHeader=None) -> 'BaseVM':
if at_header is None:
at_header = self.header
return self.vm

return super().get_vm(at_header)
Loading