Finish network simulator
This commit is contained in:
parent
f6a66c8d3c
commit
3bc75711d5
|
@ -17,15 +17,7 @@ import
|
||||||
# Nimble packages
|
# Nimble packages
|
||||||
nimcrypto,
|
nimcrypto,
|
||||||
# Local imports
|
# Local imports
|
||||||
./fork_choice_types, ./networksim
|
./fork_choice_types
|
||||||
|
|
||||||
###########################################################
|
|
||||||
# Forward declarations
|
|
||||||
|
|
||||||
method on_receive(self: Node, obj: BlockOrSig, reprocess = false) {.base.} =
|
|
||||||
raise newException(ValueError, "Not implemented error. Please implement in child types")
|
|
||||||
|
|
||||||
###########################################################
|
|
||||||
|
|
||||||
proc broadcast(self: Node, x: BlockOrSig) =
|
proc broadcast(self: Node, x: BlockOrSig) =
|
||||||
if self.sleepy and self.timestamp != DurationZero:
|
if self.sleepy and self.timestamp != DurationZero:
|
||||||
|
@ -48,8 +40,8 @@ func add_to_multiset[K, V](
|
||||||
multiset: TableRef[K, seq[V]],
|
multiset: TableRef[K, seq[V]],
|
||||||
k: K,
|
k: K,
|
||||||
v: V or seq[V]) =
|
v: V or seq[V]) =
|
||||||
if k notin multiset:
|
# if k notin multiset: # Unneeded with seq "not nil" changes
|
||||||
multiset[k] = @[]
|
# multiset[k] = @[]
|
||||||
multiset[k].add v
|
multiset[k].add v
|
||||||
|
|
||||||
func change_head(self: Node, chain: var seq[MDigest[256]], new_head: Block) =
|
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 self.blocks[x].slot <= start_slot - 1 - i
|
||||||
doAssert result.len == min(EPOCH_LENGTH, start_slot)
|
doAssert result.len == min(EPOCH_LENGTH, start_slot)
|
||||||
|
|
||||||
proc tick(self: Node) =
|
proc tick*(self: Node) =
|
||||||
self.timestamp += initDuration(milliseconds = 100)
|
self.timestamp += initDuration(milliseconds = 100)
|
||||||
self.log &"Tick: {self.timestamp}", lvl=1
|
self.log &"Tick: {self.timestamp}", lvl=1
|
||||||
# Make a block?
|
# Make a block?
|
||||||
|
|
|
@ -107,7 +107,7 @@ type
|
||||||
agents*: seq[Node]
|
agents*: seq[Node]
|
||||||
latency_distribution_sample*: proc (): Duration
|
latency_distribution_sample*: proc (): Duration
|
||||||
time*: Duration
|
time*: Duration
|
||||||
objqueue*: TableRef[Duration, seq[(Node, BlockOrSig)]]
|
objqueue*: TableRef[Duration, seq[tuple[recipient: Node, obj: BlockOrSig]]]
|
||||||
peers*: TableRef[int, seq[Node]]
|
peers*: TableRef[int, seq[Node]]
|
||||||
reliability*: float
|
reliability*: float
|
||||||
|
|
||||||
|
@ -153,3 +153,23 @@ proc initSig*(
|
||||||
result.timestamp = ts
|
result.timestamp = ts
|
||||||
for val in result.hash.data.mitems:
|
for val in result.hash.data.mitems:
|
||||||
val = rand(0.byte .. 7.byte)
|
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)
|
||||||
|
|
||||||
|
###########################################################
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
tables, times, sugar, random,
|
tables, times, sugar, random,
|
||||||
./fork_choice_types, ./distributions
|
./fork_choice_types, ./fork_choice_rule, ./distributions
|
||||||
|
|
||||||
proc initNetworkSimulator*(latency: int): NetworkSimulator =
|
proc initNetworkSimulator*(latency: int): NetworkSimulator =
|
||||||
result.latency_distribution_sample = () => initDuration(
|
result.latency_distribution_sample = () => initDuration(
|
||||||
|
@ -37,9 +37,50 @@ proc generate_peers*(self: NetworkSimulator, num_peers = 5) =
|
||||||
for peer in p:
|
for peer in p:
|
||||||
self.peers[peer.id].add a
|
self.peers[peer.id].add a
|
||||||
|
|
||||||
func broadcast*(self: NetworkSimulator, sender: Node, obj: BlockOrSig) =
|
proc tick(self: NetworkSimulator) =
|
||||||
for p in self.peers[sender.id]:
|
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()
|
let recv_time = self.time + self.latency_distribution_sample()
|
||||||
if recv_time notin self.objqueue:
|
# if recv_time notin self.objqueue: # Unneeded with seq "not nil" changes
|
||||||
self.objqueue[recv_time] = @[]
|
# self.objqueue[recv_time] = @[]
|
||||||
self.objqueue[recv_time].add (p, obj)
|
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]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue