diff --git a/beacon_chain/fork_choice_rule/fork_choice_rule.nim b/beacon_chain/fork_choice_rule/fork_choice_rule.nim index a9a0c284f..eaac7043f 100644 --- a/beacon_chain/fork_choice_rule/fork_choice_rule.nim +++ b/beacon_chain/fork_choice_rule/fork_choice_rule.nim @@ -17,15 +17,7 @@ import # Nimble packages nimcrypto, # Local imports - ./fork_choice_types, ./networksim - -########################################################### -# Forward declarations - -method on_receive(self: Node, obj: BlockOrSig, reprocess = false) {.base.} = - raise newException(ValueError, "Not implemented error. Please implement in child types") - -########################################################### + ./fork_choice_types proc broadcast(self: Node, x: BlockOrSig) = if self.sleepy and self.timestamp != DurationZero: @@ -48,8 +40,8 @@ func add_to_multiset[K, V]( multiset: TableRef[K, seq[V]], k: K, v: V or seq[V]) = - if k notin multiset: - multiset[k] = @[] + # if k notin multiset: # Unneeded with seq "not nil" changes + # multiset[k] = @[] multiset[k].add v func change_head(self: Node, chain: var seq[MDigest[256]], new_head: Block) = @@ -241,7 +233,7 @@ func get_sig_targets(self: Node, start_slot: int32): seq[MDigest[256]] = doAssert self.blocks[x].slot <= start_slot - 1 - i doAssert result.len == min(EPOCH_LENGTH, start_slot) -proc tick(self: Node) = +proc tick*(self: Node) = self.timestamp += initDuration(milliseconds = 100) self.log &"Tick: {self.timestamp}", lvl=1 # Make a block? diff --git a/beacon_chain/fork_choice_rule/fork_choice_types.nim b/beacon_chain/fork_choice_rule/fork_choice_types.nim index 19def8a37..1b1a4c987 100644 --- a/beacon_chain/fork_choice_rule/fork_choice_types.nim +++ b/beacon_chain/fork_choice_rule/fork_choice_types.nim @@ -107,7 +107,7 @@ type agents*: seq[Node] latency_distribution_sample*: proc (): Duration time*: Duration - objqueue*: TableRef[Duration, seq[(Node, BlockOrSig)]] + objqueue*: TableRef[Duration, seq[tuple[recipient: Node, obj: BlockOrSig]]] peers*: TableRef[int, seq[Node]] reliability*: float @@ -153,3 +153,23 @@ proc initSig*( result.timestamp = ts for val in result.hash.data.mitems: val = rand(0.byte .. 7.byte) + +########################################################### +# Forward declarations + +method on_receive*(self: Node, obj: BlockOrSig, reprocess = false) {.base.} = + raise newException(ValueError, "Not implemented error. Please implement in child types") + +########################################################### + +########################################################### +# Common + +func broadcast*(self: NetworkSimulator, sender: Node, obj: BlockOrSig) = + for p in self.peers[sender.id]: + let recv_time = self.time + self.latency_distribution_sample() + if recv_time notin self.objqueue: + self.objqueue[recv_time] = @[] + self.objqueue[recv_time].add (p, obj) + +########################################################### diff --git a/beacon_chain/fork_choice_rule/networksim.nim b/beacon_chain/fork_choice_rule/networksim.nim index 3db580cd4..0bac77a6a 100644 --- a/beacon_chain/fork_choice_rule/networksim.nim +++ b/beacon_chain/fork_choice_rule/networksim.nim @@ -11,7 +11,7 @@ import tables, times, sugar, random, - ./fork_choice_types, ./distributions + ./fork_choice_types, ./fork_choice_rule, ./distributions proc initNetworkSimulator*(latency: int): NetworkSimulator = result.latency_distribution_sample = () => initDuration( @@ -37,9 +37,50 @@ proc generate_peers*(self: NetworkSimulator, num_peers = 5) = for peer in p: self.peers[peer.id].add a -func broadcast*(self: NetworkSimulator, sender: Node, obj: BlockOrSig) = - for p in self.peers[sender.id]: - let recv_time = self.time + self.latency_distribution_sample() - if recv_time notin self.objqueue: - self.objqueue[recv_time] = @[] - self.objqueue[recv_time].add (p, obj) +proc tick(self: NetworkSimulator) = + if self.time in self.objqueue: + for ro in self.objqueue[self.time]: + let (recipient, obj) = ro + if rand(1.0) < self.reliability: + recipient.on_receive(obj) + self.objqueue.del self.time + for a in self.agents: + a.tick() + self.time += initDuration(seconds = 1) + +proc run(self: NetworkSimulator, steps: int) = + for i in 0 ..< steps: + self.tick() + +# func broadcast*(self: NetworkSimulator, sender: Node, obj: BlockOrSig) +# ## defined in fork_choice_types.nim + +proc direct_send(self: NetworkSimulator, to_id: int32, obj: BlockOrSig) = + for a in self.agents: + if a.id == to_id: + let recv_time = self.time + self.latency_distribution_sample() + # if recv_time notin self.objqueue: # Unneeded with seq "not nil" changes + # self.objqueue[recv_time] = @[] + self.objqueue[recv_time].add (a, obj) + +proc knock_offline_random(self: NetworkSimulator, n: int) = + var ko = initTable[int32, Node]() + while ko.len < n: + let c = rand(self.agents) + ko[c.id] = c + # for c in ko.values: # Unneeded with seq "not nil" changes + # self.peers[c.id] = @[] + for a in self.agents: + self.peers[a.id] = lc[x | (x <- self.peers[a.id], x.id notin ko), Node] # List comprehension + +proc partition(self: NetworkSimulator) = + var a = initTable[int32, Node]() + while a.len < self.agents.len div 2: + let c = rand(self.agents) + a[c.id] = c + for c in self.agents: + if c.id in a: + self.peers[c.id] = lc[x | (x <- self.peers[c.id], x.id in a), Node] + else: + self.peers[c.id] = lc[x | (x <- self.peers[c.id], x.id notin a), Node] +