diff --git a/data/simulation/config.d.ts b/data/simulation/config.d.ts
index 22f260571..a96a192ee 100644
--- a/data/simulation/config.d.ts
+++ b/data/simulation/config.d.ts
@@ -113,6 +113,8 @@ export interface Config {
/** Only supported by Rust simulation. */
"tx-validation-cpu-time-ms": number;
/** Only supported by Rust simulation. */
+ "tx-validation-cpu-time-ms-per-byte": number;
+ /** Only supported by Rust simulation. */
"tx-max-size-bytes": bigint;
/**
* What fraction of TXs (from 0 to 1) should introduce conflicts with transactions which were produced before?
diff --git a/data/simulation/config.default.yaml b/data/simulation/config.default.yaml
index 677c170ba..d42070eb9 100644
--- a/data/simulation/config.default.yaml
+++ b/data/simulation/config.default.yaml
@@ -61,6 +61,7 @@ tx-overcollateralization-factor-distribution:
distribution: constant
value: 0
tx-validation-cpu-time-ms: 1.5
+tx-validation-cpu-time-ms-per-byte: 0
tx-max-size-bytes: 16384
tx-conflict-fraction: 0
diff --git a/data/simulation/config.schema.json b/data/simulation/config.schema.json
index 569955133..a662b5018 100644
--- a/data/simulation/config.schema.json
+++ b/data/simulation/config.schema.json
@@ -511,6 +511,10 @@
"description": "Only supported by Rust simulation.",
"type": "number"
},
+ "tx-validation-cpu-time-ms-per-byte": {
+ "description": "Only supported by Rust simulation.",
+ "type": "number"
+ },
"vote-bundle-size-bytes-constant": {
"additionalProperties": false,
"properties": {},
diff --git a/sim-rs/CHANGELOG.md b/sim-rs/CHANGELOG.md
index 577e8f625..231051ae5 100644
--- a/sim-rs/CHANGELOG.md
+++ b/sim-rs/CHANGELOG.md
@@ -1,5 +1,19 @@
# Changelog
+## v1.2.0
+
+### All Leios variants
+
+Add a `tx-validation-cpu-time-ms-per-byte` setting, a CPU cost which applies to transactions before adding them to the mempool (or to an EB in Linear Leios).
+
+### Linear Leios
+
+Respect cerificate CPU time settings:
+ - `cert-generation-cpu-time-ms-constant`
+ - `cert-generation-cpu-time-ms-per-node` (currently set to 0)
+ - `cert-validation-cpu-time-ms-constant`
+ - `cert-validation-cpu-time-ms-per-node` (currently set to 0)
+
## v1.1.0
### Linear Leios
diff --git a/sim-rs/Cargo.lock b/sim-rs/Cargo.lock
index 4fdcf8ffe..5103c01c5 100644
--- a/sim-rs/Cargo.lock
+++ b/sim-rs/Cargo.lock
@@ -1213,7 +1213,7 @@ dependencies = [
[[package]]
name = "sim-cli"
-version = "1.1.0"
+version = "1.2.0"
dependencies = [
"anyhow",
"async-compression",
@@ -1241,7 +1241,7 @@ dependencies = [
[[package]]
name = "sim-core"
-version = "1.1.0"
+version = "1.2.0"
dependencies = [
"anyhow",
"async-stream",
diff --git a/sim-rs/implementations/CLASSIC_LEIOS.md b/sim-rs/implementations/CLASSIC_LEIOS.md
index 7b4476c0c..d48686d73 100644
--- a/sim-rs/implementations/CLASSIC_LEIOS.md
+++ b/sim-rs/implementations/CLASSIC_LEIOS.md
@@ -76,7 +76,7 @@ If more than one EB matches all of these criteria, we use for tiebreakers
## CPU model
|Task name in logs|Task name in code|When does it run|What happens when it completes|CPU cost
|---|---|---|---|---|
-|`ValTX`|`TransactionValidated`|After a transaction has been received from a peer.|That TX is announced to other peers.|`tx-validation-cpu-time-ms`|
+|`ValTX`|`TransactionValidated`|After a transaction has been received from a peer.|That TX is announced to other peers.|`tx-validation-cpu-time-ms` + `tx-validation-cpu-time-ms-per-byte` for each byte of TX|
|`GenRB`|`RBBlockGenerated`|After a new ranking block has been generated.|That RB is announced to peers.|`rb-generation-cpu-time-ms` + `cert-generation-cpu-time-ms-constant` + `cert-generation-cpu-time-ms-per-node` for each node that voted for the endorsed EB|
|`ValRB`|`RBBlockValidated`|After a ranking block has been received.|That RB body is announced to peers and (potentially) accepted as the tip of the chain.|`rb-body-legacy-praos-payload-validation-cpu-time-ms-constant` + `rb-body-legacy-praos-payload-validation-cpu-time-ms-per-byte` for each byte of TX + `cert-generation-cpu-time-ms-constant` + `cert-generation-cpu-time-ms-per-node` for each node that voted for the endorsed EB|
|`GenIB`|`IBBlockGenerated`|After a new IB has been generated.|That IB is announced to peers.|`ib-generation-cpu-time-ms`|
diff --git a/sim-rs/implementations/LINEAR_LEIOS.md b/sim-rs/implementations/LINEAR_LEIOS.md
index 1e869c593..e37e4b3e0 100644
--- a/sim-rs/implementations/LINEAR_LEIOS.md
+++ b/sim-rs/implementations/LINEAR_LEIOS.md
@@ -65,10 +65,10 @@ When a node receives an RB body, it immediately removes all referenced/conflicti
## CPU model
|Task name in logs|Task name in code|When does it run|What happens when it completes|CPU cost
|---|---|---|---|---|
-|`ValTX`|`TransactionValidated`|After a transaction has been received from a peer.|That TX is announced to other peers.|`tx-validation-cpu-time-ms`|
-|`GenRB`|`RBBlockGenerated`|After a new ranking block has been generated.|That RB and its EB are announced to peers.|RB generation and EB generation run in parallel.**RB generation**: `rb-generation-cpu-time-ms` + the CPU time of `ValRB`
**EB generation**: `eb-generation-cpu-time-ms` + the CPU time of `ValEB`|
+|`ValTX`|`TransactionValidated`|After a transaction has been received from a peer.|That TX is announced to other peers.|`tx-validation-cpu-time-ms` + `tx-validation-cpu-time-ms-per-byte` for each byte of TX|
+|`GenRB`|`RBBlockGenerated`|After a new ranking block has been generated.|That RB and its EB are announced to peers.|RB generation and EB generation run in parallel.**RB generation**: `rb-generation-cpu-time-ms` + `cert-generation-cpu-time-ms-constant` + `cert-generation-cpu-time-ms-per-node` for each node that voted for the endorsed EB + `rb-body-legacy-praos-payload-validation-cpu-time-ms-constant` + `rb-body-legacy-praos-payload-validation-cpu-time-ms-per-byte` for each byte of TX
**EB generation**: `eb-generation-cpu-time-ms` + the CPU time of `ValEB`|
|`ValRH`|`RBHeaderValidated`|After a ranking block header has been received.|That RB is announced to peers.
The referenced EB is queued to be downloaded when available.|`rb-head-validation-cpu-time-ms`|
-|`ValRB`|`RBBlockValidated`|After a ranking block body has been received.|That RB body is announced to peers and (potentially) accepted as the tip of the chain.|`rb-body-legacy-praos-payload-validation-cpu-time-ms-constant` + `rb-body-legacy-praos-payload-validation-cpu-time-ms-per-byte` for each byte of TX|
+|`ValRB`|`RBBlockValidated`|After a ranking block body has been received.|That RB body is announced to peers and (potentially) accepted as the tip of the chain.|`rb-body-legacy-praos-payload-validation-cpu-time-ms-constant` + `rb-body-legacy-praos-payload-validation-cpu-time-ms-per-byte` for each byte of TX + `cert-validation-cpu-time-ms-constant` + `cert-validation-cpu-time-ms-per-node` for each node that voted for the endorsed EB|
|`ValEH`|`EBHeaderValidated`|After an EB header has been received and validated.|That EB is announced to peers, and body validation begins in the background.|`eb-header-validation-cpu-time-ms`|
|`ValEB`|`EBBlockValidated`|After an EB's body has been validated.|If eligible, the node will vote for that EB.|`eb-body-validation-cpu-time-ms-constant` + `eb-body-validation-cpu-time-ms-per-byte` for each byte of TX|
|`GenVote`|`VTBundleGenerated`|After a vote bundle has been generated.|That vote bundle is announced to peers.|`vote-generation-cpu-time-ms-constant` + `vote-generation-cpu-time-ms-per-tx` for each TX in the EB|
diff --git a/sim-rs/implementations/STRACCIATELLA.md b/sim-rs/implementations/STRACCIATELLA.md
index 29f43e1a7..029dea798 100644
--- a/sim-rs/implementations/STRACCIATELLA.md
+++ b/sim-rs/implementations/STRACCIATELLA.md
@@ -15,7 +15,7 @@ Voting for endorser blocks also behaves mostly the same as in the original Leios
## CPU model
|Task name in logs|Task name in code|When does it run|What happens when it completes|CPU cost
|---|---|---|---|---|
-|`ValTX`|`TransactionValidated`|After a transaction has been received from a peer.|That TX is announced to other peers.|`tx-validation-cpu-time-ms`|
+|`ValTX`|`TransactionValidated`|After a transaction has been received from a peer.|That TX is announced to other peers.|`tx-validation-cpu-time-ms` + `tx-validation-cpu-time-ms-per-byte` for each byte of TX|
|`GenRB`|`RBBlockGenerated`|After a new ranking block has been generated.|That RB is announced to peers.|`rb-generation-cpu-time-ms` + `cert-generation-cpu-time-ms-constant` + `cert-generation-cpu-time-ms-per-node` for each node that voted for the endorsed EB|
|`ValRB`|`RBBlockValidated`|After a ranking block has been received.|That RB body is announced to peers and (potentially) accepted as the tip of the chain.|`rb-body-legacy-praos-payload-validation-cpu-time-ms-constant` + `rb-body-legacy-praos-payload-validation-cpu-time-ms-per-byte` for each byte of TX + `cert-generation-cpu-time-ms-constant` + `cert-generation-cpu-time-ms-per-node` for each node that voted for the endorsed EB|
|`GenEB`|`EBBlockGenerated`|After a new EB has been generated.|That EB is announced to peers.|`eb-generation-cpu-time-ms`|
diff --git a/sim-rs/sim-cli/Cargo.toml b/sim-rs/sim-cli/Cargo.toml
index 06eaa3392..0a51c3b89 100644
--- a/sim-rs/sim-cli/Cargo.toml
+++ b/sim-rs/sim-cli/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "sim-cli"
-version = "1.1.0"
+version = "1.2.0"
edition = "2024"
default-run = "sim-cli"
rust-version = "1.88"
diff --git a/sim-rs/sim-core/Cargo.toml b/sim-rs/sim-core/Cargo.toml
index 741af10fb..99f55a4d2 100644
--- a/sim-rs/sim-core/Cargo.toml
+++ b/sim-rs/sim-core/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "sim-core"
-version = "1.1.0"
+version = "1.2.0"
edition = "2024"
rust-version = "1.88"
diff --git a/sim-rs/sim-core/src/config.rs b/sim-rs/sim-core/src/config.rs
index 4a1d05514..455cf15e6 100644
--- a/sim-rs/sim-core/src/config.rs
+++ b/sim-rs/sim-core/src/config.rs
@@ -85,6 +85,7 @@ pub struct RawParameters {
pub tx_size_bytes_distribution: DistributionConfig,
pub tx_overcollateralization_factor_distribution: DistributionConfig,
pub tx_validation_cpu_time_ms: f64,
+ pub tx_validation_cpu_time_ms_per_byte: f64,
pub tx_max_size_bytes: u64,
pub tx_conflict_fraction: Option,
pub tx_start_time: Option,
@@ -393,7 +394,8 @@ impl From for Topology {
#[derive(Debug, Clone)]
pub(crate) struct CpuTimeConfig {
- pub tx_validation: Duration,
+ pub tx_validation_constant: Duration,
+ pub tx_validation_per_byte: Duration,
pub rb_generation: Duration,
pub rb_head_validation: Duration,
pub rb_body_validation_constant: Duration,
@@ -419,7 +421,8 @@ pub(crate) struct CpuTimeConfig {
impl CpuTimeConfig {
fn new(params: &RawParameters) -> Self {
Self {
- tx_validation: duration_ms(params.tx_validation_cpu_time_ms),
+ tx_validation_constant: duration_ms(params.tx_validation_cpu_time_ms),
+ tx_validation_per_byte: duration_ms(params.tx_validation_cpu_time_ms_per_byte),
rb_generation: duration_ms(params.rb_generation_cpu_time_ms),
rb_head_validation: duration_ms(params.rb_head_validation_cpu_time_ms),
rb_body_validation_constant: duration_ms(
diff --git a/sim-rs/sim-core/src/sim/leios.rs b/sim-rs/sim-core/src/sim/leios.rs
index e0cbb8e40..34edd9c2a 100644
--- a/sim-rs/sim-core/src/sim/leios.rs
+++ b/sim-rs/sim-core/src/sim/leios.rs
@@ -174,7 +174,9 @@ impl SimCpuTask for Task {
fn times(&self, config: &crate::config::CpuTimeConfig) -> Vec {
match self {
- Self::TransactionValidated(_, _) => vec![config.tx_validation],
+ Self::TransactionValidated(_, tx) => vec![
+ config.tx_validation_constant + config.tx_validation_per_byte * tx.bytes as u32,
+ ],
Self::RBBlockGenerated(block) => {
let mut time = config.rb_generation;
if let Some(endorsement) = &block.endorsement {
diff --git a/sim-rs/sim-core/src/sim/linear_leios.rs b/sim-rs/sim-core/src/sim/linear_leios.rs
index 7c954bc29..ea907e96c 100644
--- a/sim-rs/sim-core/src/sim/linear_leios.rs
+++ b/sim-rs/sim-core/src/sim/linear_leios.rs
@@ -163,11 +163,18 @@ impl SimCpuTask for CpuTask {
fn times(&self, config: &CpuTimeConfig) -> Vec {
match self {
- Self::TransactionValidated(_, _) => vec![config.tx_validation],
+ Self::TransactionValidated(_, tx) => vec![
+ config.tx_validation_constant + config.tx_validation_per_byte * tx.bytes as u32,
+ ],
Self::RBBlockGenerated(rb, eb, _) => {
let mut rb_time = config.rb_generation + config.rb_body_validation_constant;
let rb_bytes: u64 = rb.transactions.iter().map(|tx| tx.bytes).sum();
rb_time += config.rb_validation_per_byte * (rb_bytes as u32);
+ if let Some(endorsement) = &rb.endorsement {
+ let nodes = endorsement.votes.len();
+ rb_time += config.cert_generation_constant
+ + (config.cert_generation_per_node * nodes as u32);
+ }
let mut eb_time = config.eb_generation + config.eb_body_validation_constant;
let eb_bytes: u64 = eb.txs.iter().map(|tx| tx.bytes).sum();
@@ -180,6 +187,11 @@ impl SimCpuTask for CpuTask {
let mut time = config.rb_body_validation_constant;
let bytes: u64 = rb.transactions.iter().map(|tx| tx.bytes).sum();
time += config.rb_validation_per_byte * (bytes as u32);
+ if let Some(endorsement) = &rb.endorsement {
+ let nodes = endorsement.votes.len();
+ time += config.cert_validation_constant
+ + (config.cert_validation_per_node * nodes as u32);
+ }
vec![time]
}
Self::EBHeaderValidated(_, _) => vec![config.eb_header_validation],
diff --git a/sim-rs/sim-core/src/sim/stracciatella.rs b/sim-rs/sim-core/src/sim/stracciatella.rs
index 99303b4a2..bac0e3645 100644
--- a/sim-rs/sim-core/src/sim/stracciatella.rs
+++ b/sim-rs/sim-core/src/sim/stracciatella.rs
@@ -132,7 +132,9 @@ impl SimCpuTask for CpuTask {
fn times(&self, config: &crate::config::CpuTimeConfig) -> Vec {
match self {
- Self::TransactionValidated(_, _) => vec![config.tx_validation],
+ Self::TransactionValidated(_, tx) => vec![
+ config.tx_validation_constant + config.tx_validation_per_byte * tx.bytes as u32,
+ ],
Self::RBBlockGenerated(rb) => {
let mut time = config.rb_generation;
if let Some(endorsement) = &rb.endorsement {