Skip to content

Commit

Permalink
feat: allow setting block time in geth --dev provider (#2487)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Feb 5, 2025
1 parent db009cc commit 9c09527
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 14 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
"eth-typing>=3.5.2,<6",
"eth-utils>=2.1.0,<6",
"hexbytes>=0.3.1,<2",
"py-geth>=5.1.0,<6",
"py-geth>=5.2.1,<6",
"trie>=3.0.1,<4", # Peer: stricter pin needed for uv support.
"web3[tester]>=6.20.1,<8",
# ** Dependencies maintained by ApeWorX **
Expand Down
46 changes: 34 additions & 12 deletions src/ape_node/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from urllib.parse import urlparse

from eth_utils import add_0x_prefix, to_hex
from geth.chain import initialize_chain
from geth.chain import initialize_chain as initialize_gethdev_chain
from geth.process import BaseGethProcess
from geth.wrapper import construct_test_chain_kwargs
from pydantic import field_validator
Expand Down Expand Up @@ -110,6 +110,9 @@ def __init__(
auto_disconnect: bool = True,
extra_funded_accounts: Optional[list[str]] = None,
hd_path: Optional[str] = DEFAULT_TEST_HD_PATH,
block_time: Optional[int] = None,
generate_accounts: bool = True,
initialize_chain: bool = True,
):
executable = executable or "geth"
if not shutil.which(executable):
Expand Down Expand Up @@ -141,6 +144,8 @@ def __init__(
kwargs_ctor["ws_enabled"] = False
kwargs_ctor["ws_addr"] = None
kwargs_ctor["ws_port"] = None
if block_time is not None:
kwargs_ctor["dev_period"] = f"{block_time}"

geth_kwargs = construct_test_chain_kwargs(**kwargs_ctor)

Expand All @@ -149,15 +154,22 @@ def __init__(

geth_kwargs["dev_mode"] = True
hd_path = hd_path or DEFAULT_TEST_HD_PATH
self._dev_accounts = generate_dev_accounts(
mnemonic, number_of_accounts=number_of_accounts, hd_path=hd_path
)
addresses = [a.address for a in self._dev_accounts]
addresses.extend(extra_funded_accounts or [])
bal_dict = {"balance": str(initial_balance)}
alloc = {a: bal_dict for a in addresses}
genesis = create_genesis_data(alloc, chain_id)
initialize_chain(genesis, self.data_dir)

if generate_accounts:
self._dev_accounts = generate_dev_accounts(
mnemonic, number_of_accounts=number_of_accounts, hd_path=hd_path
)
else:
self._dev_accounts = []

if initialize_chain:
addresses = [a.address for a in self._dev_accounts]
addresses.extend(extra_funded_accounts or [])
bal_dict = {"balance": str(initial_balance)}
alloc = {a: bal_dict for a in addresses}
genesis = create_genesis_data(alloc, chain_id)
initialize_gethdev_chain(genesis, self.data_dir)

super().__init__(geth_kwargs)

@classmethod
Expand All @@ -166,9 +178,13 @@ def from_uri(cls, uri: str, data_folder: Path, **kwargs):
number_of_accounts = kwargs.get("number_of_accounts", DEFAULT_NUMBER_OF_TEST_ACCOUNTS)
balance = kwargs.get("initial_balance", DEFAULT_TEST_ACCOUNT_BALANCE)
extra_accounts = [a.lower() for a in kwargs.get("extra_funded_accounts", [])]
block_time = kwargs.get("block_time", None)
if isinstance(block_time, int):
block_time = f"{block_time}"

process_kwargs = {
"auto_disconnect": kwargs.get("auto_disconnect", True),
"block_time": block_time,
"executable": kwargs.get("executable"),
"extra_funded_accounts": extra_accounts,
"hd_path": kwargs.get("hd_path", DEFAULT_TEST_HD_PATH),
Expand Down Expand Up @@ -295,7 +311,7 @@ class EthereumNetworkConfig(PluginConfig):
holesky: dict = {}
sepolia: dict = {}
# Make sure to run via `geth --dev` (or similar)
local: dict = {**DEFAULT_SETTINGS.copy(), "chain_id": DEFAULT_TEST_CHAIN_ID}
local: dict = {**DEFAULT_SETTINGS.copy(), "chain_id": DEFAULT_TEST_CHAIN_ID, "block_time": 0}

model_config = SettingsConfigDict(extra="allow", env_prefix="APE_NODE_")

Expand Down Expand Up @@ -391,6 +407,10 @@ def process_name(self) -> str:
def chain_id(self) -> int:
return self.settings.ethereum.local.get("chain_id", DEFAULT_TEST_CHAIN_ID)

@property
def block_time(self) -> Optional[int]:
return self.settings.ethereum.local.get("block_time")

@property
def data_dir(self) -> Path:
# Overridden from base class for placing debug logs in ape data folder.
Expand Down Expand Up @@ -470,7 +490,9 @@ def _create_process(self) -> GethDevProcess:
test_config["extra_funded_accounts"] = extra_accounts
test_config["initial_balance"] = self.test_config.balance
uri = self.ws_uri or self.uri
return GethDevProcess.from_uri(uri, self.data_dir, **test_config)
return GethDevProcess.from_uri(
uri, self.data_dir, block_time=self.block_time, **test_config
)

def disconnect(self):
# Must disconnect process first.
Expand Down
14 changes: 13 additions & 1 deletion tests/functional/geth/test_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ def web3(self) -> Web3:
def test_geth_bin_not_found():
bin_name = "__NOT_A_REAL_EXECUTABLE_HOPEFULLY__"
with pytest.raises(NodeSoftwareNotInstalledError):
_ = GethDevProcess(Path.cwd(), executable=bin_name)
_ = GethDevProcess(Path.cwd() / "notexists", executable=bin_name)


@geth_process_test
Expand Down Expand Up @@ -935,3 +935,15 @@ def test_geth_dev_from_uri_ipc(data_folder):
assert kwargs.get("ws_api") is None
assert kwargs.get("ws_addr") is None
assert kwargs.get("rpc_addr") is None


@geth_process_test
def test_geth_dev_block_period(data_folder):
geth_dev = GethDevProcess.from_uri(
"path/to/geth.ipc",
data_folder,
block_time=1,
generate_accounts=False,
initialize_chain=False,
)
assert geth_dev.geth_kwargs["dev_period"] == "1"

0 comments on commit 9c09527

Please sign in to comment.