Skip to content

Commit

Permalink
fill genesis_data defaults correctly and test
Browse files Browse the repository at this point in the history
  • Loading branch information
pacrob committed Jun 6, 2024
1 parent fa47caa commit 2c9119a
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 13 deletions.
6 changes: 3 additions & 3 deletions geth/chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
is_same_path,
)
from .utils.validation import (
GenesisData,
fill_default_genesis_data,
validate_genesis_data,
)
from .wrapper import (
Expand Down Expand Up @@ -119,11 +119,11 @@ def write_genesis_file(

validate_genesis_data(genesis_data)
# use GenesisData model to fill defaults
genesis_data_model = GenesisData(**genesis_data)
filled_genesis_data_model = fill_default_genesis_data(genesis_data)

with open(genesis_file_path, "w") as genesis_file:
genesis_file.write(
json.dumps(force_obj_to_text(genesis_data_model.model_dump()))
json.dumps(force_obj_to_text(filled_genesis_data_model.model_dump()))
)


Expand Down
47 changes: 39 additions & 8 deletions geth/utils/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class GethKwargs(BaseModel):
model_config = ConfigDict(extra="forbid")


def validate_geth_kwargs(geth_kwargs: GethKwargsTypedDict) -> bool:
def validate_geth_kwargs(geth_kwargs: GethKwargsTypedDict) -> None:
"""
Converts geth_kwargs to GethKwargs and raises a ValueError if the conversion fails.
"""
Expand All @@ -73,7 +73,6 @@ def validate_geth_kwargs(geth_kwargs: GethKwargsTypedDict) -> bool:
raise PyGethValueError(f"geth_kwargs validation failed: {e}")
except TypeError as e:
raise PyGethValueError(f"error while validating geth_kwargs: {e}")
return True


class GenesisDataConfig(BaseModel):
Expand Down Expand Up @@ -121,7 +120,17 @@ class GenesisData(BaseModel):
model_config = ConfigDict(extra="forbid")


def validate_genesis_data(genesis_data: GenesisDataTypedDict) -> bool:
def validate_genesis_data(genesis_data: GenesisDataTypedDict) -> None:
"""
Validates the genesis data
"""
try:
GenesisData(**genesis_data)
except ValidationError as e:
raise PyGethValueError(f"genesis_data validation failed: {e}")
except TypeError as e:
raise PyGethValueError(f"error while validating genesis_data: {e}")

"""
Validates the genesis data config field
"""
Expand All @@ -135,13 +144,35 @@ def validate_genesis_data(genesis_data: GenesisDataTypedDict) -> bool:
raise PyGethValueError(
f"error while validating genesis_data config field: {e}"
)


def fill_default_genesis_data(
genesis_data: GenesisDataTypedDict,
) -> GenesisData:
"""
Validates the genesis data
Fills in default values for the genesis data
"""
try:
GenesisData(**genesis_data)
genesis_data_filled = GenesisData(**genesis_data)
except ValidationError as e:
raise PyGethValueError(f"genesis_data validation failed: {e}")
raise PyGethValueError(
f"genesis_data validation failed while filling defaults: {e}"
)
except TypeError as e:
raise PyGethValueError(f"error while validating genesis_data: {e}")
return True
raise PyGethValueError(f"error while filling default genesis_data: {e}")

if genesis_data.get("config"):
try:
genesis_data_config_filled = GenesisDataConfig(**genesis_data["config"])
except ValidationError as e:
raise PyGethValueError(
f"genesis_data validation failed while filling config defaults: {e}"
)
except TypeError as e:
raise PyGethValueError(
f"error while filling default genesis_data config: {e}"
)

genesis_data_filled.config = genesis_data_config_filled.model_dump()

return genesis_data_filled
1 change: 1 addition & 0 deletions newsfragments/215.internal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add ``fill_default_genesis_data`` function to properly fill ``genesis_data`` defaults
150 changes: 148 additions & 2 deletions tests/core/utility/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
)
from geth.utils.validation import (
GenesisData,
fill_default_genesis_data,
validate_genesis_data,
validate_geth_kwargs,
)
Expand All @@ -34,7 +35,7 @@
],
)
def test_validate_geth_kwargs_good(geth_kwargs):
assert validate_geth_kwargs(geth_kwargs) is True
assert validate_geth_kwargs(geth_kwargs) is None


@pytest.mark.parametrize(
Expand Down Expand Up @@ -63,7 +64,7 @@ def test_validate_geth_kwargs_bad(geth_kwargs):
],
)
def test_validate_genesis_data_good(genesis_data):
assert validate_genesis_data(genesis_data) is True
assert validate_genesis_data(genesis_data) is None


@pytest.mark.parametrize(
Expand All @@ -84,13 +85,158 @@ def test_validate_genesis_data_good(genesis_data):
"nonce": "abc",
"config": None,
},
"kangaroo",
],
)
def test_validate_genesis_data_bad(genesis_data):
with pytest.raises(PyGethValueError):
validate_genesis_data(genesis_data)


@pytest.mark.parametrize(
"genesis_data,expected",
[
(
{
"difficulty": "0x00012131",
"nonce": "abc",
"timestamp": "1234",
},
{
"alloc": {},
"coinbase": "0x3333333333333333333333333333333333333333",
"config": {
"ethash": {},
"homesteadBlock": 0,
"daoForkBlock": 0,
"daoForkSupport": True,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"arrowGlacierBlock": 0,
"grayGlacierBlock": 0,
"terminalTotalDifficulty": 0,
"terminalTotalDifficultyPassed": True,
"shanghaiTime": 0,
"cancunTime": 0,
},
"difficulty": "0x00012131",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", # noqa: E501
"gasLimit": "0x47e7c4",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", # noqa: E501
"nonce": "abc",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", # noqa: E501
"timestamp": "1234",
},
),
(
{
"difficulty": "0x00012131",
"nonce": "abc",
"config": {
"homesteadBlock": 5,
"daoForkBlock": 1,
"daoForkSupport": False,
"eip150Block": 27777777,
"eip155Block": 99,
"eip158Block": 32,
},
},
{
"alloc": {},
"coinbase": "0x3333333333333333333333333333333333333333",
"config": {
"ethash": {},
"homesteadBlock": 5,
"daoForkBlock": 1,
"daoForkSupport": False,
"eip150Block": 27777777,
"eip155Block": 99,
"eip158Block": 32,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"arrowGlacierBlock": 0,
"grayGlacierBlock": 0,
"terminalTotalDifficulty": 0,
"terminalTotalDifficultyPassed": True,
"shanghaiTime": 0,
"cancunTime": 0,
},
"difficulty": "0x00012131",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", # noqa: E501
"gasLimit": "0x47e7c4",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", # noqa: E501
"nonce": "abc",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", # noqa: E501
"timestamp": "0x0",
},
),
],
)
def test_fill_default_genesis_data_good(genesis_data, expected):
genesis_data_td = GenesisDataTypedDict(**genesis_data)
filled_genesis_data = fill_default_genesis_data(genesis_data_td).model_dump()
assert filled_genesis_data == expected


@pytest.mark.parametrize(
"genesis_data,expected_exception,expected_message",
[
(
{
"difficulty": "0x00012131",
"nonce": "abc",
"timestamp": 1234,
},
PyGethValueError,
"genesis_data validation failed while filling defaults: ",
),
(
{
"difficulty": "0x00012131",
"nonce": "abc",
"config": {
"homesteadBlock": 5,
"daoForkBlock": "beep",
"daoForkSupport": False,
"eip150Block": 27777777,
"eip155Block": 99,
"eip158Block": 32,
},
},
PyGethValueError,
"genesis_data validation failed while filling config defaults: ",
),
(
"abc123",
PyGethValueError,
"error while filling default genesis_data: ",
),
(
{"difficulty": "0x00012131", "nonce": "abc", "config": ["beep"]},
PyGethValueError,
"genesis_data validation failed while filling defaults: ",
),
],
)
def test_fill_default_genesis_data_bad(
genesis_data, expected_exception, expected_message
):
with pytest.raises(expected_exception) as excinfo:
fill_default_genesis_data(genesis_data)
assert str(excinfo.value).startswith(expected_message)


@pytest.mark.skipif(sys.version_info < (3, 9), reason="get_type_hints requires >=py39")
@pytest.mark.parametrize(
"model, typed_dict",
Expand Down

0 comments on commit 2c9119a

Please sign in to comment.