Revamp per block processing / state transition
This commit is contained in:
parent
0b560f7307
commit
14bb9b6efd
|
@ -11,22 +11,21 @@ import intsets, eth_common, math
|
|||
# ⚠ Spec is updated very often, implementation might quickly be outdated
|
||||
|
||||
type
|
||||
Keccak256_Digest* = Hash256 # TODO, previously Keccak256 fields used the "bytes" type
|
||||
Blake2_256_Digest* = Hash256 # while Blake2 used hash32, but latest spec changed everything to hash32
|
||||
Blake2_256_Digest* = Hash256 # TODO change to Blake2b-512[0 ..< 32] see https://github.com/status-im/nim-beacon-chain/issues/3
|
||||
Uint24* = range[0'u32 .. 0xFFFFFF'u32] # TODO: wrap-around
|
||||
|
||||
BeaconBlock* = object
|
||||
parent_hash*: Keccak256_Digest # Hash of the parent block
|
||||
parent_hash*: Blake2_256_Digest # Hash of the parent block
|
||||
slot_number*: int64 # Slot number (for the PoS mechanism)
|
||||
randao_reveal*: Keccak256_Digest # Randao commitment reveal
|
||||
randao_reveal*: Blake2_256_Digest # Randao commitment reveal
|
||||
attestations*: seq[AttestationRecord] # Attestation votes
|
||||
pow_chain_ref*: Keccak256_Digest # Reference to main chain block
|
||||
pow_chain_ref*: Blake2_256_Digest # Reference to main chain block
|
||||
active_state_root*: Blake2_256_Digest # Hash of the active state
|
||||
crystallized_state_root*: Blake2_256_Digest # Hash of the crystallized state
|
||||
|
||||
ActiveState* = object
|
||||
pending_attestations*: seq[AttestationRecord] # Attestations that have not yet been processed
|
||||
recent_block_hashes*: seq[Keccak256_Digest] # Most recent 2 * CYCLE_LENGTH block hashes, older to newer
|
||||
recent_block_hashes*: seq[Blake2_256_Digest] # Most recent 2 * CYCLE_LENGTH block hashes, older to newer
|
||||
|
||||
CrystallizedState* = object
|
||||
validators*: seq[ValidatorRecord] # List of active validators
|
||||
|
@ -42,7 +41,7 @@ type
|
|||
crosslinking_start_shard*: int16 # The next shard that cross-linking assignment will start from
|
||||
crosslink_records*: seq[CrosslinkRecord] # Records about the most recent crosslink for each shard
|
||||
total_deposits*: Int256 # Total balance of deposits
|
||||
dynasty_seed*: Keccak256_Digest # Used to select the committees for each shard
|
||||
dynasty_seed*: Blake2_256_Digest # Used to select the committees for each shard
|
||||
dynasty_seed_last_reset*: int64 # Last epoch the crosslink seed was reset
|
||||
|
||||
ShardAndCommittee* = object
|
||||
|
@ -53,14 +52,14 @@ type
|
|||
pubkey*: BLSPublicKey # The validator's public key
|
||||
withdrawal_shard*: int16 # What shard the validator's balance will be sent to after withdrawal
|
||||
withdrawal_address*: EthAddress # And what address
|
||||
randao_commitment*: Keccak256_Digest # The validator's current RANDAO beacon commitment
|
||||
randao_commitment*: Blake2_256_Digest # The validator's current RANDAO beacon commitment
|
||||
balance*: int64 # Current balance
|
||||
start_dynasty*: int64 # Dynasty where the validator is inducted
|
||||
end_dynasty*: int64 # Dynasty where the validator leaves
|
||||
|
||||
CrosslinkRecord* = object
|
||||
dynasty: int64 # What dynasty the crosslink was submitted in
|
||||
hash: Keccak256_Digest # The block hash
|
||||
hash: Blake2_256_Digest # The block hash
|
||||
|
||||
BLSPublicKey = object
|
||||
# Stub for BLS signature
|
||||
|
@ -69,10 +68,10 @@ type
|
|||
AttestationRecord* = object
|
||||
slot*: int64 # Slot number
|
||||
shard_id*: int16 # Shard ID
|
||||
oblique_parent_hashes*: seq[Keccak256_Digest]
|
||||
oblique_parent_hashes*: seq[Blake2_256_Digest]
|
||||
# List of block hashes that this signature is signing over that
|
||||
# are NOT part of the current chain, in order of oldest to newest
|
||||
shard_block_hash*: Keccak256_Digest # Block hash in the in the shard that we are attesting to
|
||||
shard_block_hash*: Blake2_256_Digest # Block hash in the shard that we are attesting to
|
||||
attester_bitfield*: IntSet # Who is participating
|
||||
aggregateSig*: seq[BLSPublicKey] # The actual signature
|
||||
# Note:
|
||||
|
|
|
@ -21,7 +21,7 @@ func checkPartialCrosslinkRecords*(beaconBlock: BeaconBlock, crystalState: Cryst
|
|||
if heightInEpoch < EpochLength - EndEpochGracePeriod:
|
||||
assert heightCutoffs[height_in_epoch] <= int(shardCutoffs[si] < heightCutoffs[heightInEpoch + 1]) # TODO Spec unclear
|
||||
else:
|
||||
assert vote.shardId == 65535 and vote.shardBlockHash == Keccak256_Digest()
|
||||
assert vote.shardId == 65535 and vote.shardBlockHash == Blake2_256_Digest()
|
||||
|
||||
var shard_start, shard_end: int
|
||||
if heightInEpoch < EpochLength - 8:
|
|
@ -91,13 +91,23 @@ func get_indices_for_slot*(crystallized_state: CrystallizedState,
|
|||
# Clarify with EF if light clients will need the beacon chain
|
||||
|
||||
func get_block_hash*(active_state: ActiveState,
|
||||
beacon_block: BeaconBlock, slot: int64): Keccak256_Digest =
|
||||
|
||||
# TODO: Spec uses crystallized_state as arg and activ_state.slot_number
|
||||
# which doesn't exist
|
||||
beacon_block: BeaconBlock, slot: int64): Blake2_256_Digest =
|
||||
|
||||
let sback = beacon_block.slot_number - CYCLE_LENGTH * 2
|
||||
assert sback <= slot
|
||||
assert slot < sback + CYCLE_LENGTH * 2
|
||||
|
||||
result = active_state.recent_block_hashes[int slot - sback]
|
||||
|
||||
func get_new_recent_block_hashes*(
|
||||
old_block_hashes: seq[Blake2_256_Digest],
|
||||
parent_slot, current_slot: int64,
|
||||
parent_hash: Blake2_256_Digest
|
||||
): seq[Blake2_256_Digest] =
|
||||
|
||||
# Should throw for `current_slot - CYCLE_LENGTH * 2 - 1` according to spec comment
|
||||
let d = current_slot - parent_slot
|
||||
result = old_block_hashes[d .. ^1]
|
||||
for _ in 0 ..< min(d, old_block_hashes.len):
|
||||
result.add parent_hash
|
||||
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2018 Status Research & Development GmbH
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
|
||||
# Note: this is also inspired by https://github.com/ethereum/beacon_chain/blob/master/beacon_chain/state/state_transition.py
|
||||
# The official spec at https://notes.ethereum.org/SCIg8AH5SA-O4C1G1LYZHQ# is not fully
|
||||
# defining the state transitions.
|
||||
#
|
||||
# Note that the ethresearch impl is using "block_vote_cache" field, which is a dictionary mapping hashes
|
||||
# to the following sub-dictionary:
|
||||
# {
|
||||
# 'voter_indices': set(),
|
||||
# 'total_voter_deposits': 0
|
||||
# }
|
||||
# It should not be needed anymore with the new AttestationRecord type
|
||||
|
||||
{.warning: "The official spec at https://notes.ethereum.org/SCIg8AH5SA-O4C1G1LYZHQ# is not fully defining state transitions.".}
|
||||
|
||||
import ./datatypes, ./private/helpers
|
||||
|
||||
|
||||
func process_block(active_state: ActiveState, crystallized_state: CrystallizedState, blck: BeaconBlock, slot: int64) =
|
||||
# TODO: unfinished spec
|
||||
|
||||
for attestation in blck.attestations:
|
||||
# Verify that slot < block.slot_number and slot >= max(block.slot_number - CYCLE_LENGTH, 0)
|
||||
doAssert slot < blck.slot_number
|
||||
doAssert slot >= max(blck.slot_number - CYCLE_LENGTH, 0)
|
||||
|
||||
# Compute parent_hashes = [get_block_hash(active_state, block, slot - CYCLE_LENGTH + i) for i in range(CYCLE_LENGTH - len(oblique_parent_hashes))] + oblique_parent_hashes
|
||||
# TODO - don't allocate in tight loop
|
||||
var parent_hashes = newSeq[Blake2_256_Digest](CYCLE_LENGTH - attestation.oblique_parent_hashes.len)
|
||||
for idx, val in parent_hashes.mpairs:
|
||||
val = get_block_hash(active_state, blck, slot - CYCLE_LENGTH + idx)
|
||||
parent_hashes.add attestation.oblique_parent_hashes
|
||||
|
||||
# Let attestation_indices be get_indices_for_slot(crystallized_state, slot)[x], choosing x so that attestation_indices.shard_id equals the shard_id value provided to find the set of validators that is creating this attestation record.
|
||||
let attestation_indices = block:
|
||||
let shard_and_committees = get_indices_for_slot(crystallized_state, slot)
|
||||
var
|
||||
x = 1
|
||||
record_creator = shard_and_committees[0]
|
||||
while record_creator.shard_id != attestation.shard_id:
|
||||
record_creator = shard_and_committees[x]
|
||||
inc x
|
||||
record_creator
|
||||
|
||||
# Verify that len(attester_bitfield) == ceil_div8(len(attestation_indices)), where ceil_div8 = (x + 7) // 8. Verify that bits len(attestation_indices).... and higher, if present (i.e. len(attestation_indices) is not a multiple of 8), are all zero
|
||||
doAssert attestation.attester_bitfield.len == attestation_indices.committee.len
|
||||
|
||||
# Derive a group public key by adding the public keys of all of the attesters in attestation_indices for whom the corresponding bit in attester_bitfield (the ith bit is (attester_bitfield[i // 8] >> (7 - (i %8))) % 2) equals 1
|
||||
# TODO
|
||||
|
||||
# Verify that aggregate_sig verifies using the group pubkey generated and hash((slot % CYCLE_LENGTH).to_bytes(8, 'big') + parent_hashes + shard_id + shard_block_hash) as the message.
|
||||
# TODO
|
||||
|
||||
# Extend the list of AttestationRecord objects in the active_state, ordering the new additions in the same order as they came in the block.
|
||||
# TODO
|
||||
|
||||
# Verify that the slot % len(get_indices_for_slot(crystallized_state, slot-1)[0])'th attester in get_indices_for_slot(crystallized_state, slot-1)[0]is part of at least one of the AttestationRecord objects; this attester can be considered to be the proposer of the block.
|
||||
# TODO
|
Loading…
Reference in New Issue