initial impl of fork choice rules. Main types sorted out
This commit is contained in:
parent
e403e96144
commit
f7e876471e
|
@ -15,17 +15,17 @@ type
|
|||
Uint24* = range[0'u32 .. 0xFFFFFF'u32] # TODO: wrap-around
|
||||
|
||||
BeaconBlock* = object
|
||||
parent_hash*: Blake2_256_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*: Blake2_256_Digest # Randao commitment reveal
|
||||
randao_reveal*: Blake2_256_Digest # Randao commitment reveal
|
||||
attestations*: seq[AttestationRecord] # Attestation votes
|
||||
pow_chain_ref*: Blake2_256_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[Blake2_256_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
|
||||
|
@ -41,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*: Blake2_256_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
|
||||
|
@ -52,16 +52,16 @@ 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*: Blake2_256_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: Blake2_256_Digest # The block hash
|
||||
hash: Blake2_256_Digest # The block hash
|
||||
|
||||
BLSPublicKey = object
|
||||
BLSPublicKey* = object
|
||||
# Stub for BLS signature
|
||||
data: array[32, byte]
|
||||
|
||||
|
@ -71,7 +71,7 @@ type
|
|||
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*: Blake2_256_Digest # Block hash 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:
|
||||
|
@ -91,7 +91,7 @@ type
|
|||
|
||||
const
|
||||
SHARD_COUNT* = 1024 # a constant referring to the number of shards
|
||||
DEPOSITE_SIZE* = 32 # You need to deposit 32 ETH to be a validator in Casper
|
||||
DEPOSIT_SIZE* = 32 # You need to deposit 32 ETH to be a validator in Casper
|
||||
MAX_VALIDATOR_COUNT* = 2^22 # 4_194_304, this means that ~132M ETH can stake at the same time (= MaxValidator Count * DepositSize)
|
||||
SLOT_DURATION* = 8 # seconds
|
||||
CYCLE_LENGTH* = 64 # slots
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
# 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.
|
||||
|
||||
# A port of https://github.com/ethereum/research/blob/master/clock_disparity/ghost_node.py
|
||||
# Specs: https://ethresear.ch/t/beacon-chain-casper-ffg-rpj-mini-spec/2760
|
||||
# Part of Casper+Sharding chain v2.1: https://notes.ethereum.org/SCIg8AH5SA-O4C1G1LYZHQ#
|
||||
|
||||
import
|
||||
tables, deques, # Stdlib
|
||||
nimcrypto, # Nimble packages
|
||||
# ../datatypes, # BeaconBlock is still different from the simulation blocks
|
||||
./networksim # From repo
|
||||
|
||||
import hashes
|
||||
func hash(x: MDigest): Hash =
|
||||
# Allow usage of MDigest in hashtables
|
||||
const bytes = x.type.bits div 8
|
||||
result = x.unsafeAddr.hashData(bytes)
|
||||
|
||||
const
|
||||
NOTARIES = 100 # Committee size in Casper v2.1
|
||||
SLOT_SIZE = 6 # Slot duration in Casper v2.1
|
||||
EPOCH_LENGTH = 25 # Cycle length inCasper v2.
|
||||
|
||||
# TODO, clear up if reference semantics are needed
|
||||
# for the tables, Block and Sig
|
||||
|
||||
type
|
||||
Block = ref object
|
||||
contents: array[32, byte]
|
||||
parent_hash: MDigest[256]
|
||||
hash: MDigest[256]
|
||||
height: int # slot in Casper v2.1 spec
|
||||
proposer: int64
|
||||
slot: int64
|
||||
|
||||
func min_timestamp(self: Block): int64 =
|
||||
SLOT_SIZE * self.slot
|
||||
|
||||
let Genesis = Block()
|
||||
|
||||
type
|
||||
Sig = object
|
||||
# TODO: unsure if this is still relevant in Casper v2.1
|
||||
proposer: int64 # the validator that creates a block
|
||||
targets: seq[MDigest[256]] # the hash of blocks proposed
|
||||
slot: int64 # slot number
|
||||
timestamp: int64 # ts in the ref implementation
|
||||
hash: MDigest[384] # The signature (BLS12-384)
|
||||
|
||||
type
|
||||
Node = ref object
|
||||
|
||||
blocks: TableRef[MDigest[256], Block]
|
||||
sigs: TableRef[MDigest[384], Sig]
|
||||
main_chain: seq[MDigest[256]]
|
||||
timequeue: seq[Block]
|
||||
parentqueue: TableRef[MDigest[256], Node]
|
||||
children: TableRef[MDigest[256], seq[MDigest[256]]]
|
||||
scores: TableRef[MDigest[256], int]
|
||||
scores_at_height: TableRef[MDigest[256], int] # Should be slot not height in v2.1
|
||||
justified: TableRef[MDigest[256], bool]
|
||||
finalized: TableRef[MDigest[256], bool]
|
||||
timestamp: int64
|
||||
id: int64
|
||||
network: NetworkSimulator
|
||||
used_parents: TableRef[MDigest[256], Node]
|
||||
processed: TableRef[MDigest[256], Block]
|
||||
sleepy: bool
|
||||
careless: bool
|
||||
first_round: bool
|
||||
last_made_block: int64
|
||||
last_made_sig: int64
|
||||
|
||||
proc log(self: Node, words: string, lvl = 3, all = false) =
|
||||
if (self.id == 0 or all) and lvl >= 2:
|
||||
echo self.id, words
|
||||
|
||||
func add_to_timequeue(self: Node, obj: Block) =
|
||||
var i = 0
|
||||
while i < self.timequeue.len and self.timequeue[i].min_timestamp < obj.min_timestamp:
|
||||
inc i
|
||||
self.timequeue.insert(obj, i)
|
||||
|
||||
func add_to_multiset[K, V](self: Node, multiset: var TableRef[K, V], k: K, v: V) =
|
||||
if k notin multiset:
|
||||
multiset[k] = @[]
|
||||
multiset[k].add v
|
||||
|
||||
func change_head(self: Node, chain: var seq[MDigest[256]], new_head: Block) =
|
||||
chain.add newSeq[MDigest[256]](new_head.height + 1 - chain.len)
|
||||
var (i, c) = (new_head.height, new_head.hash)
|
||||
while c != chain[i]:
|
||||
chain[i] = c
|
||||
c = self.blocks[c].parent_hash
|
||||
dec i
|
||||
for idx, val in chain:
|
||||
doAssert self.blocks[val].height == idx
|
||||
|
||||
func recalculate_head(self: Node) =
|
||||
while true:
|
||||
var
|
||||
descendant_queue = initDeque[MDigest[256]]()
|
||||
new_head: MDigest[256]
|
||||
max_count = 0
|
||||
descendant_queue.addFirst self.main_chain[^1]
|
||||
while descendant_queue.len != 0:
|
||||
let first = descendant_queue.popFirst()
|
||||
if first in self.children:
|
||||
for c in self.children[first]:
|
||||
descendant_queue.addLast c
|
||||
if self.scores.getOrDefault(first, 0) > max_count and first != self.main_chain[^1]:
|
||||
new_head = first
|
||||
max_count = self.scores.getOrDefault(first, 0)
|
||||
if new_head != MDigest[256](): # != default init, a 32-byte array of 0
|
||||
self.change_head(self.main_chain, self.blocks[new_head])
|
||||
else:
|
||||
return
|
|
@ -0,0 +1,21 @@
|
|||
# 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.
|
||||
|
||||
# A port of https://github.com/ethereum/research/blob/master/clock_disparity/ghost_node.py
|
||||
# Specs: https://ethresear.ch/t/beacon-chain-casper-ffg-rpj-mini-spec/2760
|
||||
# Part of Casper+Sharding chain v2.1: https://notes.ethereum.org/SCIg8AH5SA-O4C1G1LYZHQ#
|
||||
|
||||
import tables
|
||||
|
||||
type
|
||||
NetworkSimulator* = ref object
|
||||
agents*: seq[int]
|
||||
latency_distribution_sample*: seq[int]
|
||||
time*: int64
|
||||
objqueue*: Table[int, int]
|
||||
peers*: Table[int, int]
|
||||
reliability*: float
|
Loading…
Reference in New Issue