Skip to content

Commit a8f6406

Browse files
authored
Merge pull request #263 from pragma-org/rk/effect-logging
feat: TraceBuffer and simulation Replay
2 parents 2e6d5c1 + 132a08a commit a8f6406

42 files changed

Lines changed: 2616 additions & 1017 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 231 additions & 131 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ anyhow = "1.0.95"
2020
async-trait = "0.1.83"
2121
async-compression = { version = "0.4.24", features = ["tokio", "gzip"] }
2222
bech32 = "0.11.0"
23+
cbor4ii = { version = "1.0.0", features = ["serde1", "use_std"] }
2324
clap = { version = "4.5.38", features = ["derive", "env"] }
2425
reqwest = { version = "0.11.24", default-features = false, features = ["json", "stream", "rustls-tls"] }
2526
either = "1.15"
@@ -66,6 +67,7 @@ tracing-subscriber = { version = "0.3.18", features = [
6667
"std",
6768
"json",
6869
] }
70+
typetag = "0.2.20"
6971

7072
amaru-consensus = { path = "crates/amaru-consensus" }
7173
amaru-kernel = { path = "crates/amaru-kernel" }
@@ -84,12 +86,13 @@ vrf_dalek = { git = "https://github.com/txpipe/vrf", rev = "044b45a1a919ba9d9c24
8486
kes-summed-ed25519 = { git = "https://github.com/txpipe/kes", rev = "f69fb357d46f6a18925543d785850059569d7e78" }
8587

8688
# dev-dependencies
89+
criterion = "0.6.0"
8790
ctor = "0.4.1"
88-
tempfile = "3.20.0"
89-
rand = "0.9.1"
90-
proptest = { version = "1.5.0", default-features = false, features = ["alloc"] }
9191
insta = "1.41.1"
92-
criterion = "0.6.0"
92+
pretty_assertions = "1.4.1"
93+
proptest = { version = "1.5.0", default-features = false, features = ["alloc"] }
94+
rand = "0.9.1"
95+
tempfile = "3.20.0"
9396
test-case = "3.3.1"
9497

9598
# build-dependencies

crates/amaru-consensus/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pallas-codec.workspace = true
1818
pallas-crypto.workspace = true
1919
pallas-math.workspace = true
2020
rayon.workspace = true
21+
serde.workspace = true
2122
thiserror.workspace = true
2223
tokio.workspace = true
2324
tracing.workspace = true

crates/amaru-consensus/src/consensus/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,20 @@ impl fmt::Debug for ChainSyncEvent {
7575
}
7676
}
7777

78-
#[derive(Clone, PartialEq)]
78+
#[derive(Clone, PartialEq, serde::Serialize, serde::Deserialize)]
7979
#[allow(clippy::large_enum_variant)]
8080
pub enum DecodedChainSyncEvent {
8181
RollForward {
8282
peer: Peer,
8383
point: Point,
8484
header: Header,
85+
#[serde(skip, default = "Span::none")]
8586
span: Span,
8687
},
8788
Rollback {
8889
peer: Peer,
8990
rollback_point: Point,
91+
#[serde(skip, default = "Span::none")]
9092
span: Span,
9193
},
9294
}

crates/amaru-consensus/src/consensus/store.rs

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,18 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use amaru_kernel::{protocol_parameters::GlobalParameters, EraHistory, Nonce, Point, RawBlock};
15+
use amaru_kernel::{
16+
network::NetworkName, protocol_parameters::GlobalParameters, EraHistory, Header, Nonce, Point,
17+
RawBlock,
18+
};
1619
use amaru_ouroboros::{praos::nonce, Nonces};
1720
use amaru_ouroboros_traits::{IsHeader, Praos};
1821
use pallas_crypto::hash::Hash;
1922
use slot_arithmetic::TimeHorizonError;
20-
use std::fmt::Display;
23+
use std::{collections::BTreeMap, fmt::Display};
2124
use thiserror::Error;
2225

23-
#[derive(Error, PartialEq, Debug)]
26+
#[derive(Error, PartialEq, Debug, serde::Serialize, serde::Deserialize)]
2427
pub enum StoreError {
2528
WriteError { error: String },
2629
ReadError { error: String },
@@ -86,7 +89,7 @@ impl<H: IsHeader> ChainStore<H> for Box<dyn ChainStore<H>> {
8689
}
8790
}
8891

89-
#[derive(Error, Debug, PartialEq)]
92+
#[derive(Error, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
9093
pub enum NoncesError {
9194
#[error("cannot find nonces: unknown parent {parent} from header {header}")]
9295
UnknownParent { header: Hash<32>, parent: Hash<32> },
@@ -189,6 +192,44 @@ impl<H: IsHeader> Praos<H> for dyn ChainStore<H> {
189192
}
190193
}
191194

195+
#[derive(Default)]
196+
pub struct FakeStore {
197+
headers: BTreeMap<Hash<32>, Header>,
198+
nonces: BTreeMap<Hash<32>, Nonces>,
199+
}
200+
201+
impl ChainStore<Header> for FakeStore {
202+
fn load_header(&self, hash: &Hash<32>) -> Option<Header> {
203+
self.headers.get(hash).cloned()
204+
}
205+
206+
fn store_header(&mut self, hash: &Hash<32>, header: &Header) -> Result<(), StoreError> {
207+
self.headers.insert(*hash, header.clone());
208+
Ok(())
209+
}
210+
211+
fn get_nonces(&self, header: &Hash<32>) -> Option<Nonces> {
212+
self.nonces.get(header).cloned()
213+
}
214+
215+
fn put_nonces(&mut self, header: &Hash<32>, nonces: &Nonces) -> Result<(), StoreError> {
216+
self.nonces.insert(*header, nonces.clone());
217+
Ok(())
218+
}
219+
220+
fn era_history(&self) -> &EraHistory {
221+
NetworkName::Preprod.into()
222+
}
223+
224+
fn load_block(&self, _hash: &Hash<32>) -> Result<RawBlock, StoreError> {
225+
unimplemented!()
226+
}
227+
228+
fn store_block(&mut self, _hash: &Hash<32>, _block: &RawBlock) -> Result<(), StoreError> {
229+
unimplemented!()
230+
}
231+
}
232+
192233
#[cfg(test)]
193234
mod test {
194235
use super::*;
@@ -197,7 +238,7 @@ mod test {
197238
use amaru_ouroboros_traits::{IsHeader, Praos};
198239
use proptest::{prelude::*, prop_compose, proptest};
199240
use slot_arithmetic::Epoch;
200-
use std::{collections::BTreeMap, sync::LazyLock};
241+
use std::sync::LazyLock;
201242

202243
// Epoch 164's last header
203244
include_header!(PREPROD_HEADER_69638382, 69638382);
@@ -242,44 +283,6 @@ mod test {
242283
tail: hash!("d6fe6439aed8bddc10eec22c1575bf0648e4a76125387d9e985e9a3f8342870d"),
243284
});
244285

245-
#[derive(Default)]
246-
struct FakeStore {
247-
headers: BTreeMap<Hash<32>, Header>,
248-
nonces: BTreeMap<Hash<32>, Nonces>,
249-
}
250-
251-
impl ChainStore<Header> for FakeStore {
252-
fn load_header(&self, hash: &Hash<32>) -> Option<Header> {
253-
self.headers.get(hash).cloned()
254-
}
255-
256-
fn store_header(&mut self, hash: &Hash<32>, header: &Header) -> Result<(), StoreError> {
257-
self.headers.insert(*hash, header.clone());
258-
Ok(())
259-
}
260-
261-
fn get_nonces(&self, header: &Hash<32>) -> Option<Nonces> {
262-
self.nonces.get(header).cloned()
263-
}
264-
265-
fn put_nonces(&mut self, header: &Hash<32>, nonces: &Nonces) -> Result<(), StoreError> {
266-
self.nonces.insert(*header, nonces.clone());
267-
Ok(())
268-
}
269-
270-
fn era_history(&self) -> &EraHistory {
271-
NetworkName::Preprod.into()
272-
}
273-
274-
fn load_block(&self, _hash: &Hash<32>) -> Result<RawBlock, StoreError> {
275-
unimplemented!()
276-
}
277-
278-
fn store_block(&mut self, _hash: &Hash<32>, _block: &RawBlock) -> Result<(), StoreError> {
279-
unimplemented!()
280-
}
281-
}
282-
283286
fn evolve_nonce(
284287
last_header_last_epoch: &Header,
285288
parent: (&Header, &Nonces),

crates/amaru-consensus/src/consensus/store_header.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,20 @@ use tokio::sync::Mutex;
2020

2121
use super::DecodedChainSyncEvent;
2222

23+
#[derive(serde::Serialize, serde::Deserialize)]
2324
pub struct StoreHeader {
25+
#[serde(skip, default = "default_store")]
2426
pub store: Arc<Mutex<dyn ChainStore<Header>>>,
2527
}
28+
fn default_store() -> Arc<Mutex<dyn ChainStore<Header>>> {
29+
Arc::new(Mutex::new(super::store::FakeStore::default()))
30+
}
31+
32+
impl PartialEq for StoreHeader {
33+
fn eq(&self, _other: &Self) -> bool {
34+
true
35+
}
36+
}
2637

2738
impl fmt::Debug for StoreHeader {
2839
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

crates/amaru-consensus/src/consensus/validate_header.rs

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,46 @@ pub fn header_is_valid(
5656
.map_err(|e| ConsensusError::InvalidHeader(point.clone(), e))
5757
}
5858

59-
#[derive(Clone)]
59+
#[derive(Clone, serde::Serialize, serde::Deserialize)]
6060
pub struct ValidateHeader {
61+
#[serde(skip, default = "default_ledger")]
6162
pub ledger: Arc<dyn HasStakeDistribution>,
63+
#[serde(skip, default = "default_store")]
6264
pub store: Arc<Mutex<dyn ChainStore<Header>>>,
6365
}
6466

67+
impl PartialEq for ValidateHeader {
68+
fn eq(&self, _other: &Self) -> bool {
69+
true
70+
}
71+
}
72+
73+
fn default_ledger() -> Arc<dyn HasStakeDistribution> {
74+
struct Fake;
75+
impl HasStakeDistribution for Fake {
76+
fn get_pool(
77+
&self,
78+
_slot: amaru_kernel::Slot,
79+
_pool: &amaru_kernel::PoolId,
80+
) -> Option<amaru_ouroboros::PoolSummary> {
81+
unimplemented!()
82+
}
83+
84+
fn slot_to_kes_period(&self, _slot: amaru_kernel::Slot) -> u64 {
85+
unimplemented!()
86+
}
87+
88+
fn max_kes_evolutions(&self) -> u64 {
89+
unimplemented!()
90+
}
91+
92+
fn latest_opcert_sequence_number(&self, _pool: &amaru_kernel::PoolId) -> Option<u64> {
93+
unimplemented!()
94+
}
95+
}
96+
Arc::new(Fake)
97+
}
98+
6599
impl fmt::Debug for ValidateHeader {
66100
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67101
f.debug_struct("ValidateHeader")
@@ -71,12 +105,24 @@ impl fmt::Debug for ValidateHeader {
71105
}
72106
}
73107

108+
#[derive(serde::Serialize, serde::Deserialize)]
74109
struct EvolveNonceEffect {
110+
#[serde(skip, default = "default_store")]
75111
store: Arc<Mutex<dyn ChainStore<Header>>>,
76112
header: Header,
77113
global_parameters: GlobalParameters,
78114
}
79115

116+
impl PartialEq for EvolveNonceEffect {
117+
fn eq(&self, other: &Self) -> bool {
118+
self.header == other.header && self.global_parameters == other.global_parameters
119+
}
120+
}
121+
122+
fn default_store() -> Arc<Mutex<dyn ChainStore<Header>>> {
123+
Arc::new(Mutex::new(super::store::FakeStore::default()))
124+
}
125+
80126
impl EvolveNonceEffect {
81127
fn new(
82128
store: Arc<Mutex<dyn ChainStore<Header>>>,
@@ -101,25 +147,16 @@ impl fmt::Debug for EvolveNonceEffect {
101147
}
102148

103149
impl ExternalEffect for EvolveNonceEffect {
104-
fn run(self: Box<Self>) -> pure_stage::BoxFuture<'static, Box<dyn pure_stage::Message>> {
150+
fn run(self: Box<Self>) -> pure_stage::BoxFuture<'static, Box<dyn pure_stage::SendData>> {
105151
Box::pin(async move {
106152
let result = self
107153
.store
108154
.lock()
109155
.await
110156
.evolve_nonce(&self.header, &self.global_parameters);
111-
Box::new(result) as Box<dyn pure_stage::Message>
157+
Box::new(result) as Box<dyn pure_stage::SendData>
112158
})
113159
}
114-
115-
fn test_eq(&self, other: &dyn ExternalEffect) -> bool {
116-
other
117-
.cast_ref::<Self>()
118-
.map(|other| {
119-
self.header == other.header && self.global_parameters == other.global_parameters
120-
})
121-
.unwrap_or(false)
122-
}
123160
}
124161

125162
impl ExternalEffectAPI for EvolveNonceEffect {

crates/amaru-consensus/src/peer.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
use std::fmt::Display;
1616

1717
/// A single peer in the network, with a unique identifier.
18-
#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
18+
#[derive(
19+
Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
20+
)]
1921
pub struct Peer {
2022
pub name: String,
2123
}

crates/amaru-kernel/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ impl From<&RequiredScript> for RedeemersKey {
142142
}
143143
}
144144

145-
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
145+
#[derive(Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
146146
pub enum Point {
147147
Origin,
148148
Specific(u64, Vec<u8>),

crates/amaru-kernel/src/protocol_parameters.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ impl<C> cbor::encode::Encode<C> for ProtocolParameters {
309309
}
310310
}
311311

312-
#[derive(Debug, Clone, PartialEq)]
312+
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
313313
pub struct GlobalParameters {
314314
/// The maximum depth of a rollback, also known as the security parameter 'k'.
315315
/// This translates down to the length of our volatile storage, containing states of the ledger

0 commit comments

Comments
 (0)