Finish network simulator

This commit is contained in:
mratsim 2018-09-11 12:24:46 +02:00
parent f6a66c8d3c
commit 3bc75711d5
3 changed files with 73 additions and 20 deletions

View File

@ -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?

View File

@ -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)
###########################################################

View File

@ -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]:
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:
self.objqueue[recv_time] = @[]
self.objqueue[recv_time].add (p, obj)
# 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]