diff --git a/packages/testing/src/execution_testing/client_clis/clis/execution_specs.py b/packages/testing/src/execution_testing/client_clis/clis/execution_specs.py index cd6100495b2..ed3a48d25b5 100644 --- a/packages/testing/src/execution_testing/client_clis/clis/execution_specs.py +++ b/packages/testing/src/execution_testing/client_clis/clis/execution_specs.py @@ -229,6 +229,9 @@ class ExecutionSpecsExceptionMapper(ExceptionMapper): BlockException.SYSTEM_CONTRACT_EMPTY: "System contract address", BlockException.SYSTEM_CONTRACT_CALL_FAILED: "call failed:", BlockException.INVALID_DEPOSIT_EVENT_LAYOUT: "deposit", + BlockException.BLOCK_ACCESS_LIST_GAS_LIMIT_EXCEEDED: ( + "Block access list exceeds gas limit" + ), TransactionException.LOG_MISMATCH: "LogMismatchError", } mapping_regex: ClassVar[Dict[ExceptionBase, str]] = { diff --git a/packages/testing/src/execution_testing/exceptions/exceptions/block.py b/packages/testing/src/execution_testing/exceptions/exceptions/block.py index b10c59d5d2e..eceb98b6336 100644 --- a/packages/testing/src/execution_testing/exceptions/exceptions/block.py +++ b/packages/testing/src/execution_testing/exceptions/exceptions/block.py @@ -186,3 +186,7 @@ class BlockException(ExceptionBase): """ Block BAL is missing an account change that is present in the computed BAL. """ + BLOCK_ACCESS_LIST_GAS_LIMIT_EXCEEDED = auto() + """ + Block access list exceeds the gas limit constraint (EIP-7928). + """ diff --git a/packages/testing/src/execution_testing/forks/base_fork.py b/packages/testing/src/execution_testing/forks/base_fork.py index 89fa18afc26..d213a6ba3a9 100644 --- a/packages/testing/src/execution_testing/forks/base_fork.py +++ b/packages/testing/src/execution_testing/forks/base_fork.py @@ -361,6 +361,19 @@ def header_bal_hash_required( """Return true if the header must contain block access list hash.""" pass + @classmethod + @abstractmethod + def empty_block_bal_item_count( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> int: + """ + Return the number of BAL items produced by an empty block. + + Each system contract address counts as 1 item, and each unique + storage key it touches (reads or writes) counts as 1 item. + """ + pass + # Gas related abstract methods @classmethod diff --git a/packages/testing/src/execution_testing/forks/forks/forks.py b/packages/testing/src/execution_testing/forks/forks/forks.py index f4ee96f13be..5640faa0f18 100644 --- a/packages/testing/src/execution_testing/forks/forks/forks.py +++ b/packages/testing/src/execution_testing/forks/forks/forks.py @@ -200,6 +200,7 @@ def gas_costs( GAS_PRECOMPILE_BLS_PAIRING_BASE=0, GAS_PRECOMPILE_BLS_PAIRING_PER_PAIR=0, GAS_PRECOMPILE_P256VERIFY=0, + GAS_BLOCK_ACCESS_LIST_ITEM=0, ) @classmethod @@ -1011,6 +1012,14 @@ def header_bal_hash_required( del block_number, timestamp return False + @classmethod + def empty_block_bal_item_count( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> int: + """Pre-Amsterdam forks have no block access list.""" + del block_number, timestamp + return 0 + @classmethod def engine_new_payload_version( cls, *, block_number: int = 0, timestamp: int = 0 @@ -3431,6 +3440,37 @@ def header_bal_hash_required( del block_number, timestamp return True + @classmethod + def gas_costs( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> GasCosts: + """ + On Amsterdam, the cost per block access list item is introduced + in EIP-7928. + """ + return replace( + super(Amsterdam, cls).gas_costs( + block_number=block_number, timestamp=timestamp + ), + GAS_BLOCK_ACCESS_LIST_ITEM=2000, + ) + + @classmethod + def empty_block_bal_item_count( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> int: + """ + Return the BAL item count for an empty Amsterdam block. + + Four system contracts produce 15 items: + EIP-4788 beacon roots: 1 address + 1 write + 1 read = 3 + EIP-2935 history storage: 1 address + 1 write = 2 + EIP-7002 withdrawal requests: 1 address + 4 reads = 5 + EIP-7251 consolidation requests: 1 address + 4 reads = 5 + """ + del block_number, timestamp + return 15 + @classmethod def is_deployed(cls) -> bool: """Return True if this fork is deployed.""" diff --git a/packages/testing/src/execution_testing/forks/gas_costs.py b/packages/testing/src/execution_testing/forks/gas_costs.py index f5125946b7d..eb632dd0888 100644 --- a/packages/testing/src/execution_testing/forks/gas_costs.py +++ b/packages/testing/src/execution_testing/forks/gas_costs.py @@ -89,3 +89,5 @@ class GasCosts: # Refund constants REFUND_STORAGE_CLEAR: int REFUND_AUTH_PER_EXISTING_ACCOUNT: int + + GAS_BLOCK_ACCESS_LIST_ITEM: int diff --git a/src/ethereum/forks/amsterdam/block_access_lists.py b/src/ethereum/forks/amsterdam/block_access_lists.py index 08c18ce9656..c6bcf176886 100644 --- a/src/ethereum/forks/amsterdam/block_access_lists.py +++ b/src/ethereum/forks/amsterdam/block_access_lists.py @@ -23,6 +23,7 @@ from ethereum.crypto.hash import Hash32, keccak256 from ethereum.state import EMPTY_CODE_HASH, Account, Address, PreState +from .exceptions import BlockAccessListGasLimitExceededError from .state_tracker import BlockState, TransactionState, get_code # TODO: Either remove or generalize these type aliases (#2260). @@ -558,6 +559,9 @@ def _build_from_builder( - Storage slots (lexicographically) - Transaction indices (numerically) for each change type + Addresses, storage slots, and block access indices are unique. + Storage reads that also appear in storage changes are excluded. + [`BlockAccessList`]: ref:ethereum.forks.amsterdam.block_access_lists.BlockAccessList """ # noqa: E501 block_access_list: BlockAccessList = [] @@ -728,3 +732,39 @@ def hash_block_access_list( Compute the hash of a Block Access List. """ return keccak256(rlp.encode(block_access_list)) + + +def validate_block_access_list_gas_limit( + block_access_list: BlockAccessList, + block_gas_limit: Uint, +) -> None: + """ + Validate that the block access list does not exceed the gas limit. + + The total number of items (addresses + unique storage keys) must not + exceed ``block_gas_limit // GAS_BLOCK_ACCESS_LIST_ITEM``. + """ + from .vm.gas import GAS_BLOCK_ACCESS_LIST_ITEM + + bal_items = Uint(0) + for account in block_access_list: + # Count each address as one item + bal_items += Uint(1) + + # Collect unique storage keys across both + # reads and writes + unique_slots: Set[U256] = set() + for slot_change in account.storage_changes: + unique_slots.add(slot_change.slot) + for slot in account.storage_reads: + unique_slots.add(slot) + + # Count each unique storage key as one item + bal_items += Uint(len(unique_slots)) + + if bal_items > block_gas_limit // GAS_BLOCK_ACCESS_LIST_ITEM: + raise BlockAccessListGasLimitExceededError( + f"Block access list exceeds gas limit, {bal_items} items " + f"exceeds limit of " + f"{block_gas_limit // GAS_BLOCK_ACCESS_LIST_ITEM}." + ) diff --git a/src/ethereum/forks/amsterdam/exceptions.py b/src/ethereum/forks/amsterdam/exceptions.py index 3074a1f738f..1c6c14cc33d 100644 --- a/src/ethereum/forks/amsterdam/exceptions.py +++ b/src/ethereum/forks/amsterdam/exceptions.py @@ -6,7 +6,7 @@ from ethereum_types.numeric import Uint -from ethereum.exceptions import InvalidTransaction +from ethereum.exceptions import InvalidBlock, InvalidTransaction if TYPE_CHECKING: from .transactions import Transaction @@ -129,3 +129,13 @@ class TransactionGasLimitExceededError(InvalidTransaction): Note that this is _not_ the exception thrown when bytecode execution runs out of gas. """ + + +class BlockAccessListGasLimitExceededError(InvalidBlock): + """ + The block access list exceeds the gas limit constraint. + + Introduced in [EIP-7928]. + + [EIP-7928]: https://eips.ethereum.org/EIPS/eip-7928 + """ diff --git a/src/ethereum/forks/amsterdam/fork.py b/src/ethereum/forks/amsterdam/fork.py index 3fccd54f218..da363e622bb 100644 --- a/src/ethereum/forks/amsterdam/fork.py +++ b/src/ethereum/forks/amsterdam/fork.py @@ -35,6 +35,7 @@ BlockAccessListBuilder, build_block_access_list, hash_block_access_list, + validate_block_access_list_gas_limit, ) from .blocks import Block, Header, Log, Receipt, Withdrawal, encode_receipt from .bloom import logs_bloom @@ -814,6 +815,12 @@ def apply_body( block_env.block_access_list_builder, block_env.state ) + # Validate block access list gas limit constraint (EIP-7928) + validate_block_access_list_gas_limit( + block_access_list=block_output.block_access_list, + block_gas_limit=block_env.block_gas_limit, + ) + return block_output diff --git a/src/ethereum/forks/amsterdam/vm/gas.py b/src/ethereum/forks/amsterdam/vm/gas.py index 7044b2ae110..c5d365a2a3c 100644 --- a/src/ethereum/forks/amsterdam/vm/gas.py +++ b/src/ethereum/forks/amsterdam/vm/gas.py @@ -84,6 +84,8 @@ GAS_BLS_G2_MUL = Uint(22500) GAS_BLS_G2_MAP = Uint(23800) +GAS_BLOCK_ACCESS_LIST_ITEM = Uint(2000) + @dataclass class ExtendMemory: diff --git a/src/ethereum_spec_tools/evm_tools/t8n/__init__.py b/src/ethereum_spec_tools/evm_tools/t8n/__init__.py index 3f5084cd4d6..523aa5a026c 100644 --- a/src/ethereum_spec_tools/evm_tools/t8n/__init__.py +++ b/src/ethereum_spec_tools/evm_tools/t8n/__init__.py @@ -22,6 +22,7 @@ from ethereum.forks.amsterdam.block_access_lists import ( BlockAccessIndex, BlockAccessListBuilder, + validate_block_access_list_gas_limit, ) from ethereum_spec_tools.forks import Hardfork, TemporaryHardfork @@ -465,6 +466,12 @@ def _run_blockchain_test(self, block_env: Any, block_output: Any) -> None: block_env.block_access_list_builder, block_env.state ) + # Validate block access list gas limit constraint (EIP-7928) + validate_block_access_list_gas_limit( + block_access_list=block_output.block_access_list, + block_gas_limit=block_env.block_gas_limit, + ) + def run_blockchain_test(self) -> None: """ Apply a block on the pre-state. Also includes system operations. diff --git a/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py b/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py index 1aff9d629fa..0f377f6f937 100644 --- a/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py +++ b/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py @@ -18,6 +18,7 @@ Block, BlockAccessListExpectation, BlockchainTestFiller, + BlockException, Environment, Fork, Hash, @@ -2645,3 +2646,53 @@ def test_bal_lexicographic_address_ordering( addr_endian_high: Account(balance=addr_balance), }, ) + + +@pytest.mark.parametrize( + "boundary_offset", + [ + pytest.param(0, id="at_boundary"), + pytest.param( + -1, + marks=pytest.mark.exception_test, + id="below_boundary", + ), + ], +) +def test_bal_gas_limit_boundary( + blockchain_test: BlockchainTestFiller, + pre: Alloc, + fork: Fork, + boundary_offset: int, +) -> None: + """ + Test the BAL max items gas limit boundary for an empty block. + + The consensus rule requires + ``bal_items <= block_gas_limit // GAS_BLOCK_ACCESS_LIST_ITEM``. + The boundary gas limit is derived from the fork's system-contract + BAL footprint. At the boundary the check passes; one below it fails. + """ + # EIP-7928 + # bal_items <= block_gas_limit // ITEM_COST + min_gas_limit = ( + fork.empty_block_bal_item_count() + * fork.gas_costs().GAS_BLOCK_ACCESS_LIST_ITEM + ) + gas_limit = min_gas_limit + boundary_offset + + block = Block( + txs=[], + exception=( + BlockException.BLOCK_ACCESS_LIST_GAS_LIMIT_EXCEEDED + if boundary_offset < 0 + else None + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={}, + genesis_environment=Environment(gas_limit=gas_limit), + ) diff --git a/tests/constantinople/eip1052_extcodehash/test_extcodehash.py b/tests/constantinople/eip1052_extcodehash/test_extcodehash.py index af1f9a22114..2739240c625 100644 --- a/tests/constantinople/eip1052_extcodehash/test_extcodehash.py +++ b/tests/constantinople/eip1052_extcodehash/test_extcodehash.py @@ -9,6 +9,7 @@ Alloc, Initcode, Op, + Opcodes, StateTestFiller, Storage, Transaction, @@ -589,3 +590,77 @@ def test_extcodehash_precompile( post={code_address: Account(storage=storage)}, tx=tx, ) + + +@pytest.mark.ported_from( + [ + "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stExtCodeHash/extCodeHashNewAccountFiller.json", # noqa: E501 + "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stExtCodeHash/createEmptyThenExtcodehashFiller.json", # noqa: E501 + ], + pr=["https://github.com/ethereum/execution-specs/pull/2326"], +) +@pytest.mark.parametrize("opcode", [Op.CREATE, Op.CREATE2]) +@pytest.mark.parametrize( + "deployed_code", + [ + pytest.param((0x1234).to_bytes(32, "big"), id="non-empty"), + pytest.param(b"", id="empty"), + ], +) +def test_extcodehash_new_account( + state_test: StateTestFiller, + pre: Alloc, + deployed_code: bytes, + opcode: Opcodes, +) -> None: + """ + Test EXTCODEHASH/EXTCODESIZE of a contract created within the same tx. + + Uses CREATE/CREATE2 to deploy a contract, then verifies that EXTCODEHASH + and EXTCODESIZE reflect the newly deployed code. + """ + storage = Storage() + + initcode = Op.MSTORE( + 0, int.from_bytes(deployed_code.ljust(32, b"\0"), "big") + ) + Op.RETURN(0, len(deployed_code)) + + created_slot = storage.store_next(0) + hash_slot = storage.store_next(keccak256(deployed_code)) + size_slot = storage.store_next(len(deployed_code)) + + code = ( + Op.MSTORE(0, Op.PUSH32(bytes(initcode).ljust(32, b"\0"))) + + Op.SSTORE( + created_slot, + opcode(value=0, offset=0, size=len(initcode)), + ) + + Op.SSTORE(hash_slot, Op.EXTCODEHASH(Op.SLOAD(created_slot))) + + Op.SSTORE(size_slot, Op.EXTCODESIZE(Op.SLOAD(created_slot))) + + Op.STOP + ) + + code_address = pre.deploy_contract(code, storage=storage.canary()) + created_address = compute_create_address( + address=code_address, + nonce=1, + salt=0, + initcode=initcode, + opcode=opcode, + ) + storage[created_slot] = created_address + + tx = Transaction( + sender=pre.fund_eoa(), + to=code_address, + gas_limit=400_000, + ) + + state_test( + pre=pre, + post={ + code_address: Account(storage=storage), + created_address: Account(nonce=1, code=deployed_code), + }, + tx=tx, + ) diff --git a/tests/frontier/validation/test_header.py b/tests/frontier/validation/test_header.py index fd1adb89317..e8d590e7241 100644 --- a/tests/frontier/validation/test_header.py +++ b/tests/frontier/validation/test_header.py @@ -1,6 +1,7 @@ """Test the block header validations applied from Frontier.""" import pytest +from execution_testing import Fork from execution_testing.base_types.base_types import ZeroPaddedHexNumber from execution_testing.base_types.composite_types import Alloc from execution_testing.exceptions.exceptions import BlockException @@ -18,7 +19,14 @@ pytest.param(0, marks=pytest.mark.exception_test), pytest.param(1, marks=pytest.mark.exception_test), pytest.param(4999, marks=pytest.mark.exception_test), - 5000, + pytest.param(5000, marks=pytest.mark.valid_until("Osaka")), + pytest.param( + 5000, + marks=[ + pytest.mark.valid_from("Amsterdam"), + pytest.mark.exception_test, + ], + ), ], ) def test_gas_limit_below_minimum( @@ -26,6 +34,7 @@ def test_gas_limit_below_minimum( pre: Alloc, gas_limit: int, env: Environment, + fork: Fork, ) -> None: """ Tests that a block with a gas limit below the minimum throws an error. @@ -33,12 +42,12 @@ def test_gas_limit_below_minimum( modified_fields = {"gas_limit": gas_limit} env.gas_limit = ZeroPaddedHexNumber(5000) - block = Block( - txs=[], - rlp_modifier=Header(**modified_fields), - exception=BlockException.INVALID_GASLIMIT - if gas_limit < 5000 - else None, - ) + block = Block(txs=[]) + + if gas_limit < 5000: + block.rlp_modifier = Header(**modified_fields) + block.exception = BlockException.INVALID_GASLIMIT + elif fork.header_bal_hash_required(): + block.exception = BlockException.BLOCK_ACCESS_LIST_GAS_LIMIT_EXCEEDED blockchain_test(pre=pre, post={}, blocks=[block], genesis_environment=env) diff --git a/tests/static/state_tests/stExtCodeHash/createEmptyThenExtcodehashFiller.json b/tests/static/state_tests/stExtCodeHash/createEmptyThenExtcodehashFiller.json deleted file mode 100644 index a61270473bc..00000000000 --- a/tests/static/state_tests/stExtCodeHash/createEmptyThenExtcodehashFiller.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "createEmptyThenExtcodehash" : { - "_info" : { - "comment" : "https://github.com/ethereum/tests/issues/652" - }, - "env" : { - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x20000", - "currentGasLimit" : "0x0b00000000", - "currentNumber" : "0x01", - "currentTimestamp" : "0x03e8" - }, - "expect" : [ - { "indexes" : { - "data" : -1, - "gas" : -1, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "1000000000000000000000000000000000000000" : { - "storage" : { - "0x00" : "0x0826562ac9373818f7a055166f7b0cc87485f05d", - "0x01" : "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "0x02" : "0x7c5a2c91b22d7a9226523d4ba717db6afb741ebd", - "0x03" : "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" - } - }, - "0x0826562ac9373818f7a055166f7b0cc87485f05d" : { - "nonce" : "1", - "code" : "" - } - } - } - ], - "pre" : { - "1000000000000000000000000000000000000000" : { - "balance" : "0x00", - "code" : "{ [[0]] (CREATE2 0 0 (lll (seq (sstore 0 0x112233) (STOP)) 0) 0) [[1]] (EXTCODEHASH 0x0826562ac9373818f7a055166f7b0cc87485f05d) [[2]] (CREATE 0 0 (lll (seq (sstore 0 0x112233) (STOP)) 0)) [[3]] (EXTCODEHASH 0x7c5a2c91b22d7a9226523d4ba717db6afb741ebd) }", - "nonce" : "0x00", - "storage" : { - "0x00" : "0x01", - "0x01" : "0x01", - "0x02" : "0x01", - "0x03" : "0x01" - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x6400000000", - "code" : "", - "nonce" : "0x00", - "storage" : { - } - } - }, - "transaction" : { - "data" : [ - "" - ], - "gasLimit" : [ - "300000" - ], - "gasPrice" : "0x0a", - "nonce" : "0x00", - "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "0x1000000000000000000000000000000000000000", - "value" : [ - "0" - ] - } - } -} diff --git a/tests/static/state_tests/stExtCodeHash/extCodeHashNewAccountFiller.json b/tests/static/state_tests/stExtCodeHash/extCodeHashNewAccountFiller.json deleted file mode 100644 index 75e395ecf8f..00000000000 --- a/tests/static/state_tests/stExtCodeHash/extCodeHashNewAccountFiller.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "extCodeHashNewAccount": { - "_info": { - "comment": "EXTCODEHASH/EXTCODESIZE of an account created in same transaction" - }, - "env": { - "currentCoinbase": "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty": "0x20000", - "currentGasLimit": "1000000", - "currentNumber": "1", - "currentTimestamp": "1000" - }, - "expect": [ - { - "indexes": { - "data": -1, - "gas": -1, - "value": -1 - }, - "network": [ - ">=Cancun" - ], - "result": { - "0x75e23f851ce92ee62896c1fb1127d4be2c53f59d": { - "code": "0x0000000000000000000000000000000000000000000000000000000000001234", - "nonce": "0x01", - "storage": { - } - }, - "deadbeef00000000000000000000000000000000": { - "storage": { - "0x00": "0xe321d900f3fd366734e2d071e30949ded20c27fd638f1a059390091c643b62c5", - "0x01": "0x20" - } - } - } - } - ], - "pre": { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "1000000000000000000", - "code": "", - "nonce": "0", - "storage": { - } - }, - "deadbeef00000000000000000000000000000000": { - "balance": "1000000000000000000", - "code": "{ (MSTORE 0 (CREATE2 0 0 (lll {(MSTORE 0 0x1234) (RETURN 0 32)} 0) 0x10)) [[0]] (EXTCODEHASH (MLOAD 0)) [[1]] (EXTCODESIZE (MLOAD 0)) (STOP)}", - "nonce": "0", - "storage": { - } - } - }, - "transaction": { - "data": [ - "" - ], - "gasLimit": [ - "400000" - ], - "gasPrice": "10", - "nonce": "0", - "secretKey": "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to": "deadbeef00000000000000000000000000000000", - "value": [ - "1" - ] - } - } -} diff --git a/tests/static/state_tests/stStaticCall/static_InternalCallHittingGasLimitFiller.json b/tests/static/state_tests/stStaticCall/static_InternalCallHittingGasLimitFiller.json index 10831860c47..4c5ade17f85 100644 --- a/tests/static/state_tests/stStaticCall/static_InternalCallHittingGasLimitFiller.json +++ b/tests/static/state_tests/stStaticCall/static_InternalCallHittingGasLimitFiller.json @@ -3,7 +3,7 @@ "env" : { "currentCoinbase" : "2adf5374fce5edbc8e2a8697c15331677e6ebf0b", "currentDifficulty" : "0x020000", - "currentGasLimit" : "22000", + "currentGasLimit" : "100000", "currentNumber" : "1", "currentTimestamp" : "1000" }, diff --git a/tests/static/state_tests/stTransactionTest/InternalCallHittingGasLimitFiller.json b/tests/static/state_tests/stTransactionTest/InternalCallHittingGasLimitFiller.json index ded51571395..726f144c16d 100644 --- a/tests/static/state_tests/stTransactionTest/InternalCallHittingGasLimitFiller.json +++ b/tests/static/state_tests/stTransactionTest/InternalCallHittingGasLimitFiller.json @@ -3,7 +3,7 @@ "env" : { "currentCoinbase" : "2adf5374fce5edbc8e2a8697c15331677e6ebf0b", "currentDifficulty" : "0x020000", - "currentGasLimit" : "22000", + "currentGasLimit" : "100000", "currentNumber" : "1", "currentTimestamp" : "1000" },