Skip to content

Commit 9af61b1

Browse files
authored
Add support for conflicting transactions (#415)
* sim-rs: add input_id to traces * sim-rs: include rb-ref on output * sim-rs: do not create IBs with conflicting transactions * sim-rs: do not add conflicting blocks to mempool * sim-rs: support configuring tx-conflict-fraction * sim-rs: support leios-aggressive-mempool-pruning setting * sim-rs: fix intermittent test failure
1 parent 4d2e12a commit 9af61b1

File tree

15 files changed

+266
-64
lines changed

15 files changed

+266
-64
lines changed

data/simulation/config.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ export interface Config {
5353
* The strategy to use when selecting TXs from the Leios mempool.
5454
*/
5555
"leios-mempool-sampling-strategy": MempoolSamplingStrategy;
56+
/**
57+
* If true, transactions will be removed from the Leios mempool if they conflict with in-flight IBs.
58+
*/
59+
"leios-mempool-aggressive-pruning": boolean;
5660
/**
5761
* Praos blockchain quality parameter.
5862
* This is η from the Leios paper.
@@ -75,6 +79,10 @@ export interface Config {
7579
"tx-validation-cpu-time-ms": number;
7680
/** Only supported by Rust simulation. */
7781
"tx-max-size-bytes": bigint;
82+
/**
83+
* What fraction of TXs (from 0 to 1) should introduce conflicts with transactions which were produced before?
84+
* Only supported by Rust simulation. */
85+
"tx-conflict-fraction": number | null;
7886
/**
7987
* When the first transaction should appear.
8088
* Only supported by Rust simulation. */

data/simulation/config.default.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ leios-vote-send-recv-stages: false
3030
leios-late-ib-inclusion: true
3131
leios-header-diffusion-time-ms: 1000.0
3232
leios-mempool-sampling-strategy: ordered-by-id
33+
leios-mempool-aggressive-pruning: false
3334
# TODO: revise default
3435
praos-chain-quality: 40
3536
praos-fallback-enabled: true
@@ -48,6 +49,7 @@ tx-size-bytes-distribution:
4849
sigma: 1.127
4950
tx-validation-cpu-time-ms: 1.5
5051
tx-max-size-bytes: 16384
52+
tx-conflict-fraction: 0
5153

5254
################################################################################
5355
# Ranking Block Configuration

data/simulation/config.schema.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,10 @@
355355
"description": "When `true`, any delays and message sizes are calculated as if\neach block contained as much data as the expected average, rounded up.\nIn particular, for the sake of the above, we consider that:\n - Each RB includes a certificate.\n - Certificates contain votes from `vote-threshold` nodes.\n - Vote bundles vote for `ceil eb-generation-probability` EBs.\n - EBs reference `ceil (ib-generation-probability * leios-stage-length-slots)` IBs.\nOnly supported by Haskell simulation.",
356356
"type": "boolean"
357357
},
358+
"tx-conflict-fraction": {
359+
"description": "What fraction of TXs (from 0 to 1) should introduce conflicts with transactions which were produced before?\nOnly supported by Rust simulation.",
360+
"type": "number"
361+
},
358362
"tx-generation-distribution": {
359363
"$ref": "#/definitions/Distribution",
360364
"description": "Only supported by Rust simulation."

data/simulation/example.rust.jsonl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{"time_s":0.0,"message":{"type":"CpuTaskScheduled","task":{"node":"node-0","index":1},"task_type":"GenIB","subtasks":1}}
88
{"time_s":0.0,"message":{"type":"Cpu","task":{"node":"node-0","index":1},"node":"node-0","cpu_time_s":0.13,"task_label":"GenIB: node-0-1-0","task_type":"GenIB","id":"node-0-1-0"}}
99
{"time_s":0.0,"message":{"type":"VTLotteryWon","id":"0-node-1","slot":0,"pipeline":0,"producer":"node-1"}}
10-
{"time_s":0.0,"message":{"type":"TXGenerated","id":"0","publisher":"node-11","size_bytes":156}}
10+
{"time_s":0.0,"message":{"type":"TXGenerated","id":"0","publisher":"node-11","size_bytes":156,"input_id":0}}
1111
{"time_s":0.0,"message":{"type":"VTLotteryWon","id":"0-node-3","slot":0,"pipeline":0,"producer":"node-3"}}
1212
{"time_s":0.0,"message":{"type":"VTLotteryWon","id":"0-node-4","slot":0,"pipeline":0,"producer":"node-4"}}
1313
{"time_s":0.0,"message":{"type":"EBLotteryWon","id":"0-node-4","slot":0,"pipeline":1,"producer":"node-4"}}

data/simulation/topology.d.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
*/
1010
export interface Topology {
1111
nodes:
12-
| {
13-
[name: NodeName]: Node<Cluster>;
14-
}
15-
| {
16-
[name: NodeName]: Node<Coord2D>;
17-
};
12+
| {
13+
[name: NodeName]: Node<Cluster>;
14+
}
15+
| {
16+
[name: NodeName]: Node<Coord2D>;
17+
};
1818
}
1919

2020
/** A node. */
@@ -23,6 +23,10 @@ export interface Node<Location> {
2323
"cpu-core-count"?: bigint | null;
2424
location: Location;
2525
producers: { [producer: NodeName]: LinkInfo };
26+
/**
27+
* What fraction of TXs (from 0 to 1) should introduce conflicts with transactions which were produced before?
28+
* Only supported by Rust simulation. */
29+
"tx-conflict-fraction"?: number | null;
2630
/** If not null, the node will behave according to the given Behaviour.
2731
*
2832
* Only supported by Haskell simulation.

data/simulation/topology.schema.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@
4848
"additionalProperties": false,
4949
"properties": {},
5050
"type": "number"
51+
},
52+
"tx-conflict-fraction": {
53+
"description": "What fraction of TXs (from 0 to 1) should introduce conflicts with transactions which were produced before?\nOnly supported by Rust simulation.",
54+
"type": "number"
5155
}
5256
},
5357
"type": "object"
@@ -87,6 +91,10 @@
8791
"additionalProperties": false,
8892
"properties": {},
8993
"type": "number"
94+
},
95+
"tx-conflict-fraction": {
96+
"description": "What fraction of TXs (from 0 to 1) should introduce conflicts with transactions which were produced before?\nOnly supported by Rust simulation.",
97+
"type": "number"
9098
}
9199
},
92100
"type": "object"

data/simulation/trace.rust.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ interface GeneratedTransaction {
5656
id: string;
5757
publisher: string;
5858
size_bytes: number;
59+
input_id: number;
5960
}
6061

6162
interface LostTransaction {

data/simulation/trace.rust.schema.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@
239239
"id": {
240240
"type": "string"
241241
},
242+
"input_id": {
243+
"type": "number"
244+
},
242245
"publisher": {
243246
"type": "string"
244247
},
@@ -250,7 +253,7 @@
250253
"type": "string"
251254
}
252255
},
253-
"required": ["id", "publisher", "size_bytes", "type"],
256+
"required": ["id", "input_id", "publisher", "size_bytes", "type"],
254257
"type": "object"
255258
},
256259
"GeneratedVote": {

sim-rs/sim-cli/src/bin/gen-test-data/strategy/utils.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ impl GraphBuilder {
6262
let loc1 = to_netsim_location(self.location_of(node));
6363
let loc2 = to_netsim_location(self.location_of(producer));
6464
latency_between_locations(loc1, loc2, 1.)
65-
.unwrap()
66-
.to_duration()
65+
.map(|d| d.to_duration())
66+
.unwrap_or_default()
6767
.max(Duration::from_millis(1))
6868
});
6969
self.links.push(RawLinkConfig {
@@ -170,6 +170,7 @@ impl GraphBuilder {
170170
stake: n.stake,
171171
location: RawNodeLocation::Coords(n.location),
172172
cpu_core_count: n.cores,
173+
tx_conflict_fraction: None,
173174
producers: BTreeMap::new(),
174175
};
175176
(name, node)

sim-rs/sim-core/src/config.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub struct RawParameters {
6868
pub leios_late_ib_inclusion: bool,
6969
pub leios_header_diffusion_time_ms: f64,
7070
pub leios_mempool_sampling_strategy: MempoolSamplingStrategy,
71+
pub leios_mempool_aggressive_pruning: bool,
7172
pub praos_chain_quality: u64,
7273
pub praos_fallback_enabled: bool,
7374

@@ -76,6 +77,7 @@ pub struct RawParameters {
7677
pub tx_size_bytes_distribution: DistributionConfig,
7778
pub tx_validation_cpu_time_ms: f64,
7879
pub tx_max_size_bytes: u64,
80+
pub tx_conflict_fraction: Option<f64>,
7981
pub tx_start_time: Option<f64>,
8082
pub tx_stop_time: Option<f64>,
8183

@@ -177,6 +179,8 @@ pub struct RawNode {
177179
pub location: RawNodeLocation,
178180
#[serde(skip_serializing_if = "Option::is_none")]
179181
pub cpu_core_count: Option<u64>,
182+
#[serde(skip_serializing_if = "Option::is_none")]
183+
pub tx_conflict_fraction: Option<f64>,
180184
pub producers: BTreeMap<String, RawLinkInfo>,
181185
}
182186

@@ -254,6 +258,7 @@ impl From<RawTopology> for Topology {
254258
stake: node.stake.unwrap_or_default(),
255259
cpu_multiplier: 1.0,
256260
cores: node.cpu_core_count,
261+
tx_conflict_fraction: node.tx_conflict_fraction,
257262
consumers: vec![],
258263
},
259264
);
@@ -403,6 +408,7 @@ impl TransactionConfig {
403408
max_size: params.tx_max_size_bytes,
404409
frequency_ms: params.tx_generation_distribution.into(),
405410
size_bytes: params.tx_size_bytes_distribution.into(),
411+
conflict_fraction: params.tx_conflict_fraction.unwrap_or_default(),
406412
start_time: params
407413
.tx_start_time
408414
.map(|t| Timestamp::zero() + Duration::from_secs_f64(t)),
@@ -425,6 +431,7 @@ pub(crate) struct RealTransactionConfig {
425431
pub max_size: u64,
426432
pub frequency_ms: FloatDistribution,
427433
pub size_bytes: FloatDistribution,
434+
pub conflict_fraction: f64,
428435
pub start_time: Option<Timestamp>,
429436
pub stop_time: Option<Timestamp>,
430437
}
@@ -437,11 +444,16 @@ pub(crate) struct MockTransactionConfig {
437444
}
438445

439446
impl MockTransactionConfig {
440-
pub fn next_id(&self) -> TransactionId {
447+
pub fn mock_tx(&self, bytes: u64) -> Transaction {
441448
let id = self
442449
.next_id
443450
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
444-
TransactionId::new(id)
451+
Transaction {
452+
id: TransactionId::new(id),
453+
shard: 0,
454+
bytes,
455+
input_id: id,
456+
}
445457
}
446458
}
447459

@@ -464,6 +476,7 @@ pub struct SimConfiguration {
464476
pub(crate) header_diffusion_time: Duration,
465477
pub(crate) relay_strategy: RelayStrategy,
466478
pub(crate) mempool_strategy: MempoolSamplingStrategy,
479+
pub(crate) mempool_aggressive_pruning: bool,
467480
pub(crate) praos_chain_quality: u64,
468481
pub(crate) block_generation_probability: f64,
469482
pub(crate) ib_generation_probability: f64,
@@ -509,6 +522,7 @@ impl SimConfiguration {
509522
header_diffusion_time: duration_ms(params.leios_header_diffusion_time_ms),
510523
relay_strategy: params.relay_strategy,
511524
mempool_strategy: params.leios_mempool_sampling_strategy,
525+
mempool_aggressive_pruning: params.leios_mempool_aggressive_pruning,
512526
praos_chain_quality: params.praos_chain_quality,
513527
block_generation_probability: params.rb_generation_probability,
514528
ib_generation_probability: params.ib_generation_probability,
@@ -542,6 +556,7 @@ pub struct NodeConfiguration {
542556
pub stake: u64,
543557
pub cpu_multiplier: f64,
544558
pub cores: Option<u64>,
559+
pub tx_conflict_fraction: Option<f64>,
545560
pub consumers: Vec<NodeId>,
546561
}
547562

0 commit comments

Comments
 (0)