In the end, get_merkle_root is back

This commit is contained in:
Hsiao-Wei Wang
2019-06-29 02:16:16 +08:00
parent 2252142e01
commit 4dc526fbb7
6 changed files with 59 additions and 24 deletions

View File

@@ -11,7 +11,8 @@ from typing import (
)
PHASE0_IMPORTS = '''from typing import (
PHASE0_IMPORTS = '''from math import log2
from typing import (
Any, Callable, Dict, Set, Sequence, Tuple,
)
@@ -36,7 +37,8 @@ from eth2spec.utils.bls import (
from eth2spec.utils.hash_function import hash
'''
PHASE1_IMPORTS = '''from typing import (
PHASE1_IMPORTS = '''from math import log2
from typing import (
Any, Callable, Dict, Optional, Set, Sequence, MutableSequence, Tuple,
)

View File

@@ -51,6 +51,8 @@
- [`hash`](#hash)
- [`hash_tree_root`](#hash_tree_root)
- [`signing_root`](#signing_root)
- [`calc_merkle_tree_from_leaves`](#calc_merkle_tree_from_leaves)
- [`get_merkle_root`](#get_merkle_root)
- [`bls_domain`](#bls_domain)
- [`slot_to_epoch`](#slot_to_epoch)
- [`get_previous_epoch`](#get_previous_epoch)
@@ -558,6 +560,33 @@ The `hash` function is SHA256.
`def signing_root(object: Container) -> Hash` is a function for computing signing messages, as defined in the [SimpleSerialize spec](../simple-serialize.md#self-signed-containers).
### `calc_merkle_tree_from_leaves`
```python
zerohashes = [ZERO_HASH]
for layer in range(1, 100):
zerohashes.append(hash(zerohashes[layer - 1] + zerohashes[layer - 1]))
def calc_merkle_tree_from_leaves(values: Sequence[Hash], layer_count: int=32) -> Sequence[Sequence[Hash]]:
values = list(values)
tree = [values[::]]
for h in range(layer_count):
if len(values) % 2 == 1:
values.append(zerohashes[h])
values = [hash(values[i] + values[i + 1]) for i in range(0, len(values), 2)]
tree.append(values[::])
return tree
```
### `get_merkle_root`
```python
def get_merkle_root(values: Sequence[Hash], pad_to: int=1) -> Hash:
layer_count = int(log2(pad_to))
if len(values) == 0:
return zerohashes[layer_count]
return calc_merkle_tree_from_leaves(values, layer_count)[-1][0]
```
### `bls_domain`
```python
@@ -1144,10 +1173,10 @@ def is_genesis_trigger(deposits: List[Deposit, 2**DEPOSIT_CONTRACT_TREE_DEPTH],
# Process deposits
state = BeaconState()
for i, deposit in enumerate(deposits):
state.eth1_data.deposit_root = hash_tree_root(
Vector[DepositData, len(deposits)](list(map(lambda deposit: deposit.data, deposits[:i])))
)
for deposit_index, deposit in enumerate(deposits):
leaves = [hash_tree_root(d.data) for d in deposits[:deposit_index + 1]]
state.eth1_data.deposit_root = get_merkle_root(leaves, 2**DEPOSIT_CONTRACT_TREE_DEPTH)
state.eth1_deposit_index = deposit_index
process_deposit(state, deposit)
# Count active validators at genesis
@@ -1173,9 +1202,14 @@ def get_genesis_beacon_state(deposits: Sequence[Deposit], genesis_time: int, eth
)
# Process genesis deposits
for deposit in deposits:
for deposit_index, deposit in enumerate(deposits):
leaves = [hash_tree_root(d.data) for d in deposits[:deposit_index + 1]]
state.eth1_data.deposit_root = get_merkle_root(leaves, 2**DEPOSIT_CONTRACT_TREE_DEPTH)
state.eth1_deposit_index = deposit_index
process_deposit(state, deposit)
assert state.eth1_data.deposit_root == eth1_data.deposit_root
# Process genesis activations
for validator in state.validators:
if validator.effective_balance == MAX_EFFECTIVE_BALANCE:

View File

@@ -8,12 +8,11 @@ from eth2spec.test.helpers.deposits import (
@spectest_with_bls_switch
def test_is_genesis_trigger_false(spec):
deposit_count = 2
genesis_deposits, deposit_root = prepare_genesis_deposits(spec, deposit_count, spec.MAX_EFFECTIVE_BALANCE)
genesis_deposits, _ = prepare_genesis_deposits(spec, deposit_count, spec.MAX_EFFECTIVE_BALANCE)
genesis_time = 1546300800
yield "deposits", genesis_deposits
yield "time", genesis_time
yield "deposit_root", deposit_root
is_triggered = spec.is_genesis_trigger(genesis_deposits, genesis_time)
assert is_triggered is False
@@ -25,13 +24,12 @@ def test_is_genesis_trigger_false(spec):
@spectest_with_bls_switch
def test_is_genesis_trigger_true(spec):
deposit_count = spec.GENESIS_ACTIVE_VALIDATOR_COUNT
genesis_deposits, deposit_root = prepare_genesis_deposits(spec, deposit_count, spec.MAX_EFFECTIVE_BALANCE)
genesis_deposits, _ = prepare_genesis_deposits(spec, deposit_count, spec.MAX_EFFECTIVE_BALANCE)
SECONDS_PER_DAY = 86400
genesis_time = 1578009600 - 2 * SECONDS_PER_DAY
yield "deposits", genesis_deposits
yield "time", genesis_time
yield "deposit_root", deposit_root
is_triggered = spec.is_genesis_trigger(genesis_deposits, genesis_time)
assert is_triggered is True
@@ -43,11 +41,10 @@ def test_is_genesis_trigger_true(spec):
@spectest_with_bls_switch
def test_is_genesis_trigger_not_enough_balance(spec):
deposit_count = spec.GENESIS_ACTIVE_VALIDATOR_COUNT
genesis_deposits, deposit_root = prepare_genesis_deposits(spec, deposit_count, spec.MAX_EFFECTIVE_BALANCE - 1)
genesis_deposits, _ = prepare_genesis_deposits(spec, deposit_count, spec.MAX_EFFECTIVE_BALANCE - 1)
genesis_time = 1546300800
yield "deposits", genesis_deposits
yield "time", genesis_time
yield "deposit_root", deposit_root
is_triggered = spec.is_genesis_trigger(genesis_deposits, genesis_time)
assert is_triggered is False

View File

@@ -41,7 +41,9 @@ def build_deposit(spec,
amount,
withdrawal_credentials,
signed):
deposit_data = build_deposit_data(spec, pubkey, privkey, amount, withdrawal_credentials, state=state, signed=signed)
deposit_data = build_deposit_data(
spec, pubkey, privkey, amount, withdrawal_credentials, state=state, signed=signed,
)
item = deposit_data.hash_tree_root()
index = len(deposit_data_leaves)
@@ -63,6 +65,7 @@ def build_deposit(spec,
def prepare_genesis_deposits(spec, genesis_validator_count, amount, signed=False):
genesis_deposit_data_list = []
deposit_data_leaves = []
genesis_deposits = []
for validator_index in range(genesis_validator_count):
pubkey = pubkeys[validator_index]
privkey = privkeys[validator_index]
@@ -79,13 +82,11 @@ def prepare_genesis_deposits(spec, genesis_validator_count, amount, signed=False
deposit_data_leaves.append(item)
genesis_deposit_data_list.append(deposit_data)
tree = calc_merkle_tree_from_leaves(tuple(deposit_data_leaves))
root = get_merkle_root((tuple(deposit_data_leaves)))
genesis_deposits = list(
spec.Deposit(proof=list(get_merkle_proof(tree, item_index=index)), data=deposit_data)
for index, deposit_data in enumerate(genesis_deposit_data_list)
)
tree = calc_merkle_tree_from_leaves(tuple(deposit_data_leaves))
root = get_merkle_root((tuple(deposit_data_leaves)), 2**32)
genesis_deposits.append(
spec.Deposit(proof=list(get_merkle_proof(tree, item_index=validator_index)), data=deposit_data)
)
return genesis_deposits, root

View File

@@ -1,5 +1,5 @@
from .hash_function import hash
from math import log2
from math import log2
ZERO_BYTES32 = b'\x00' * 32

View File

@@ -1,5 +1,5 @@
import pytest
from .merkle_minimal import zerohashes, merkleize_chunks
from .merkle_minimal import zerohashes, merkleize_chunks, get_merkle_root
from .hash_function import hash
@@ -53,6 +53,7 @@ cases = [
'depth,count,pow2,value',
cases,
)
def test_merkleize_chunks(depth, count, pow2, value):
def test_merkleize_chunks_and_get_merkle_root(depth, count, pow2, value):
chunks = [e(i) for i in range(count)]
assert merkleize_chunks(chunks, pad_to=pow2) == value
assert get_merkle_root(chunks, pad_to=pow2) == value