Merge pull request #2726 from ethereum/get_pow_block_at_ttd-tests
Fix `get_pow_block_at_terminal_total_difficulty` and add unit tests
This commit is contained in:
commit
3c25da8218
|
@ -43,14 +43,15 @@ Please see related Beacon Chain doc before continuing and use them as a referenc
|
||||||
```python
|
```python
|
||||||
def get_pow_block_at_terminal_total_difficulty(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]:
|
def get_pow_block_at_terminal_total_difficulty(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]:
|
||||||
# `pow_chain` abstractly represents all blocks in the PoW chain
|
# `pow_chain` abstractly represents all blocks in the PoW chain
|
||||||
for block in pow_chain:
|
for block in pow_chain.values():
|
||||||
block_reached_ttd = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
block_reached_ttd = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
||||||
|
if block_reached_ttd:
|
||||||
# If genesis block, no parent exists so reaching TTD alone qualifies as valid terminal block
|
# If genesis block, no parent exists so reaching TTD alone qualifies as valid terminal block
|
||||||
if block_reached_ttd and block.parent_hash == Hash32():
|
if block.parent_hash == Hash32():
|
||||||
return block
|
return block
|
||||||
parent = pow_chain[block.parent_hash]
|
parent = pow_chain[block.parent_hash]
|
||||||
parent_reached_ttd = parent.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
parent_reached_ttd = parent.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
||||||
if block_reached_ttd and not parent_reached_ttd:
|
if not parent_reached_ttd:
|
||||||
return block
|
return block
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -15,6 +15,12 @@ class PowChain:
|
||||||
assert offset <= 0
|
assert offset <= 0
|
||||||
return self.blocks[offset - 1]
|
return self.blocks[offset - 1]
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {
|
||||||
|
block.block_hash: block
|
||||||
|
for block in self.blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def prepare_random_pow_block(spec, rng=Random(3131)):
|
def prepare_random_pow_block(spec, rng=Random(3131)):
|
||||||
return spec.PowBlock(
|
return spec.PowBlock(
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
from eth2spec.test.helpers.pow_block import (
|
||||||
|
prepare_random_pow_chain,
|
||||||
|
)
|
||||||
|
from eth2spec.test.context import (
|
||||||
|
spec_state_test,
|
||||||
|
with_merge_and_later,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# For test_get_pow_block_at_terminal_total_difficulty
|
||||||
|
IS_HEAD_BLOCK = 'is_head_block'
|
||||||
|
IS_HEAD_PARENT_BLOCK = 'is_head_parent_block'
|
||||||
|
|
||||||
|
# NOTE: The following parameter names are in the view of the head block (the second block)
|
||||||
|
# 'block_reached_ttd', 'block_parent_hash_is_empty', 'parent_reached_ttd', 'return_block'
|
||||||
|
expected_results = [
|
||||||
|
(False, False, False, None),
|
||||||
|
(False, False, True, IS_HEAD_PARENT_BLOCK),
|
||||||
|
(False, True, False, None),
|
||||||
|
(False, True, True, IS_HEAD_PARENT_BLOCK),
|
||||||
|
(True, False, False, IS_HEAD_BLOCK),
|
||||||
|
(True, False, True, IS_HEAD_PARENT_BLOCK),
|
||||||
|
(True, True, False, IS_HEAD_BLOCK),
|
||||||
|
(True, True, True, IS_HEAD_PARENT_BLOCK),
|
||||||
|
]
|
||||||
|
# NOTE: since the first block's `parent_hash` is set to `Hash32()` in test, if `parent_reached_ttd is True`,
|
||||||
|
# it would return the first block (IS_HEAD_PARENT_BLOCK).
|
||||||
|
|
||||||
|
|
||||||
|
@with_merge_and_later
|
||||||
|
@spec_state_test
|
||||||
|
def test_get_pow_block_at_terminal_total_difficulty(spec, state):
|
||||||
|
for result in expected_results:
|
||||||
|
(
|
||||||
|
block_reached_ttd,
|
||||||
|
block_parent_hash_is_empty,
|
||||||
|
parent_reached_ttd,
|
||||||
|
return_block
|
||||||
|
) = result
|
||||||
|
pow_chain = prepare_random_pow_chain(spec, 2)
|
||||||
|
pow_chain.head(-1).parent_hash = spec.Hash32()
|
||||||
|
|
||||||
|
if block_reached_ttd:
|
||||||
|
pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY
|
||||||
|
else:
|
||||||
|
pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - 1
|
||||||
|
|
||||||
|
if parent_reached_ttd:
|
||||||
|
pow_chain.head(-1).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY
|
||||||
|
else:
|
||||||
|
pow_chain.head(-1).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - 1
|
||||||
|
|
||||||
|
if block_parent_hash_is_empty:
|
||||||
|
pow_chain.head().parent_hash = spec.Hash32()
|
||||||
|
|
||||||
|
pow_block = spec.get_pow_block_at_terminal_total_difficulty(pow_chain.to_dict())
|
||||||
|
if return_block == IS_HEAD_BLOCK:
|
||||||
|
assert pow_block == pow_chain.head()
|
||||||
|
elif return_block == IS_HEAD_PARENT_BLOCK:
|
||||||
|
assert pow_block == pow_chain.head(-1)
|
||||||
|
elif return_block is None:
|
||||||
|
assert pow_block is None
|
||||||
|
else:
|
||||||
|
raise Exception('Something is wrong')
|
Loading…
Reference in New Issue