@@ -48,9 +48,7 @@ def partial_message_scenario(
4848 gs_params .GossipFactor = 0
4949 instructions .extend (spread_heartbeat_delay (node_count , gs_params ))
5050
51- number_of_conns_per_node = 20
52- if number_of_conns_per_node >= node_count :
53- number_of_conns_per_node = node_count - 1
51+ number_of_conns_per_node = min (20 , node_count - 1 )
5452 instructions .extend (random_network_mesh (node_count , number_of_conns_per_node ))
5553
5654 topic = "a-subnet"
@@ -107,13 +105,103 @@ def partial_message_scenario(
107105 return instructions
108106
109107
108+ def partial_message_extension_scenario (
109+ disable_gossip : bool , node_count : int
110+ ) -> List [ScriptInstruction ]:
111+ instructions : List [ScriptInstruction ] = []
112+ gs_params = GossipSubParams ()
113+ if disable_gossip :
114+ gs_params .Dlazy = 0
115+ gs_params .GossipFactor = 0
116+ instructions .extend (spread_heartbeat_delay (node_count , gs_params ))
117+
118+ # Create a bidirectional chain topology: 0<->1<->2....<->n-1
119+ # Each node connects to both previous and next (except first and last)
120+ for i in range (node_count ):
121+ connections = []
122+ if i > 0 :
123+ connections .append (i - 1 ) # Connect to previous
124+ if i < node_count - 1 :
125+ connections .append (i + 1 ) # Connect to next
126+
127+ if connections :
128+ instructions .append (
129+ script_instruction .IfNodeIDEquals (
130+ nodeID = i ,
131+ instruction = script_instruction .Connect (connectTo = connections ),
132+ )
133+ )
134+
135+ topic = "partial-ext-topic"
136+ instructions .append (
137+ script_instruction .SubscribeToTopic (topicID = topic , partial = True )
138+ )
139+
140+ # Wait for setup time and mesh stabilization
141+ elapsed_seconds = 30
142+ instructions .append (script_instruction .WaitUntil (elapsedSeconds = elapsed_seconds ))
143+
144+ # 16 messages with 8 parts each
145+ num_messages = 16
146+ num_parts = 8
147+
148+ # Assign parts to nodes in round-robin fashion
149+ # Each message-part combination goes to exactly one node
150+ for msg_idx in range (num_messages ):
151+ groupID = msg_idx # Unique group ID for each message
152+
153+ # Assign each of the 8 parts to nodes in round-robin
154+ for part_idx in range (num_parts ):
155+ node_idx = (msg_idx * num_parts + part_idx ) % node_count
156+ part_bitmap = 1 << part_idx # Single bit for this part
157+
158+ instructions .append (
159+ script_instruction .IfNodeIDEquals (
160+ nodeID = node_idx ,
161+ instruction = script_instruction .AddPartialMessage (
162+ topicID = topic , groupID = groupID , parts = part_bitmap
163+ ),
164+ )
165+ )
166+
167+ # Have multiple nodes with parts for each message try to publish
168+ # This creates redundancy and ensures the exchange process starts
169+ for msg_idx in range (num_messages ):
170+ groupID = msg_idx
171+
172+ elapsed_seconds += 2 # Delay between message groups
173+ instructions .append (
174+ script_instruction .WaitUntil (elapsedSeconds = elapsed_seconds )
175+ )
176+
177+ publisher_node = (msg_idx * num_parts ) % node_count
178+ print ("publisher node: " , publisher_node , msg_idx )
179+ instructions .append (
180+ script_instruction .IfNodeIDEquals (
181+ nodeID = publisher_node ,
182+ instruction = script_instruction .PublishPartial (
183+ topicID = topic , groupID = groupID
184+ ),
185+ )
186+ )
187+
188+ # Wait for propagation and assembly
189+ elapsed_seconds += 30
190+ instructions .append (script_instruction .WaitUntil (elapsedSeconds = elapsed_seconds ))
191+ return instructions
192+
193+
110194def scenario (
111195 scenario_name : str , node_count : int , disable_gossip : bool
112196) -> ExperimentParams :
113197 instructions : List [ScriptInstruction ] = []
114198 match scenario_name :
115199 case "partial-messages" :
116200 instructions = partial_message_scenario (disable_gossip , node_count )
201+ case "partial-message-extension" :
202+ instructions = partial_message_extension_scenario (
203+ disable_gossip , node_count
204+ )
117205 case "subnet-blob-msg" :
118206 gs_params = GossipSubParams ()
119207 if disable_gossip :
0 commit comments