improve advesary: io_window_moving_interval

This commit is contained in:
Youngjoon Lee 2024-05-27 18:20:59 +09:00
parent 5e698b7e00
commit 55f0f67554
No known key found for this signature in database
GPG Key ID: 09B750B5BD6F08A2
4 changed files with 44 additions and 25 deletions

View File

@ -1,7 +1,7 @@
from __future__ import annotations
import math
from collections import defaultdict
from collections import defaultdict, deque
from enum import Enum
from typing import TYPE_CHECKING
@ -21,7 +21,8 @@ class Adversary:
self.config = config
self.message_sizes = []
self.senders_around_interval = defaultdict(int)
self.mixed_msgs_per_window = []
self.msgs_in_node_per_window = [] # [<node, int>]
self.cur_window_per_node = defaultdict(lambda: deque()) # <node, [(time, int)]>: int is + or -.
# self.node_states = defaultdict(dict)
self.env.process(self.update_observation_window())
@ -30,12 +31,12 @@ class Adversary:
self.message_sizes.append(len(msg))
def observe_receiving_node(self, node: "Node"):
self.mixed_msgs_per_window[-1][node] += 1
self.cur_window_per_node[node].append((self.env.now, 1))
# if node not in self.node_states[self.env.now]:
# self.node_states[self.env.now][node] = NodeState.RECEIVING
def observe_sending_node(self, node: "Node"):
self.mixed_msgs_per_window[-1][node] -= 1
self.cur_window_per_node[node].append((self.env.now, -1))
if self.is_around_message_interval(self.env.now):
self.senders_around_interval[node] += 1
# self.node_states[self.env.now][node] = NodeState.SENDING
@ -46,8 +47,19 @@ class Adversary:
def update_observation_window(self):
while True:
self.mixed_msgs_per_window.append(defaultdict(int))
yield self.env.timeout(self.config.adversary.io_observation_window)
yield self.env.timeout(self.config.adversary.io_window_moving_interval)
self.msgs_in_node_per_window.append(defaultdict(int)) # <node, int>
for node, queue in self.cur_window_per_node.items():
msg_cnt = 0.0
# Pop old events that are out of the new window, and accumulate msg_cnt
while queue and queue[0][0] < self.env.now - self.config.adversary.io_window_size:
_, delta = queue.popleft()
msg_cnt += delta
# Iterate remaining events that will remain in the new window, and accumulate msg_cnt
for _, delta in queue:
msg_cnt += delta
self.msgs_in_node_per_window[-1][node] = msg_cnt
class NodeState(Enum):

View File

@ -16,8 +16,7 @@ class Analysis:
message_size_df = self.message_size_distribution()
self.bandwidth(message_size_df)
self.messages_emitted_around_interval()
if self.config.mixnet.is_mixing_on():
self.mixed_messages_per_node_over_time()
self.messages_in_node_over_time()
# self.node_states()
def bandwidth(self, message_size_df: pd.DataFrame):
@ -88,24 +87,25 @@ class Analysis:
plt.legend(title="expected")
plt.show()
def mixed_messages_per_node_over_time(self):
def messages_in_node_over_time(self):
dataframes = []
for mixed_msgs_per_node in self.sim.p2p.adversary.mixed_msgs_per_window:
df = pd.DataFrame([(node.id, cnt) for node, cnt in mixed_msgs_per_node.items()],
columns=["node_id", "msg_count"])
dataframes.append(df)
observation_times = range(len(dataframes))
df = pd.concat([df.assign(Time=time) for df, time in zip(dataframes, observation_times)], ignore_index=True)
df = df.pivot(index="Time", columns="node_id", values="msg_count")
for i, msgs_in_node in enumerate(self.sim.p2p.adversary.msgs_in_node_per_window):
time = i * self.config.adversary.io_window_moving_interval
df = pd.DataFrame([(time, node.id, cnt) for node, cnt in msgs_in_node.items()],
columns=["time", "node_id", "msg_count"])
if not df.empty:
dataframes.append(df)
df = pd.concat(dataframes, ignore_index=True)
df_pivot = df.pivot(index="time", columns="node_id", values="msg_count")
plt.figure(figsize=(12, 6))
for column in df.columns:
plt.plot(df.index, df[column], marker="o", label=column)
plt.title("Mixed messages in each mix over time")
for column in df_pivot.columns:
plt.plot(df_pivot.index, df_pivot[column], marker=None, label=column)
plt.title("Messages in each node over time")
plt.xlabel("Time")
plt.ylabel("Msg Count")
plt.ylim(bottom=0)
plt.legend(title="Node ID")
plt.grid(True)
plt.tight_layout()
plt.show()
def node_states(self):

View File

@ -131,8 +131,12 @@ class MeasurementConfig:
@dataclass
class AdversaryConfig:
# A discrete time window for the adversary to observe inputs and outputs of a certain node
io_observation_window: int
# A time window for the adversary to observe inputs and outputs of each node
io_window_size: float
# A moving interval of the time window for the adversary to observe inputs and outputs of each node
# This must be smaller or equal to io_window_size.
io_window_moving_interval: float
def validate(self):
assert self.io_observation_window >= 1
assert self.io_window_size > 0
assert 0 < self.io_window_moving_interval <= self.io_window_size

View File

@ -38,5 +38,8 @@ measurement:
sim_time_per_second: 1
adversary:
# A discrete time window for the adversary to observe inputs and outputs of a certain node
io_observation_window: 1
# A time window for the adversary to observe inputs and outputs of each node
io_window_size: 0.20
# A moving interval of the time window for the adversary to observe inputs and outputs of each node
# This must be smaller or equal to io_window_size.
io_window_moving_interval: 0.10