Merge in `dev`
This commit is contained in:
commit
cb71409114
|
@ -7,7 +7,7 @@ A BLS compressed-hash to G2.
|
|||
```yaml
|
||||
input:
|
||||
message: bytes32,
|
||||
domain: bytes -- any number
|
||||
domain: uint64 -- the BLS domain
|
||||
output: List[bytes48] -- length of two
|
||||
```
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ A BLS uncompressed-hash to G2.
|
|||
|
||||
```yaml
|
||||
input:
|
||||
message: bytes32,
|
||||
domain: bytes -- any number
|
||||
message: bytes32
|
||||
domain: uint64 -- the BLS domain
|
||||
output: List[List[bytes48]] -- 3 lists, each a length of two
|
||||
```
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ Message signing with BLS should produce a signature.
|
|||
input:
|
||||
privkey: bytes32 -- the private key used for signing
|
||||
message: bytes32 -- input message to sign (a hash)
|
||||
domain: bytes -- BLS domain
|
||||
domain: uint64 -- the BLS domain
|
||||
output: bytes96 -- expected signature
|
||||
```
|
||||
|
||||
|
|
|
@ -17,13 +17,17 @@ post: BeaconState -- state after applying the epoch sub-transition.
|
|||
## Condition
|
||||
|
||||
A handler of the `epoch_processing` test-runner should process these cases,
|
||||
calling the corresponding processing implementation.
|
||||
calling the corresponding processing implementation (same name, prefixed with `process_`).
|
||||
This excludes the other parts of the epoch-transition.
|
||||
The provided pre-state is already transitioned to just before the specific sub-transition of focus of the handler.
|
||||
|
||||
Sub-transitions:
|
||||
|
||||
| *`sub-transition-name`* | *`processing call`* |
|
||||
|-------------------------|-----------------------------------|
|
||||
| `crosslinks` | `process_crosslinks(state)` |
|
||||
| `registry_updates` | `process_registry_updates(state)` |
|
||||
- `justification_and_finalization`
|
||||
- `crosslinks`
|
||||
- *`rewards_and_penalties` - planned testing extension*
|
||||
- `registry_updates`
|
||||
- `slashings`
|
||||
- `final_updates`
|
||||
|
||||
The resulting state should match the expected `post` state.
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# Genesis tests
|
||||
|
||||
The aim of the genesis tests is to provide a baseline to test genesis-state initialization and test
|
||||
if the proposed genesis-validity conditions are working.
|
||||
|
||||
There are two handlers, documented individually:
|
||||
- [`validity`](./validity.md): Tests if a genesis state is valid, i.e. if it counts as trigger to launch.
|
||||
- [`initialization`](./initialization.md): Tests the initialization of a genesis state based on Eth1 data.
|
|
@ -0,0 +1,22 @@
|
|||
# Genesis creation testing
|
||||
|
||||
Tests the initialization of a genesis state based on Eth1 data.
|
||||
|
||||
## Test case format
|
||||
|
||||
```yaml
|
||||
description: string -- description of test case, purely for debugging purposes
|
||||
bls_setting: int -- see general test-format spec.
|
||||
eth1_block_hash: Bytes32 -- the root of the Eth-1 block, hex encoded, with prefix 0x
|
||||
eth1_timestamp: int -- the timestamp of the block, in seconds.
|
||||
deposits: [Deposit] -- list of deposits to build the genesis state with
|
||||
state: BeaconState -- the expected genesis state.
|
||||
```
|
||||
|
||||
To process this test, build a genesis state with the provided `eth1_block_hash`, `eth1_timestamp` and `deposits`:
|
||||
`initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)`,
|
||||
as described in the Beacon Chain specification.
|
||||
|
||||
## Condition
|
||||
|
||||
The resulting state should match the expected `state`.
|
|
@ -0,0 +1,19 @@
|
|||
# Genesis validity testing
|
||||
|
||||
Tests if a genesis state is valid, i.e. if it counts as trigger to launch.
|
||||
|
||||
## Test case format
|
||||
|
||||
```yaml
|
||||
description: string -- description of test case, purely for debugging purposes
|
||||
bls_setting: int -- see general test-format spec.
|
||||
genesis: BeaconState -- state to validate.
|
||||
is_valid: bool -- true if the genesis state is deemed valid as to launch with, false otherwise.
|
||||
```
|
||||
|
||||
To process the data, call `is_valid_genesis_state(genesis)`.
|
||||
|
||||
|
||||
## Condition
|
||||
|
||||
The result of calling `is_valid_genesis_state(genesis)` should match the expected `is_valid` boolean.
|
|
@ -16,13 +16,14 @@ post: BeaconState -- state after applying the operation. No
|
|||
|
||||
A handler of the `operations` test-runner should process these cases,
|
||||
calling the corresponding processing implementation.
|
||||
This excludes the other parts of the block-transition.
|
||||
|
||||
Operations:
|
||||
|
||||
| *`operation-name`* | *`operation-object`* | *`input name`* | *`processing call`* |
|
||||
|-------------------------|----------------------|----------------------|--------------------------------------------------------|
|
||||
| `attestation` | `Attestation` | `attestation` | `process_attestation(state, attestation)` |
|
||||
| `attester_slashing` | `AttesterSlashing` | `attester_slashing` | `process_attester_slashing(state, attester_slashing)` |
|
||||
| `attestation` | `Attestation` | `attestation` | `process_attestation(state, attestation)` |
|
||||
| `attester_slashing` | `AttesterSlashing` | `attester_slashing` | `process_attester_slashing(state, attester_slashing)` |
|
||||
| `block_header` | `Block` | `block` | `process_block_header(state, block)` |
|
||||
| `deposit` | `Deposit` | `deposit` | `process_deposit(state, deposit)` |
|
||||
| `proposer_slashing` | `ProposerSlashing` | `proposer_slashing` | `process_proposer_slashing(state, proposer_slashing)` |
|
||||
|
|
|
@ -12,11 +12,10 @@ slots: N -- amount of slots to process, N being a positive number.
|
|||
post: BeaconState -- state after applying all the transitions.
|
||||
```
|
||||
|
||||
The transition with pure time, no blocks, is known as `state_transition_to(state, slot)` in the spec.
|
||||
The transition with pure time, no blocks, is known as `process_slots(state, slot)` in the spec.
|
||||
This runs state-caching (pure slot transition) and epoch processing (every E slots).
|
||||
|
||||
To process the data, call `state_transition_to(pre, pre.slot + N)`. And see if `pre` mutated into the equivalent of `post`.
|
||||
|
||||
To process the data, call `process_slots(pre, pre.slot + N)`.
|
||||
|
||||
## Condition
|
||||
|
||||
|
|
|
@ -27,9 +27,6 @@ def hex_to_int(x: str) -> int:
|
|||
return int(x, 16)
|
||||
|
||||
|
||||
# Note: even though a domain is only an uint64,
|
||||
# To avoid issues with YAML parsers that are limited to 53-bit (JS language limit)
|
||||
# It is serialized as an hex string as well.
|
||||
DOMAINS = [
|
||||
0,
|
||||
1,
|
||||
|
@ -92,7 +89,7 @@ def case01_message_hash_G2_uncompressed():
|
|||
yield {
|
||||
'input': {
|
||||
'message': '0x' + msg.hex(),
|
||||
'domain': int_to_hex(domain)
|
||||
'domain': domain
|
||||
},
|
||||
'output': hash_message(msg, domain)
|
||||
}
|
||||
|
@ -104,7 +101,7 @@ def case02_message_hash_G2_compressed():
|
|||
yield {
|
||||
'input': {
|
||||
'message': '0x' + msg.hex(),
|
||||
'domain': int_to_hex(domain)
|
||||
'domain': domain
|
||||
},
|
||||
'output': hash_message_compressed(msg, domain)
|
||||
}
|
||||
|
@ -129,7 +126,7 @@ def case04_sign_messages():
|
|||
'input': {
|
||||
'privkey': int_to_hex(privkey),
|
||||
'message': '0x' + message.hex(),
|
||||
'domain': int_to_hex(domain)
|
||||
'domain': domain
|
||||
},
|
||||
'output': '0x' + sig.hex()
|
||||
}
|
||||
|
|
|
@ -4,7 +4,10 @@ from eth2spec.phase0 import spec as spec_phase0
|
|||
from eth2spec.phase1 import spec as spec_phase1
|
||||
from eth2spec.test.phase_0.epoch_processing import (
|
||||
test_process_crosslinks,
|
||||
test_process_registry_updates
|
||||
test_process_final_updates,
|
||||
test_process_justification_and_finalization,
|
||||
test_process_registry_updates,
|
||||
test_process_slashings
|
||||
)
|
||||
from gen_base import gen_runner, gen_suite, gen_typing
|
||||
from gen_from_tests.gen import generate_from_tests
|
||||
|
@ -35,8 +38,16 @@ if __name__ == "__main__":
|
|||
gen_runner.run_generator("epoch_processing", [
|
||||
create_suite('crosslinks', 'minimal', lambda: generate_from_tests(test_process_crosslinks, 'phase0')),
|
||||
create_suite('crosslinks', 'mainnet', lambda: generate_from_tests(test_process_crosslinks, 'phase0')),
|
||||
create_suite('final_updates', 'minimal', lambda: generate_from_tests(test_process_final_updates, 'phase0')),
|
||||
create_suite('final_updates', 'mainnet', lambda: generate_from_tests(test_process_final_updates, 'phase0')),
|
||||
create_suite('justification_and_finalization', 'minimal',
|
||||
lambda: generate_from_tests(test_process_justification_and_finalization, 'phase0')),
|
||||
create_suite('justification_and_finalization', 'mainnet',
|
||||
lambda: generate_from_tests(test_process_justification_and_finalization, 'phase0')),
|
||||
create_suite('registry_updates', 'minimal',
|
||||
lambda: generate_from_tests(test_process_registry_updates, 'phase0')),
|
||||
create_suite('registry_updates', 'mainnet',
|
||||
lambda: generate_from_tests(test_process_registry_updates, 'phase0')),
|
||||
create_suite('slashings', 'minimal', lambda: generate_from_tests(test_process_slashings, 'phase0')),
|
||||
create_suite('slashings', 'mainnet', lambda: generate_from_tests(test_process_slashings, 'phase0')),
|
||||
])
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# Genesis test generator
|
||||
|
||||
Genesis tests cover the initialization and validity-based launch trigger for the Beacon Chain genesis state.
|
||||
|
||||
Information on the format of the tests can be found in the [genesis test formats documentation](../../specs/test_formats/genesis/README.md).
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
from typing import Callable, Iterable
|
||||
|
||||
from eth2spec.test.genesis import test_initialization, test_validity
|
||||
|
||||
from gen_base import gen_runner, gen_suite, gen_typing
|
||||
from gen_from_tests.gen import generate_from_tests
|
||||
from preset_loader import loader
|
||||
from eth2spec.phase0 import spec as spec
|
||||
|
||||
|
||||
def create_suite(handler_name: str, config_name: str, get_cases: Callable[[], Iterable[gen_typing.TestCase]]) \
|
||||
-> Callable[[str], gen_typing.TestSuiteOutput]:
|
||||
def suite_definition(configs_path: str) -> gen_typing.TestSuiteOutput:
|
||||
presets = loader.load_presets(configs_path, config_name)
|
||||
spec.apply_constants_preset(presets)
|
||||
|
||||
return ("genesis_%s_%s" % (handler_name, config_name), handler_name, gen_suite.render_suite(
|
||||
title="genesis testing",
|
||||
summary="Genesis test suite, %s type, generated from pytests" % handler_name,
|
||||
forks_timeline="testing",
|
||||
forks=["phase0"],
|
||||
config=config_name,
|
||||
runner="genesis",
|
||||
handler=handler_name,
|
||||
test_cases=get_cases()))
|
||||
return suite_definition
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
gen_runner.run_generator("genesis", [
|
||||
create_suite('initialization', 'minimal', lambda: generate_from_tests(test_initialization, 'phase0')),
|
||||
create_suite('validity', 'minimal', lambda: generate_from_tests(test_validity, 'phase0')),
|
||||
])
|
|
@ -0,0 +1,4 @@
|
|||
eth-utils==1.6.0
|
||||
../../test_libs/gen_helpers
|
||||
../../test_libs/config_helpers
|
||||
../../test_libs/pyspec
|
|
@ -49,7 +49,9 @@ if __name__ == "__main__":
|
|||
create_suite('proposer_slashing', 'minimal', lambda: generate_from_tests(test_process_proposer_slashing, 'phase0')),
|
||||
create_suite('proposer_slashing', 'mainnet', lambda: generate_from_tests(test_process_proposer_slashing, 'phase0')),
|
||||
create_suite('transfer', 'minimal', lambda: generate_from_tests(test_process_transfer, 'phase0')),
|
||||
create_suite('transfer', 'mainnet', lambda: generate_from_tests(test_process_transfer, 'phase0')),
|
||||
# Disabled, due to the high amount of different transfer tests, this produces a shocking size of tests.
|
||||
# Unnecessarily, as transfer are disabled currently, so not a priority.
|
||||
# create_suite('transfer', 'mainnet', lambda: generate_from_tests(test_process_transfer, 'phase0')),
|
||||
create_suite('voluntary_exit', 'minimal', lambda: generate_from_tests(test_process_voluntary_exit, 'phase0')),
|
||||
create_suite('voluntary_exit', 'mainnet', lambda: generate_from_tests(test_process_voluntary_exit, 'phase0')),
|
||||
])
|
||||
|
|
|
@ -10,7 +10,7 @@ from preset_loader import loader
|
|||
def shuffling_case(seed, count):
|
||||
yield 'seed', '0x' + seed.hex()
|
||||
yield 'count', count
|
||||
yield 'shuffled', [spec.compute_shuffled_index(i, count, seed) for i in range(count)]
|
||||
yield 'shuffled', [int(spec.compute_shuffled_index(i, count, seed)) for i in range(count)]
|
||||
|
||||
|
||||
@to_tuple
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||
from eth2spec.utils.ssz.ssz_typing import (
|
||||
SSZValue, uint, Container, boolean
|
||||
uint, Container, boolean
|
||||
)
|
||||
|
||||
|
||||
def encode(value: SSZValue, include_hash_tree_roots=False):
|
||||
def encode(value, include_hash_tree_roots=False):
|
||||
if isinstance(value, uint):
|
||||
# Larger uints are boxed and the class declares their byte length
|
||||
if value.type().byte_len > 8:
|
||||
|
|
|
@ -16,13 +16,13 @@ def create_valid_beacon_state(spec):
|
|||
def run_is_valid_genesis_state(spec, state, valid=True):
|
||||
"""
|
||||
Run ``is_valid_genesis_state``, yielding:
|
||||
- state ('state')
|
||||
- genesis ('state')
|
||||
- is_valid ('is_valid')
|
||||
If ``valid == False``, run expecting ``AssertionError``
|
||||
"""
|
||||
yield state
|
||||
yield 'genesis', state
|
||||
is_valid = spec.is_valid_genesis_state(state)
|
||||
yield 'is_valid', is_valid
|
||||
assert is_valid == valid
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
||||
|
@ -39,7 +39,7 @@ def test_is_valid_genesis_state_false_invalid_timestamp(spec):
|
|||
state = create_valid_beacon_state(spec)
|
||||
state.genesis_time = spec.MIN_GENESIS_TIME - 1
|
||||
|
||||
yield from run_is_valid_genesis_state(spec, state, valid=True)
|
||||
yield from run_is_valid_genesis_state(spec, state, valid=False)
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
||||
|
@ -51,13 +51,14 @@ def test_is_valid_genesis_state_true_more_balance(spec):
|
|||
yield from run_is_valid_genesis_state(spec, state, valid=True)
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
||||
@spectest_with_bls_switch
|
||||
def test_is_valid_genesis_state_false_not_enough_balance(spec):
|
||||
state = create_valid_beacon_state(spec)
|
||||
state.validators[0].effective_balance = spec.MAX_EFFECTIVE_BALANCE - 1
|
||||
|
||||
yield from run_is_valid_genesis_state(spec, state, valid=False)
|
||||
# TODO: not part of the genesis function yet. Erroneously merged.
|
||||
# @with_phases(['phase0'])
|
||||
# @spectest_with_bls_switch
|
||||
# def test_is_valid_genesis_state_false_not_enough_balance(spec):
|
||||
# state = create_valid_beacon_state(spec)
|
||||
# state.validators[0].effective_balance = spec.MAX_EFFECTIVE_BALANCE - 1
|
||||
#
|
||||
# yield from run_is_valid_genesis_state(spec, state, valid=False)
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
|
@ -1,6 +1,7 @@
|
|||
from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases, with_phases
|
||||
from eth2spec.test.helpers.attestations import (
|
||||
get_valid_attestation,
|
||||
sign_aggregate_attestation,
|
||||
sign_attestation,
|
||||
)
|
||||
from eth2spec.test.helpers.state import (
|
||||
|
@ -59,6 +60,7 @@ def test_success(spec, state):
|
|||
@spec_state_test
|
||||
def test_success_previous_epoch(spec, state):
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
state.slot = spec.SLOTS_PER_EPOCH - 1
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
|
@ -68,6 +70,9 @@ def test_success_previous_epoch(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_success_since_max_epochs_per_crosslink(spec, state):
|
||||
# Do not run mainnet (64 epochs), that would mean the equivalent of ~7 hours chain simulation.
|
||||
if spec.MAX_EPOCHS_PER_CROSSLINK > 4:
|
||||
return
|
||||
for _ in range(spec.MAX_EPOCHS_PER_CROSSLINK + 2):
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
@ -87,6 +92,9 @@ def test_success_since_max_epochs_per_crosslink(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_wrong_end_epoch_with_max_epochs_per_crosslink(spec, state):
|
||||
# Do not run mainnet (64 epochs), that would mean the equivalent of ~7 hours chain simulation.
|
||||
if spec.MAX_EPOCHS_PER_CROSSLINK > 4:
|
||||
return
|
||||
for _ in range(spec.MAX_EPOCHS_PER_CROSSLINK + 2):
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
@ -130,8 +138,9 @@ def test_before_inclusion_delay(spec, state):
|
|||
@spec_state_test
|
||||
def test_after_epoch_slots(spec, state):
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
state.slot = spec.SLOTS_PER_EPOCH - 1
|
||||
# increment past latest inclusion slot
|
||||
spec.process_slots(state, state.slot + spec.SLOTS_PER_EPOCH + 1)
|
||||
spec.process_slots(state, state.slot + 2)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
yield from run_attestation_processing(spec, state, attestation, False)
|
||||
|
@ -203,10 +212,17 @@ def test_future_target_epoch(spec, state):
|
|||
|
||||
attestation = get_valid_attestation(spec, state)
|
||||
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
participants = spec.get_attesting_indices(
|
||||
state,
|
||||
attestation.data,
|
||||
attestation.aggregation_bits
|
||||
)
|
||||
attestation.data.target.epoch = spec.get_current_epoch(state) + 1 # target epoch will be too new to handle
|
||||
sign_attestation(spec, state, attestation)
|
||||
|
||||
# manually add signature for correct participants
|
||||
attestation.signature = sign_aggregate_attestation(spec, state, attestation.data, participants)
|
||||
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
yield from run_attestation_processing(spec, state, attestation, False)
|
||||
|
||||
|
@ -290,15 +306,17 @@ def test_non_zero_crosslink_data_root(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_bad_parent_crosslink(spec, state):
|
||||
state.slot = spec.SLOTS_PER_EPOCH - 1
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
attestation = get_valid_attestation(spec, state, signed=False)
|
||||
for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY):
|
||||
next_slot(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
attestation.data.crosslink.parent_root = b'\x27' * 32
|
||||
sign_attestation(spec, state, attestation)
|
||||
|
||||
yield from run_attestation_processing(spec, state, attestation, False)
|
||||
|
||||
|
@ -306,15 +324,17 @@ def test_bad_parent_crosslink(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_bad_crosslink_start_epoch(spec, state):
|
||||
state.slot = spec.SLOTS_PER_EPOCH - 1
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
attestation = get_valid_attestation(spec, state, signed=False)
|
||||
for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY):
|
||||
next_slot(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
attestation.data.crosslink.start_epoch += 1
|
||||
sign_attestation(spec, state, attestation)
|
||||
|
||||
yield from run_attestation_processing(spec, state, attestation, False)
|
||||
|
||||
|
@ -322,15 +342,17 @@ def test_bad_crosslink_start_epoch(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_bad_crosslink_end_epoch(spec, state):
|
||||
state.slot = spec.SLOTS_PER_EPOCH - 1
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
attestation = get_valid_attestation(spec, state, signed=False)
|
||||
for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY):
|
||||
next_slot(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
attestation.data.crosslink.end_epoch += 1
|
||||
sign_attestation(spec, state, attestation)
|
||||
|
||||
yield from run_attestation_processing(spec, state, attestation, False)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from typing import Dict, Any, Callable, Iterable
|
||||
from eth2spec.debug.encode import encode
|
||||
from eth2spec.utils.ssz.ssz_typing import Container
|
||||
from eth2spec.utils.ssz.ssz_typing import SSZValue
|
||||
|
||||
|
||||
def spectest(description: str = None):
|
||||
|
@ -29,10 +29,12 @@ def spectest(description: str = None):
|
|||
(key, value, typ) = data
|
||||
out[key] = encode(value, typ)
|
||||
else:
|
||||
# Otherwise, try to infer the type, but keep it as-is if it's not a SSZ container.
|
||||
# Otherwise, try to infer the type, but keep it as-is if it's not a SSZ type or bytes.
|
||||
(key, value) = data
|
||||
if isinstance(value, Container):
|
||||
out[key] = encode(value, value.__class__)
|
||||
if isinstance(value, (SSZValue, bytes)):
|
||||
out[key] = encode(value)
|
||||
elif isinstance(value, list) and all([isinstance(el, (SSZValue, bytes)) for el in value]):
|
||||
out[key] = [encode(el) for el in value]
|
||||
else:
|
||||
# not a ssz value.
|
||||
# It could be vector or bytes still, but it is a rare case,
|
||||
|
|
Loading…
Reference in New Issue