From 0d51179922e61e8ff7dd93419bdaac13c8bdc7e3 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Tue, 1 Oct 2024 15:44:04 +0200 Subject: [PATCH 01/53] Scaffold new hydra source - use tokio-tungstenite to communicate with hydra node - deserialize some messages and pass data to oura To run, first start the hydra demo: ```bash cd hydra/demo ./prepare-devnet.sh docker compose up -d cardano-node ./seed-devnet.sh docker compose up -d hydra-node-{1,2,3} ``` Then, in this repositroy, run: ```bash cargo run daemon --config examples/hydra/daemon.toml ``` --- Cargo.lock | 50 +++++- Cargo.toml | 4 + examples/hydra/daemon.toml | 25 +++ src/sources/hydra.rs | 301 +++++++++++++++++++++++++++++++++++++ src/sources/mod.rs | 11 ++ 5 files changed, 389 insertions(+), 2 deletions(-) create mode 100644 examples/hydra/daemon.toml create mode 100644 src/sources/hydra.rs diff --git a/Cargo.lock b/Cargo.lock index 8f2cc968..7e65c217 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1088,9 +1088,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "bytes-utils" @@ -1802,6 +1802,12 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + [[package]] name = "debugid" version = "0.8.0" @@ -4107,6 +4113,7 @@ dependencies = [ "aws-sdk-sqs", "aws-types", "bech32 0.9.1", + "bytes", "clap", "config", "crossterm", @@ -4115,6 +4122,7 @@ dependencies = [ "extism", "file-rotate", "futures", + "futures-util", "gasket", "gasket-prometheus", "google-cloud-default", @@ -4144,9 +4152,11 @@ dependencies = [ "strum_macros 0.25.3", "thiserror", "tokio", + "tokio-tungstenite", "tonic 0.11.0", "tracing", "tracing-subscriber", + "tungstenite", "unicode-truncate", ] @@ -6751,6 +6761,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -6983,6 +7005,24 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 1.0.0", + "httparse", + "log", + "rand", + "sha1 0.10.6", + "thiserror", + "utf-8", +] + [[package]] name = "twox-hash" version = "1.6.3" @@ -7157,6 +7197,12 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8parse" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index d8387ac3..186ec51d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,3 +79,7 @@ extism = { version = "1.2.0", optional = true } mithril-client = { version = "^0.8", optional = true, features = ["fs"] } miette = { version = "7.2.0", features = ["fancy"] } itertools = "0.12.1" +tungstenite = "0.24.0" +tokio-tungstenite = "0.24.0" +futures-util = "0.3" +bytes = "1.7.2" diff --git a/examples/hydra/daemon.toml b/examples/hydra/daemon.toml new file mode 100644 index 00000000..ca894433 --- /dev/null +++ b/examples/hydra/daemon.toml @@ -0,0 +1,25 @@ +[source] +type = "Hydra" +hydra_socket_url = "ws://127.0.0.1:4001" +magic = 42 + +[chain] +type = "custom" +magic = 42 +network_id = 1 +byron_epoch_length = 21600 +byron_slot_length = 20 +byron_known_slot = 18 +byron_known_hash = "96f058d2ab8abb3a7726ef7b18bfba4b9003e84819c59b0a9406a63d48ad274a" +byron_known_time = 1506203091 +shelley_epoch_length = 432000 +shelley_slot_length = 1 +shelley_known_slot = 18 +shelley_known_hash = "96f058d2ab8abb3a7726ef7b18bfba4b9003e84819c59b0a9406a63d48ad274a" +shelley_known_time = 1596491091 + +[intersect] +type = "Tip" + +[sink] +type = "Stdout" diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs new file mode 100644 index 00000000..1518aaf7 --- /dev/null +++ b/src/sources/hydra.rs @@ -0,0 +1,301 @@ +use std::collections::HashMap; +use tokio::net::TcpStream; +use tokio_tungstenite::MaybeTlsStream; + +use bytes::Bytes; + +use pallas::network::miniprotocols::Point; +use pallas::ledger::addresses::Address; + +use pallas::interop::utxorpc::spec::cardano::{TxOutput, TxInput, Tx}; + +use gasket::framework::*; +use serde::{Deserialize, Serialize, Deserializer}; +use tracing::{debug, info, warn}; + +use tokio_tungstenite::WebSocketStream; +use futures_util::StreamExt; +use tokio_tungstenite::{connect_async, tungstenite::protocol::Message}; + +use crate::framework::*; + + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "tag", rename_all = "PascalCase")] +pub enum HydraMessage { + #[serde(deserialize_with = "deserialize_head_is_open")] + HeadIsOpen { txs: Vec }, // FIXME: revisit; see comments in impl + + + #[serde(deserialize_with = "deserialize_tx_valid")] + TxValid { tx: Vec}, // TODO: Use Tx instead? + // +// SnapshotConfirmed { snapshot: Snapshot }, + + #[serde(other)] + SomethingElse, +} + + +// Example json: +// { +// "headId": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab" +// "seq": 15 +// "timestamp": "2024-10-03T11:38:45.449663464Z", +// "transaction": { +// "cborHex": "84a300d9010281825820635ffa4d3f8b5ccd60a89918866a5bb0776966572324da9a86870f79dcce4aad01018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a0098968082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a039387000200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840c1f23b630cf3d0ffe4186436225906c81bcddb0a27a632696035d4bb2d32e646c81759789c35c940b9695a87a0978a0408cff550c8d8f9ab4ac6d6d29b82a109f5f6", +// "description": "Ledger Cddl Format", +// "txId": "08bb77374329ca28cd3023cace2948d0fc23e2812e8998c966db8b457e6390fe", +// "type": "Witnessed Tx ConwayEra", +// }, +// } +fn deserialize_tx_valid<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + + #[derive(Debug, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct TxValidJson { + transaction: TxCborJson + } + #[derive(Debug, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct TxCborJson { + cbor_hex: String + } + + let msg = TxValidJson::deserialize(deserializer)?; + let cbor = hex::decode(msg.transaction.cbor_hex) + .map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded cbor")))?; + + Ok(cbor) +} + + +fn deserialize_head_is_open<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + #[derive(Debug, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct HeadIsOpenJson { + utxo: HashMap + } + #[derive(Debug, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct TxOutJson { + address: String, + datum: Option, + datumhash: Option, + inline_datum: Option, + reference_script: Option, + value: HashMap + } + // Access the `utxo` field within the JSON object + let msg = HeadIsOpenJson::deserialize(deserializer)?; + + + // FIXME: Do we really want to turn the utxo of the HeadIsOpen message to pseodo-txs? + // Kupo may have done this out of necessity. We may not need to. + let mut txs = Vec::new(); + + for (in_str, out_json) in msg.utxo.iter() { + let parts: Vec<&str> = in_str.split('#').collect(); + if parts.len() != 2 { return Err(serde::de::Error::custom("Invalid transaction input format")); } + let hash_vec = hex::decode(parts[0]) + .map_err(|e| serde::de::Error::custom(format!("Failed to parse transaction ID: {}", e)))?; + let hash = Bytes::from(hash_vec); + let ix = parts[1].parse::() + .map_err(|e| serde::de::Error::custom(format!("Failed to parse transaction index: {}", e)))?; + + let _i = TxInput { + tx_hash: hash.clone(), + output_index: ix, + as_output: None, + redeemer: None, + }; + + let addr = Address::from_bech32(&out_json.address) + .map_err(|_| serde::de::Error::custom("invalid address"))? + .to_vec(); + + let o = TxOutput { + address: Bytes::from(addr), + coin: 0, // TODO + assets: [].to_vec(), // TODO + datum: None, // TODO + script: None, // TODO + }; + + // FIXME: Temporary + let tx = Tx { + inputs: [].to_vec(), + outputs: [o].to_vec(), // FIXME: This is utterly wrong! The ix is not captured. + certificates: [].to_vec(), + withdrawals: [].to_vec(), + mint: [].to_vec(), + reference_inputs: [].to_vec(), + witnesses: None, + collateral: None, + fee: 0, + validity: None, + successful: true, + auxiliary: None, + hash: hash, + }; + + txs.push(tx); + } + + + Ok(txs) + +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Snapshot { + number: u64, + confirmed_transaction_ids: Vec, +} +type HydraConnection = WebSocketStream>; + +#[derive(Stage)] +#[stage( + name = "source", + unit = "Message", + worker = "Worker" +)] +pub struct Stage { + config: Config, + + chain: GenesisValues, + + intersect: IntersectConfig, + + breadcrumbs: Breadcrumbs, + + pub output: SourceOutputPort, + + #[metric] + ops_count: gasket::metrics::Counter, + + #[metric] + chain_tip: gasket::metrics::Gauge, + + #[metric] + current_slot: gasket::metrics::Gauge, + + #[metric] + rollback_count: gasket::metrics::Counter, +} + +pub struct Worker { + socket: HydraConnection, +} + +impl Worker { + async fn process_next( + &mut self, + stage: &mut Stage, + next: HydraMessage, + ) -> Result<(), WorkerError> { + match next { + HydraMessage::HeadIsOpen { txs } => { + // FIXME: Dummy values + let slot = 0; + let hash = vec![0u8; 32]; + let point = Point::Specific(slot, hash.to_vec()); + + for tx in txs { + let evt = ChainEvent::Apply(point.clone(), Record::ParsedTx(tx)); + stage.output.send(evt.into()).await.or_panic()?; + stage.ops_count.inc(1); + }; + + }, + HydraMessage::TxValid { tx } => { + // FIXME: Dummy values + let slot = 0; + let hash = vec![0u8; 32]; + let point = Point::Specific(slot, hash.to_vec()); + + let evt = ChainEvent::Apply(point.clone(), Record::CborTx(tx)); + stage.output.send(evt.into()).await.or_panic()?; + stage.ops_count.inc(1); + + // FIXME: Ensure we do everything we should here (c.f. n2c implementation) + } + + _ => (), + }; + + Ok(()) + } +} + +#[async_trait::async_trait(?Send)] +impl gasket::framework::Worker for Worker { + async fn bootstrap(stage: &Stage) -> Result { + debug!("connecting to hydra WebSocket"); + + let url = &stage.config.hydra_socket_url; + let (socket, _) = connect_async(url).await.expect("Can't connect"); + let worker = Self { socket }; + + Ok(worker) + } + + async fn schedule(&mut self, _stage: &mut Stage) -> Result, WorkerError> { + let next_msg = self.socket.next().await.transpose().or_restart()?; + + Ok(match next_msg { + Some(message) => WorkSchedule::Unit(message), + None => WorkSchedule::Idle, + }) + } + + async fn execute(&mut self, message: &Message, stage: &mut Stage) -> Result<(), WorkerError> { + match message { + Message::Text(text) => { + match serde_json::from_str::(text) { + Ok(hydra_message) => { + self.process_next(stage, hydra_message).await; + } + Err(err) => { + warn!("Failed to deserialize hydra message: {}", err); + } + } + } + Message::Binary(data) => { + debug!("Received binary data: {:?}", data); + } + _ => {} + } + + Ok(()) + } +} + +#[derive(Deserialize)] +pub struct Config { + hydra_socket_url: String, +} + +impl Config { + pub fn bootstrapper(self, ctx: &Context) -> Result { + let stage = Stage { + config: self, + breadcrumbs: ctx.breadcrumbs.clone(), + chain: ctx.chain.clone().into(), + intersect: ctx.intersect.clone(), + output: Default::default(), + ops_count: Default::default(), + chain_tip: Default::default(), + current_slot: Default::default(), + rollback_count: Default::default(), + }; + + Ok(stage) + } +} diff --git a/src/sources/mod.rs b/src/sources/mod.rs index 87cb3950..cd41bdd7 100644 --- a/src/sources/mod.rs +++ b/src/sources/mod.rs @@ -8,6 +8,7 @@ use crate::framework::*; pub mod n2c; pub mod n2n; +pub mod hydra; #[cfg(feature = "u5c")] pub mod u5c; @@ -24,6 +25,8 @@ pub enum Bootstrapper { #[cfg(target_family = "unix")] N2C(n2c::Stage), + Hydra(hydra::Stage), + #[cfg(feature = "u5c")] U5C(u5c::Stage), @@ -42,6 +45,8 @@ impl Bootstrapper { #[cfg(target_family = "unix")] Bootstrapper::N2C(p) => &mut p.output, + Bootstrapper::Hydra(p) => &mut p.output, + #[cfg(feature = "u5c")] Bootstrapper::U5C(p) => &mut p.output, @@ -60,6 +65,8 @@ impl Bootstrapper { #[cfg(target_family = "unix")] Bootstrapper::N2C(x) => gasket::runtime::spawn_stage(x, policy), + Bootstrapper::Hydra(x) => gasket::runtime::spawn_stage(x, policy), + #[cfg(feature = "u5c")] Bootstrapper::U5C(x) => gasket::runtime::spawn_stage(x, policy), @@ -80,6 +87,8 @@ pub enum Config { #[cfg(target_family = "unix")] N2C(n2c::Config), + Hydra(hydra::Config), + #[cfg(feature = "u5c")] U5C(u5c::Config), @@ -98,6 +107,8 @@ impl Config { #[cfg(target_family = "unix")] Config::N2C(c) => Ok(Bootstrapper::N2C(c.bootstrapper(ctx)?)), + Config::Hydra(c) => Ok(Bootstrapper::Hydra(c.bootstrapper(ctx)?)), + #[cfg(feature = "u5c")] Config::U5C(c) => Ok(Bootstrapper::U5C(c.bootstrapper(ctx)?)), From 2228417d884ffbaea8c84c0b1867da263062bc19 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Tue, 8 Oct 2024 15:35:23 +0200 Subject: [PATCH 02/53] testing skeleton and test scenario vectors added --- tests/hydra.rs | 20 ++++++++++++++++++++ tests/hydra/scenario_1.txt | 23 +++++++++++++++++++++++ tests/hydra/scenario_2.txt | 30 ++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 tests/hydra.rs create mode 100644 tests/hydra/scenario_1.txt create mode 100644 tests/hydra/scenario_2.txt diff --git a/tests/hydra.rs b/tests/hydra.rs new file mode 100644 index 00000000..a22913c7 --- /dev/null +++ b/tests/hydra.rs @@ -0,0 +1,20 @@ +use std::fs; + +use oura::sources::hydra::HydraMessage; + +type TestResult = Result<(), Box>; + +fn run_scenario(_expected_msgs: &[HydraMessage], expected_file: &str) -> TestResult { + let _file = fs::read_to_string(expected_file)?; + Ok(()) +} + +#[test] +fn hydra_scenario_1() -> TestResult { + run_scenario(&[HydraMessage::SomethingElse], "tests/hydra/scenario_1.txt") +} + +#[test] +fn hydra_scenario_2() -> TestResult { + run_scenario(&[HydraMessage::SomethingElse], "tests/hydra/scenario_2.txt") +} diff --git a/tests/hydra/scenario_1.txt b/tests/hydra/scenario_1.txt new file mode 100644 index 00000000..575d1697 --- /dev/null +++ b/tests/hydra/scenario_1.txt @@ -0,0 +1,23 @@ +{"peer":"3","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.556003751Z"} +{"peer":"2","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.559653645Z"} +{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:04:56.445761285Z"} +1 +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","parties":[{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"}],"seq":2,"tag":"HeadIsInitializing","timestamp":"2024-10-08T13:05:47.330461177Z"} +2 +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":3,"tag":"Committed","timestamp":"2024-10-08T13:05:56.918549005Z","utxo":{"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}}} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},"seq":4,"tag":"Committed","timestamp":"2024-10-08T13:06:05.615623261Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}}}} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"},"seq":5,"tag":"Committed","timestamp":"2024-10-08T13:06:17.51514695Z","utxo":{"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":6,"tag":"HeadIsOpen","timestamp":"2024-10-08T13:06:18.687120539Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}},"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}} +3 +4 +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":7,"tag":"TxValid","timestamp":"2024-10-08T13:07:18.008847436Z","transaction":{"cborHex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858401b13ee550f3167a1b94796f2a2f5e22d782d628336a7797c5b798f358fa564dbe92ea75a4e2449eb2cef59c097d8497545ef1e4ea441b88a481194323ae7c608f5f6","description":"Ledger Cddl Format","txId":"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1","type":"Witnessed Tx ConwayEra"}} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":8,"signatures":{"multiSignature":["71c368f5f9b124d6b327132fbbf7e92939a88ddcc26e2e06ee17f23318b2bb9c8fa87ebb92d63b6d9cf53ff7612140ea5b7084951ec422d41f909b97f5e64904","51d78ed466a67c4acacf588772d3cc6bf72325e83c318c5ac6a1d90a10ba132a225fa48240570b6254df2c831f952a72213984d0953b22d49a1de1fbfb38540a","993126e89e417fcff9135d7cedc9fa2b46dcf1c9d2ccaa64e5400b782ef40643afe69e73983ee3517492f1816dc99a5dd29002ca9b2d5182bd24e00c9e40b105"]},"snapshot":{"confirmedTransactions":["633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":1,"utxo":{"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":23000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:07:18.064534686Z"} +5 +{"contestationDeadline":"2024-10-08T13:07:37.7Z","headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":9,"snapshotNumber":1,"tag":"HeadIsClosed","timestamp":"2024-10-08T13:07:31.814065753Z"} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":10,"tag":"ReadyToFanout","timestamp":"2024-10-08T13:07:37.807683329Z"} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":11,"tag":"HeadIsFinalized","timestamp":"2024-10-08T13:07:40.815046135Z","utxo":{"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":23000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}}} +6 +7 +8 +9 +10 diff --git a/tests/hydra/scenario_2.txt b/tests/hydra/scenario_2.txt new file mode 100644 index 00000000..c64b7061 --- /dev/null +++ b/tests/hydra/scenario_2.txt @@ -0,0 +1,30 @@ +{"peer":"2","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.954897681Z"} +{"peer":"3","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.98647342Z"} +{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:21:28.141876427Z"} +1 +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","parties":[{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"}],"seq":2,"tag":"HeadIsInitializing","timestamp":"2024-10-08T13:22:05.725778923Z"} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":3,"tag":"Committed","timestamp":"2024-10-08T13:22:11.016254447Z","utxo":{"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}}} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},"seq":4,"tag":"Committed","timestamp":"2024-10-08T13:22:18.915120931Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}}}} +2 +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"},"seq":5,"tag":"Committed","timestamp":"2024-10-08T13:22:30.313144555Z","utxo":{"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":6,"tag":"HeadIsOpen","timestamp":"2024-10-08T13:22:30.520745142Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}},"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":7,"tag":"TxValid","timestamp":"2024-10-08T13:22:44.316966394Z","transaction":{"cborHex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858407342c0c4de1b55bc9e56c86829a1fb5906e964f109fd698d37d5933ed230b1a878bfee20980bb90b48aa32c472fdd465c2eb770551b84de7041838415faed502f5f6","description":"Ledger Cddl Format","txId":"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617","type":"Witnessed Tx ConwayEra"}} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":8,"signatures":{"multiSignature":["e9eaa5edf35b35872c94d9b11b1074e8dc737a24ad5956a7c982ee7eb3d2bfe31def724b8a8e586e30806b50ed55984e331a3fae986bc12e6e705e1138164400","7058aca64e437169677db810048bbfc1e0714bbf348cd43c37c46f3d836dc251e09ca7d2a2d6c89e87b2e7d7f4b110024ecbcec59f694370079a069df1903d03","e55bfb59691c93dfd6343a034cf9c78b03261e7d51a16e61e8fd7257378b563b8de6568abd88ddeb532d109e3ad33c6454b268b6ee6b29849786ac5691898603"]},"snapshot":{"confirmedTransactions":["65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":1,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":23000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:22:44.360477345Z"} +3 +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":9,"tag":"TxValid","timestamp":"2024-10-08T13:23:18.169555579Z","transaction":{"cborHex":"84a300d901028182582065d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e5161701018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a0016e36082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a014810600200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf85840b991c62af8e2b2d06f821fb6064f98c2fc8909b0b2d81435c7e075a61fc92ee6c9224f23d817de35d5529f54034c2ab8dfaded387e99fc525344846bb5dc860af5f6","description":"Ledger Cddl Format","txId":"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af","type":"Witnessed Tx ConwayEra"}} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":10,"signatures":{"multiSignature":["5897602f543c3692cfb691119b2e9feb22e2302333b3200f95fa65feffaa0846abeb293afc8dcbd4ba2ac4b0ba1df729730d2e3b5e69a652f99b52fa15729209","d2268afebbbde31886cf8ce1c7b827f92a1c675bc9dee5603d6d87d7c30d9f7ae46d596095a6e03624d2526fe101b026c9c765abb7e2603b06ffb4fa6ecc6b0e","b3342f10a0678c24bff40ab5d394b8d7382419b826bfbbc3c019a8c4fd20d6d4db9eec29d72fb58ceb09dfe6720ae5c8ade77fd49e2a4b7e884beeb93f027b00"]},"snapshot":{"confirmedTransactions":["a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":2,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:23:18.220733933Z"} +4 +5 +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":11,"tag":"TxValid","timestamp":"2024-10-08T13:24:09.770902618Z","transaction":{"cborHex":"84a300d90102818258207b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c69700018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a00a7d8c082581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a025317c00200a100d9010281825820aa268d154185c9ea06ea73442fd8143c34c1dd543b7142bcb132aac0d1ed6ece5840fc6e2b0750259deedd5a73eeadf481138bf82edc3425614871a0ef09bfcf8cae52a80240fb895a7e6a8ad94d4acb32dffe567ed0d338afcd7878f745737f420df5f6","description":"Ledger Cddl Format","txId":"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce","type":"Witnessed Tx ConwayEra"}} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":12,"signatures":{"multiSignature":["aa0673de465f1e7f4ca472b85315243ca2327f15778b3625b8a225563fd4dbb083e2ff9e50bb3a4680a3d1a3da89a839ed841f18c3f85770bf669fe268418608","c682e3bc61e3bf78db64a6bfdd48588e3aafcba62bdb507b8f6b56b364985e575d7185505f33597a45782edff46687d67281e65cf19c7dbbbc68b80b4ed92605","7efc7a1846184214ea2d6748f3db82a34c3be0d9af310d685a47f24e2694223b03611111902512c5674729553440c57755f340694589ccc94e093732b9630908"]},"snapshot":{"confirmedTransactions":["de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":3,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:24:09.825917124Z"} +6 +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":13,"tag":"TxValid","timestamp":"2024-10-08T13:24:30.136780836Z","transaction":{"cborHex":"84a300d9010281825820c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d9700018282581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a00c65d4082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a052f83c00200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840ac8f1632d9a636d3627328ffd09cd32e1b654cbf318f0ce499a9870b05530041aa0badf07cd43fec8f1456537ada71227bea8123c1ed641ae3cb22b7313d5f08f5f6","description":"Ledger Cddl Format","txId":"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74","type":"Witnessed Tx ConwayEra"}} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":14,"signatures":{"multiSignature":["cdd5844d70c2ad9d6e6981f922757cc5aff7785b425ffcbff83347f2ad9545c646bae9c75f6b65d23aad9452e17704d76cbd5e948408e73277cafa2858cb9104","a1551898f0c4b0f2a9b5a94998a18b9ca962dc92f24d4e5308a0dd449eaf1661c1e075fbc9895ad6f0bbbcd141eb251c9e08493d04adff01125a15906f919701","976e8a5fc707c4e048d266344a2af1a43e94dd7ca29f395d1735c70562ff915af22e9b9829f5058eb02d734e625bd30ada7cbb49060098ad27d6c8a747e9740f"]},"snapshot":{"confirmedTransactions":["bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":4,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":13000000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#1":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":87000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:24:30.186588075Z"} +{"contestationDeadline":"2024-10-08T13:24:42.6Z","headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":15,"snapshotNumber":4,"tag":"HeadIsClosed","timestamp":"2024-10-08T13:24:36.81629911Z"} +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":16,"tag":"ReadyToFanout","timestamp":"2024-10-08T13:24:42.708785607Z"} +7 +{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":17,"tag":"HeadIsFinalized","timestamp":"2024-10-08T13:25:02.420848196Z","utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":13000000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#1":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":87000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}}} +8 +9 +10 +11 From 3f69d8649c4da19b334768254bb303b01ce37cd5 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Fri, 4 Oct 2024 11:32:33 +0200 Subject: [PATCH 03/53] Make sure to log unrecognized hydra messages --- src/sources/hydra.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 1518aaf7..10dab534 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -32,8 +32,8 @@ pub enum HydraMessage { // // SnapshotConfirmed { snapshot: Snapshot }, - #[serde(other)] - SomethingElse, +// #[serde(other)] +// SomethingElse, } @@ -263,7 +263,7 @@ impl gasket::framework::Worker for Worker { self.process_next(stage, hydra_message).await; } Err(err) => { - warn!("Failed to deserialize hydra message: {}", err); + debug!("Some other hydra message: {}", text); } } } From 5835339f124b49dd6268f73bbfa2e21cca0a40da Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Tue, 8 Oct 2024 22:52:23 +0200 Subject: [PATCH 04/53] Polish and use `point = (seq, head_id)` --- src/sources/hydra.rs | 177 +++++++++++++++++++++++++++---------------- 1 file changed, 112 insertions(+), 65 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 10dab534..2d510be7 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -6,36 +6,65 @@ use bytes::Bytes; use pallas::network::miniprotocols::Point; use pallas::ledger::addresses::Address; - -use pallas::interop::utxorpc::spec::cardano::{TxOutput, TxInput, Tx}; +use pallas::interop::utxorpc::spec::cardano::{TxOutput, Tx}; use gasket::framework::*; -use serde::{Deserialize, Serialize, Deserializer}; -use tracing::{debug, info, warn}; +use tracing::{debug, warn}; use tokio_tungstenite::WebSocketStream; use futures_util::StreamExt; use tokio_tungstenite::{connect_async, tungstenite::protocol::Message}; +use serde::{Deserialize, Serialize, Deserializer}; +use serde_json::Value; +use serde::de::{self}; + use crate::framework::*; +// Models /most/ hydra messages. Messages without head_id are excluded. +pub struct HydraMessage { + seq: u64, + head_id: Vec, + payload: HydraMessagePayload +} -#[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(tag = "tag", rename_all = "PascalCase")] -pub enum HydraMessage { - #[serde(deserialize_with = "deserialize_head_is_open")] - HeadIsOpen { txs: Vec }, // FIXME: revisit; see comments in impl +impl<'de> Deserialize<'de> for HydraMessage { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let map: Value = Deserialize::deserialize(deserializer)?; + let seq = map.get("seq") + .ok_or_else(|| de::Error::missing_field("seq"))? + .as_u64() + .ok_or_else(|| de::Error::custom("seq should be a u64"))?; - #[serde(deserialize_with = "deserialize_tx_valid")] - TxValid { tx: Vec}, // TODO: Use Tx instead? - // -// SnapshotConfirmed { snapshot: Snapshot }, + let head_id_str = map.get("headId") + .ok_or_else(|| de::Error::missing_field("headId"))? + .as_str() + .ok_or_else(|| de::Error::custom("headId should be a string"))?; + + let head_id = hex::decode(head_id_str) + .map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded headId")))?; -// #[serde(other)] -// SomethingElse, + let payload = HydraMessagePayload::deserialize(&map) + .map_err(de::Error::custom)?; + + Ok(HydraMessage { seq, head_id, payload }) + } } +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "tag", rename_all = "PascalCase")] +pub enum HydraMessagePayload { + #[serde(deserialize_with = "deserialize_head_is_open")] + HeadIsOpen { txs: Vec, }, // FIXME: revisit; see comments in impl + #[serde(deserialize_with = "deserialize_tx_valid")] + TxValid { tx: Vec }, // TODO: Use Tx instead? + #[serde(other)] + Other +} // Example json: // { @@ -57,7 +86,7 @@ where #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TxValidJson { - transaction: TxCborJson + transaction: TxCborJson, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -73,6 +102,36 @@ where } +// Example JSON: +// { +// "headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab", +// "seq":6, +// "tag":"HeadIsOpen", +// "timestamp":"2024-10-07T11:45:12.219902045Z", +// "utxo": { +// "060d5256c6335978f59c8434dfec2f814276983c41949ffc150fa9a0d0cd5f6f#0": { +// "address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c", +// "datum":null, +// "datumhash":null, +// "inlineDatum":null, +// "referenceScript":null, +// "value":{"lovelace":25000000}}, +// "9dce218cadb86ec5e26e9bdddab614efa722f1d72f8b98eade4b5ce52bb2eb8a#0": { +// "address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh", +// "datum":null, +// "datumhash":null, +// "inlineDatum":null, +// "referenceScript":null, +// "value":{"lovelace":50000000}}, +// "d683dda48161cef8015c40c55a51569c85631d294dc5e4ce39a29a54939ca6f3#0": { +// "address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z", +// "datum":null, +// "datumhash":null, +// "inlineDatum":null, +// "referenceScript":null, +// "value":{"lovelace":100000000}} +// } +// } fn deserialize_head_is_open<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, @@ -80,7 +139,7 @@ where #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct HeadIsOpenJson { - utxo: HashMap + utxo: HashMap, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -106,15 +165,6 @@ where let hash_vec = hex::decode(parts[0]) .map_err(|e| serde::de::Error::custom(format!("Failed to parse transaction ID: {}", e)))?; let hash = Bytes::from(hash_vec); - let ix = parts[1].parse::() - .map_err(|e| serde::de::Error::custom(format!("Failed to parse transaction index: {}", e)))?; - - let _i = TxInput { - tx_hash: hash.clone(), - output_index: ix, - as_output: None, - redeemer: None, - }; let addr = Address::from_bech32(&out_json.address) .map_err(|_| serde::de::Error::custom("invalid address"))? @@ -142,13 +192,12 @@ where validity: None, successful: true, auxiliary: None, - hash: hash, + hash, }; txs.push(tx); } - Ok(txs) } @@ -200,36 +249,39 @@ impl Worker { stage: &mut Stage, next: HydraMessage, ) -> Result<(), WorkerError> { - match next { - HydraMessage::HeadIsOpen { txs } => { - // FIXME: Dummy values - let slot = 0; - let hash = vec![0u8; 32]; - let point = Point::Specific(slot, hash.to_vec()); - - for tx in txs { - let evt = ChainEvent::Apply(point.clone(), Record::ParsedTx(tx)); - stage.output.send(evt.into()).await.or_panic()?; - stage.ops_count.inc(1); - }; - - }, - HydraMessage::TxValid { tx } => { - // FIXME: Dummy values - let slot = 0; - let hash = vec![0u8; 32]; - let point = Point::Specific(slot, hash.to_vec()); - - let evt = ChainEvent::Apply(point.clone(), Record::CborTx(tx)); - stage.output.send(evt.into()).await.or_panic()?; - stage.ops_count.inc(1); - - // FIXME: Ensure we do everything we should here (c.f. n2c implementation) - } - _ => (), + // As a first implementation, we'll treat the msg seq number + // as a slot number, and the head id as a block hash. + // + // This means all points on the same chain will share the same block hash, but hopefully + // this shouldn't matter. + let slot = next.seq; + let hash = next.head_id; + let point = Point::Specific(slot, hash); + + let events = match next.payload { + HydraMessagePayload::HeadIsOpen { txs } => { + txs.into_iter() + .map (|tx| ChainEvent::Apply(point.clone(), Record::ParsedTx(tx)) ) + .collect() + }, + HydraMessagePayload::TxValid { tx } => { + [ChainEvent::Apply(point.clone(), Record::CborTx(tx))].to_vec() + } + HydraMessagePayload::Other => [].to_vec() }; + for evt in events { + stage.output.send(evt.into()).await.or_panic()?; + stage.ops_count.inc(1); + } + + stage.breadcrumbs.track(point.clone()); + + stage.chain_tip.set(point.slot_or_default() as i64); + stage.current_slot.set(point.slot_or_default() as i64); + stage.ops_count.inc(1); + Ok(()) } } @@ -258,22 +310,17 @@ impl gasket::framework::Worker for Worker { async fn execute(&mut self, message: &Message, stage: &mut Stage) -> Result<(), WorkerError> { match message { Message::Text(text) => { + debug!("Hydra message: {}", text); match serde_json::from_str::(text) { - Ok(hydra_message) => { - self.process_next(stage, hydra_message).await; - } + Ok(hydra_message) => self.process_next(stage, hydra_message).await, Err(err) => { - debug!("Some other hydra message: {}", text); + warn!("Failed to parse Hydra message: {}", err); + Ok(()) } } } - Message::Binary(data) => { - debug!("Received binary data: {:?}", data); - } - _ => {} + _ => Ok(()) } - - Ok(()) } } From bc48a28fff313ddd3d8859ac7564050f05027b13 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Wed, 9 Oct 2024 15:48:30 +0200 Subject: [PATCH 05/53] Drop `HeadIsOpen` message and make tests compile --- src/sources/hydra.rs | 188 ++++++++----------------------------------- tests/hydra.rs | 8 +- 2 files changed, 37 insertions(+), 159 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 2d510be7..724be035 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -1,15 +1,10 @@ -use std::collections::HashMap; use tokio::net::TcpStream; use tokio_tungstenite::MaybeTlsStream; -use bytes::Bytes; - use pallas::network::miniprotocols::Point; -use pallas::ledger::addresses::Address; -use pallas::interop::utxorpc::spec::cardano::{TxOutput, Tx}; use gasket::framework::*; -use tracing::{debug, warn}; +use tracing::{debug, error}; use tokio_tungstenite::WebSocketStream; use futures_util::StreamExt; @@ -21,11 +16,9 @@ use serde::de::{self}; use crate::framework::*; -// Models /most/ hydra messages. Messages without head_id are excluded. pub struct HydraMessage { - seq: u64, - head_id: Vec, - payload: HydraMessagePayload + pub seq: u64, + pub payload: HydraMessagePayload } impl<'de> Deserialize<'de> for HydraMessage { @@ -40,28 +33,18 @@ impl<'de> Deserialize<'de> for HydraMessage { .as_u64() .ok_or_else(|| de::Error::custom("seq should be a u64"))?; - let head_id_str = map.get("headId") - .ok_or_else(|| de::Error::missing_field("headId"))? - .as_str() - .ok_or_else(|| de::Error::custom("headId should be a string"))?; - - let head_id = hex::decode(head_id_str) - .map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded headId")))?; - let payload = HydraMessagePayload::deserialize(&map) .map_err(de::Error::custom)?; - Ok(HydraMessage { seq, head_id, payload }) + Ok(HydraMessage { seq, payload }) } } #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(tag = "tag", rename_all = "PascalCase")] pub enum HydraMessagePayload { - #[serde(deserialize_with = "deserialize_head_is_open")] - HeadIsOpen { txs: Vec, }, // FIXME: revisit; see comments in impl #[serde(deserialize_with = "deserialize_tx_valid")] - TxValid { tx: Vec }, // TODO: Use Tx instead? + TxValid { tx: Vec, head_id: Vec }, // TODO: Use Tx instead? #[serde(other)] Other } @@ -78,15 +61,15 @@ pub enum HydraMessagePayload { // "type": "Witnessed Tx ConwayEra", // }, // } -fn deserialize_tx_valid<'de, D>(deserializer: D) -> Result, D::Error> +fn deserialize_tx_valid<'de, D>(deserializer: D) -> Result<(Vec, Vec), D::Error> where D: Deserializer<'de>, { - #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TxValidJson { transaction: TxCborJson, + head_id: String } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -98,108 +81,11 @@ where let cbor = hex::decode(msg.transaction.cbor_hex) .map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded cbor")))?; - Ok(cbor) -} + let head_id = hex::decode(msg.head_id) + .map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded headId")))?; -// Example JSON: -// { -// "headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab", -// "seq":6, -// "tag":"HeadIsOpen", -// "timestamp":"2024-10-07T11:45:12.219902045Z", -// "utxo": { -// "060d5256c6335978f59c8434dfec2f814276983c41949ffc150fa9a0d0cd5f6f#0": { -// "address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c", -// "datum":null, -// "datumhash":null, -// "inlineDatum":null, -// "referenceScript":null, -// "value":{"lovelace":25000000}}, -// "9dce218cadb86ec5e26e9bdddab614efa722f1d72f8b98eade4b5ce52bb2eb8a#0": { -// "address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh", -// "datum":null, -// "datumhash":null, -// "inlineDatum":null, -// "referenceScript":null, -// "value":{"lovelace":50000000}}, -// "d683dda48161cef8015c40c55a51569c85631d294dc5e4ce39a29a54939ca6f3#0": { -// "address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z", -// "datum":null, -// "datumhash":null, -// "inlineDatum":null, -// "referenceScript":null, -// "value":{"lovelace":100000000}} -// } -// } -fn deserialize_head_is_open<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - #[derive(Debug, Serialize, Deserialize)] - #[serde(rename_all = "camelCase")] - pub struct HeadIsOpenJson { - utxo: HashMap, - } - #[derive(Debug, Serialize, Deserialize)] - #[serde(rename_all = "camelCase")] - pub struct TxOutJson { - address: String, - datum: Option, - datumhash: Option, - inline_datum: Option, - reference_script: Option, - value: HashMap - } - // Access the `utxo` field within the JSON object - let msg = HeadIsOpenJson::deserialize(deserializer)?; - - - // FIXME: Do we really want to turn the utxo of the HeadIsOpen message to pseodo-txs? - // Kupo may have done this out of necessity. We may not need to. - let mut txs = Vec::new(); - - for (in_str, out_json) in msg.utxo.iter() { - let parts: Vec<&str> = in_str.split('#').collect(); - if parts.len() != 2 { return Err(serde::de::Error::custom("Invalid transaction input format")); } - let hash_vec = hex::decode(parts[0]) - .map_err(|e| serde::de::Error::custom(format!("Failed to parse transaction ID: {}", e)))?; - let hash = Bytes::from(hash_vec); - - let addr = Address::from_bech32(&out_json.address) - .map_err(|_| serde::de::Error::custom("invalid address"))? - .to_vec(); - - let o = TxOutput { - address: Bytes::from(addr), - coin: 0, // TODO - assets: [].to_vec(), // TODO - datum: None, // TODO - script: None, // TODO - }; - - // FIXME: Temporary - let tx = Tx { - inputs: [].to_vec(), - outputs: [o].to_vec(), // FIXME: This is utterly wrong! The ix is not captured. - certificates: [].to_vec(), - withdrawals: [].to_vec(), - mint: [].to_vec(), - reference_inputs: [].to_vec(), - witnesses: None, - collateral: None, - fee: 0, - validity: None, - successful: true, - auxiliary: None, - hash, - }; - - txs.push(tx); - } - - Ok(txs) - + Ok((cbor, head_id)) } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -249,39 +135,29 @@ impl Worker { stage: &mut Stage, next: HydraMessage, ) -> Result<(), WorkerError> { - - // As a first implementation, we'll treat the msg seq number - // as a slot number, and the head id as a block hash. - // - // This means all points on the same chain will share the same block hash, but hopefully - // this shouldn't matter. - let slot = next.seq; - let hash = next.head_id; - let point = Point::Specific(slot, hash); - - let events = match next.payload { - HydraMessagePayload::HeadIsOpen { txs } => { - txs.into_iter() - .map (|tx| ChainEvent::Apply(point.clone(), Record::ParsedTx(tx)) ) - .collect() - }, - HydraMessagePayload::TxValid { tx } => { - [ChainEvent::Apply(point.clone(), Record::CborTx(tx))].to_vec() + match next.payload { + HydraMessagePayload::TxValid { tx, head_id } => { + // As a first implementation, we'll treat the msg seq number + // as a slot number, and the head id as a block hash. + // + // This means all points on the same chain will share the same block hash, but hopefully + // this shouldn't matter. + let slot = next.seq; + let hash = head_id; + let point = Point::Specific(slot, hash); + + let evt = ChainEvent::Apply(point.clone(), Record::CborTx(tx)); + stage.output.send(evt.into()).await.or_panic()?; + stage.ops_count.inc(1); + + stage.breadcrumbs.track(point.clone()); + + stage.chain_tip.set(point.slot_or_default() as i64); + stage.current_slot.set(point.slot_or_default() as i64); + stage.ops_count.inc(1); } - HydraMessagePayload::Other => [].to_vec() + HydraMessagePayload::Other => () }; - - for evt in events { - stage.output.send(evt.into()).await.or_panic()?; - stage.ops_count.inc(1); - } - - stage.breadcrumbs.track(point.clone()); - - stage.chain_tip.set(point.slot_or_default() as i64); - stage.current_slot.set(point.slot_or_default() as i64); - stage.ops_count.inc(1); - Ok(()) } } @@ -314,7 +190,7 @@ impl gasket::framework::Worker for Worker { match serde_json::from_str::(text) { Ok(hydra_message) => self.process_next(stage, hydra_message).await, Err(err) => { - warn!("Failed to parse Hydra message: {}", err); + error!("Failed to parse Hydra message: {}", err); Ok(()) } } diff --git a/tests/hydra.rs b/tests/hydra.rs index a22913c7..4683188b 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -1,6 +1,6 @@ use std::fs; -use oura::sources::hydra::HydraMessage; +use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; type TestResult = Result<(), Box>; @@ -11,10 +11,12 @@ fn run_scenario(_expected_msgs: &[HydraMessage], expected_file: &str) -> TestRes #[test] fn hydra_scenario_1() -> TestResult { - run_scenario(&[HydraMessage::SomethingElse], "tests/hydra/scenario_1.txt") + let msgs = [ HydraMessage { seq: 0, payload: HydraMessagePayload::Other } ]; + run_scenario(&msgs, "tests/hydra/scenario_1.txt") } #[test] fn hydra_scenario_2() -> TestResult { - run_scenario(&[HydraMessage::SomethingElse], "tests/hydra/scenario_2.txt") + let msgs = [ HydraMessage { seq: 0, payload: HydraMessagePayload::Other } ]; + run_scenario(&msgs, "tests/hydra/scenario_2.txt") } From 6348e2d175add681845a8eb19f46018aaac3613f Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Fri, 11 Oct 2024 05:38:01 +0200 Subject: [PATCH 06/53] failing unit test TxValid --- src/sources/hydra.rs | 48 +++++++++++++++----------------------------- tests/hydra.rs | 45 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 34 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 724be035..b885148b 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -6,19 +6,20 @@ use pallas::network::miniprotocols::Point; use gasket::framework::*; use tracing::{debug, error}; -use tokio_tungstenite::WebSocketStream; use futures_util::StreamExt; +use tokio_tungstenite::WebSocketStream; use tokio_tungstenite::{connect_async, tungstenite::protocol::Message}; -use serde::{Deserialize, Serialize, Deserializer}; -use serde_json::Value; use serde::de::{self}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_json::Value; use crate::framework::*; +#[derive(PartialEq, Debug)] pub struct HydraMessage { pub seq: u64, - pub payload: HydraMessagePayload + pub payload: HydraMessagePayload, } impl<'de> Deserialize<'de> for HydraMessage { @@ -28,39 +29,27 @@ impl<'de> Deserialize<'de> for HydraMessage { { let map: Value = Deserialize::deserialize(deserializer)?; - let seq = map.get("seq") + let seq = map + .get("seq") .ok_or_else(|| de::Error::missing_field("seq"))? .as_u64() .ok_or_else(|| de::Error::custom("seq should be a u64"))?; - let payload = HydraMessagePayload::deserialize(&map) - .map_err(de::Error::custom)?; + let payload = HydraMessagePayload::deserialize(&map).map_err(de::Error::custom)?; Ok(HydraMessage { seq, payload }) } } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] #[serde(tag = "tag", rename_all = "PascalCase")] pub enum HydraMessagePayload { #[serde(deserialize_with = "deserialize_tx_valid")] - TxValid { tx: Vec, head_id: Vec }, // TODO: Use Tx instead? + TxValid { tx: Vec, head_id: Vec }, #[serde(other)] - Other + Other, } -// Example json: -// { -// "headId": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab" -// "seq": 15 -// "timestamp": "2024-10-03T11:38:45.449663464Z", -// "transaction": { -// "cborHex": "84a300d9010281825820635ffa4d3f8b5ccd60a89918866a5bb0776966572324da9a86870f79dcce4aad01018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a0098968082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a039387000200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840c1f23b630cf3d0ffe4186436225906c81bcddb0a27a632696035d4bb2d32e646c81759789c35c940b9695a87a0978a0408cff550c8d8f9ab4ac6d6d29b82a109f5f6", -// "description": "Ledger Cddl Format", -// "txId": "08bb77374329ca28cd3023cace2948d0fc23e2812e8998c966db8b457e6390fe", -// "type": "Witnessed Tx ConwayEra", -// }, -// } fn deserialize_tx_valid<'de, D>(deserializer: D) -> Result<(Vec, Vec), D::Error> where D: Deserializer<'de>, @@ -69,19 +58,18 @@ where #[serde(rename_all = "camelCase")] pub struct TxValidJson { transaction: TxCborJson, - head_id: String + head_id: String, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TxCborJson { - cbor_hex: String + cbor_hex: String, } let msg = TxValidJson::deserialize(deserializer)?; let cbor = hex::decode(msg.transaction.cbor_hex) .map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded cbor")))?; - let head_id = hex::decode(msg.head_id) .map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded headId")))?; @@ -96,11 +84,7 @@ pub struct Snapshot { type HydraConnection = WebSocketStream>; #[derive(Stage)] -#[stage( - name = "source", - unit = "Message", - worker = "Worker" -)] +#[stage(name = "source", unit = "Message", worker = "Worker")] pub struct Stage { config: Config, @@ -156,7 +140,7 @@ impl Worker { stage.current_slot.set(point.slot_or_default() as i64); stage.ops_count.inc(1); } - HydraMessagePayload::Other => () + HydraMessagePayload::Other => (), }; Ok(()) } @@ -195,7 +179,7 @@ impl gasket::framework::Worker for Worker { } } } - _ => Ok(()) + _ => Ok(()), } } } diff --git a/tests/hydra.rs b/tests/hydra.rs index 4683188b..0210bdc5 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -9,14 +9,55 @@ fn run_scenario(_expected_msgs: &[HydraMessage], expected_file: &str) -> TestRes Ok(()) } +fn test_event_deserialization(expected: HydraMessage, input: &str) -> TestResult { + let deserialized: HydraMessage = serde_json::from_str(&input)?; + assert_eq!(deserialized, expected); + Ok(()) +} + #[test] fn hydra_scenario_1() -> TestResult { - let msgs = [ HydraMessage { seq: 0, payload: HydraMessagePayload::Other } ]; + let msgs = [HydraMessage { + seq: 0, + payload: HydraMessagePayload::Other, + }]; run_scenario(&msgs, "tests/hydra/scenario_1.txt") } #[test] fn hydra_scenario_2() -> TestResult { - let msgs = [ HydraMessage { seq: 0, payload: HydraMessagePayload::Other } ]; + let msgs = [HydraMessage { + seq: 0, + payload: HydraMessagePayload::Other, + }]; run_scenario(&msgs, "tests/hydra/scenario_2.txt") } + +#[test] +fn tx_valid_evt() -> TestResult { + let evt = HydraMessage { + seq: 15, + payload: HydraMessagePayload::TxValid { + tx: "84a300d9010281825820635ffa4d3f8b5ccd60a89918866a5bb0776966572324da9a86870f79dcce4aad01018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a0098968082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a039387000200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840c1f23b630cf3d0ffe4186436225906c81bcddb0a27a632696035d4bb2d32e646c81759789c35c940b9695a87a0978a0408cff550c8d8f9ab4ac6d6d29b82a109f5f6".as_bytes() + .to_vec(), + head_id: "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab".as_bytes() + .to_vec(), + }, + }; + + let raw_str = r#" + { + "headId": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab", + "seq": 15, + "timestamp": "2024-10-03T11:38:45.449663464Z", + "tag":"TxValid", + "transaction": { + "cborHex": "84a300d9010281825820635ffa4d3f8b5ccd60a89918866a5bb0776966572324da9a86870f79dcce4aad01018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a0098968082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a039387000200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840c1f23b630cf3d0ffe4186436225906c81bcddb0a27a632696035d4bb2d32e646c81759789c35c940b9695a87a0978a0408cff550c8d8f9ab4ac6d6d29b82a109f5f6", + "description": "Ledger Cddl Format", + "txId": "08bb77374329ca28cd3023cace2948d0fc23e2812e8998c966db8b457e6390fe", + "type": "Witnessed Tx ConwayEra" + } + } +"#; + test_event_deserialization(evt, &raw_str) +} From 6720a24198cdc68f62c742ec8a7beecb630b416b Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Fri, 11 Oct 2024 12:49:21 +0200 Subject: [PATCH 07/53] Make sure to decode the hex of the expected values in the tests --- tests/hydra.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index 0210bdc5..1076a5eb 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -38,9 +38,10 @@ fn tx_valid_evt() -> TestResult { let evt = HydraMessage { seq: 15, payload: HydraMessagePayload::TxValid { - tx: "84a300d9010281825820635ffa4d3f8b5ccd60a89918866a5bb0776966572324da9a86870f79dcce4aad01018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a0098968082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a039387000200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840c1f23b630cf3d0ffe4186436225906c81bcddb0a27a632696035d4bb2d32e646c81759789c35c940b9695a87a0978a0408cff550c8d8f9ab4ac6d6d29b82a109f5f6".as_bytes() + tx: hex::decode("84a300d9010281825820635ffa4d3f8b5ccd60a89918866a5bb0776966572324da9a86870f79dcce4aad01018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a0098968082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a039387000200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840c1f23b630cf3d0ffe4186436225906c81bcddb0a27a632696035d4bb2d32e646c81759789c35c940b9695a87a0978a0408cff550c8d8f9ab4ac6d6d29b82a109f5f6") + .unwrap() .to_vec(), - head_id: "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab".as_bytes() + head_id: hex::decode("84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab").unwrap() .to_vec(), }, }; From 91f9005bb98bd0efaf07e0af4f66f24344342b0c Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Tue, 15 Oct 2024 18:10:56 +0200 Subject: [PATCH 08/53] Add basic intersect logic to hydra source This allows us to resume processing from a point specified in the config. Tested manually using the following steps: 1. Ensure hydra demo is running 2. `cargo run daemon --config examples/hydra/daemon.toml` 3. Read the `seq` and `head_id` of the last message printed 4. Set the following in `hydra/daemon.toml`: ``` [intersect] type = "Point" value = [ 7, "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab" ] ``` but with `7` and `84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab` being the actually observed `seq` and `head_id` values. 5. Restart `oura` 6. Observe that `oura` ignores all previously processed messages --- examples/hydra/daemon.toml | 2 +- src/sources/hydra.rs | 45 +++++++++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/examples/hydra/daemon.toml b/examples/hydra/daemon.toml index ca894433..08dff024 100644 --- a/examples/hydra/daemon.toml +++ b/examples/hydra/daemon.toml @@ -19,7 +19,7 @@ shelley_known_hash = "96f058d2ab8abb3a7726ef7b18bfba4b9003e84819c59b0a9406a63d48 shelley_known_time = 1596491091 [intersect] -type = "Tip" +type = "Origin" [sink] type = "Stdout" diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index b885148b..9d3b2987 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -4,7 +4,7 @@ use tokio_tungstenite::MaybeTlsStream; use pallas::network::miniprotocols::Point; use gasket::framework::*; -use tracing::{debug, error}; +use tracing::{debug, error, info}; use futures_util::StreamExt; use tokio_tungstenite::WebSocketStream; @@ -111,6 +111,7 @@ pub struct Stage { pub struct Worker { socket: HydraConnection, + intersect: Point, } impl Worker { @@ -146,14 +147,39 @@ impl Worker { } } +fn intersect_from_config(intersect: &IntersectConfig) -> Point { + match intersect { + IntersectConfig::Origin => { + info!("intersecting origin"); + Point::Origin + } + IntersectConfig::Tip => { + panic!("intersecting tip not currently supported with hydra as source") + } + IntersectConfig::Point(slot, hash_str) => { + info!("intersecting specific points"); + let hash = hex::decode(hash_str).expect("valid hex hash"); + Point::Specific(slot.clone(), hash) + } + IntersectConfig::Breadcrumbs(_) => { + panic!("intersecting breadcrumbs not currently supported with hydra as source") + } + } +} + #[async_trait::async_trait(?Send)] impl gasket::framework::Worker for Worker { async fn bootstrap(stage: &Stage) -> Result { debug!("connecting to hydra WebSocket"); + + let url = &stage.config.hydra_socket_url; let (socket, _) = connect_async(url).await.expect("Can't connect"); - let worker = Self { socket }; + let worker = Self { + socket, + intersect: intersect_from_config(&stage.intersect) + }; Ok(worker) } @@ -172,7 +198,20 @@ impl gasket::framework::Worker for Worker { Message::Text(text) => { debug!("Hydra message: {}", text); match serde_json::from_str::(text) { - Ok(hydra_message) => self.process_next(stage, hydra_message).await, + Ok(hydra_message) => { + // TODO: search for the intersection point to ensure + // we're on the same chain. + let should_process = match &self.intersect { + Point::Origin => true, + Point::Specific(slot,_hash) => &hydra_message.seq > slot + }; + if should_process { + self.process_next(stage, hydra_message).await + } else { + debug!("Skipping message before intersection"); + Ok(()) + } + } Err(err) => { error!("Failed to parse Hydra message: {}", err); Ok(()) From 93d31acf2fa4eb314137f89153d8be7515a60cf7 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Wed, 16 Oct 2024 17:16:21 +0200 Subject: [PATCH 09/53] Drop unused `chain` value in hydra config --- examples/hydra/daemon.toml | 15 --------------- src/sources/hydra.rs | 3 --- 2 files changed, 18 deletions(-) diff --git a/examples/hydra/daemon.toml b/examples/hydra/daemon.toml index 08dff024..f58b38bd 100644 --- a/examples/hydra/daemon.toml +++ b/examples/hydra/daemon.toml @@ -3,21 +3,6 @@ type = "Hydra" hydra_socket_url = "ws://127.0.0.1:4001" magic = 42 -[chain] -type = "custom" -magic = 42 -network_id = 1 -byron_epoch_length = 21600 -byron_slot_length = 20 -byron_known_slot = 18 -byron_known_hash = "96f058d2ab8abb3a7726ef7b18bfba4b9003e84819c59b0a9406a63d48ad274a" -byron_known_time = 1506203091 -shelley_epoch_length = 432000 -shelley_slot_length = 1 -shelley_known_slot = 18 -shelley_known_hash = "96f058d2ab8abb3a7726ef7b18bfba4b9003e84819c59b0a9406a63d48ad274a" -shelley_known_time = 1596491091 - [intersect] type = "Origin" diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 9d3b2987..91d69b9f 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -88,8 +88,6 @@ type HydraConnection = WebSocketStream>; pub struct Stage { config: Config, - chain: GenesisValues, - intersect: IntersectConfig, breadcrumbs: Breadcrumbs, @@ -233,7 +231,6 @@ impl Config { let stage = Stage { config: self, breadcrumbs: ctx.breadcrumbs.clone(), - chain: ctx.chain.clone().into(), intersect: ctx.intersect.clone(), output: Default::default(), ops_count: Default::default(), From 62743b0e75b33c334bc77919cb8531f4c421c110 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Wed, 16 Oct 2024 17:18:00 +0200 Subject: [PATCH 10/53] Drop unused `breadcrumbs` value in hydra config --- src/sources/hydra.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 91d69b9f..a62e1fbe 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -90,8 +90,6 @@ pub struct Stage { intersect: IntersectConfig, - breadcrumbs: Breadcrumbs, - pub output: SourceOutputPort, #[metric] @@ -133,8 +131,6 @@ impl Worker { stage.output.send(evt.into()).await.or_panic()?; stage.ops_count.inc(1); - stage.breadcrumbs.track(point.clone()); - stage.chain_tip.set(point.slot_or_default() as i64); stage.current_slot.set(point.slot_or_default() as i64); stage.ops_count.inc(1); @@ -230,7 +226,6 @@ impl Config { pub fn bootstrapper(self, ctx: &Context) -> Result { let stage = Stage { config: self, - breadcrumbs: ctx.breadcrumbs.clone(), intersect: ctx.intersect.clone(), output: Default::default(), ops_count: Default::default(), From 4a1d0ca81e4daf24b57881970d9d4995eafd4817 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Wed, 16 Oct 2024 18:12:27 +0200 Subject: [PATCH 11/53] Make "skipping message" debug log clearer --- src/sources/hydra.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index a62e1fbe..7e502fd0 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -195,15 +195,13 @@ impl gasket::framework::Worker for Worker { Ok(hydra_message) => { // TODO: search for the intersection point to ensure // we're on the same chain. - let should_process = match &self.intersect { - Point::Origin => true, - Point::Specific(slot,_hash) => &hydra_message.seq > slot - }; - if should_process { - self.process_next(stage, hydra_message).await - } else { - debug!("Skipping message before intersection"); - Ok(()) + match &self.intersect { + Point::Specific(slot,_hash) if &hydra_message.seq <= slot => { + debug!("Skipping message {} before or at intersection {}", hydra_message.seq, slot); + Ok(()) + } + Point::Origin | Point::Specific(_, _) => + self.process_next(stage, hydra_message).await } } Err(err) => { From 92cf03df6878c60120f53b1310a1a8edba8461f6 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Wed, 16 Oct 2024 18:16:38 +0200 Subject: [PATCH 12/53] fixup: whitespace and minor log message tweak --- src/sources/hydra.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 7e502fd0..6746aad1 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -151,7 +151,7 @@ fn intersect_from_config(intersect: &IntersectConfig) -> Point { panic!("intersecting tip not currently supported with hydra as source") } IntersectConfig::Point(slot, hash_str) => { - info!("intersecting specific points"); + info!("intersecting specific point"); let hash = hex::decode(hash_str).expect("valid hex hash"); Point::Specific(slot.clone(), hash) } @@ -166,8 +166,6 @@ impl gasket::framework::Worker for Worker { async fn bootstrap(stage: &Stage) -> Result { debug!("connecting to hydra WebSocket"); - - let url = &stage.config.hydra_socket_url; let (socket, _) = connect_async(url).await.expect("Can't connect"); let worker = Self { From 662c528e0b3db6dd4073d6ce4224cef97cc6f637 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Tue, 15 Oct 2024 22:16:10 +0200 Subject: [PATCH 13/53] Forward all `raw_json` of hydra messages With this we see output from oura like: ```json {"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":1},"record":{"peer":"2","seq":1,"tag":"PeerConnected","timestamp":"2024-10-15T11:48:00.516366926Z"}} ``` --- src/sources/hydra.rs | 61 +++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 6746aad1..571d07b3 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -19,7 +19,26 @@ use crate::framework::*; #[derive(PartialEq, Debug)] pub struct HydraMessage { pub seq: u64, + pub head_id: Option>, pub payload: HydraMessagePayload, + pub raw_json: Value + +} + +impl HydraMessage { + fn head_id_or_default(&self) -> Vec { + let dummy_hash = vec![0u8; 32]; + self.head_id.clone().unwrap_or(dummy_hash) + } + + /// As a first implementation, we'll treat the msg seq number + /// as a slot number, and the head id as a block hash. + /// + /// This means all points on the same chain will share the same block hash, but hopefully + /// this shouldn't matter. + fn pseudo_point(&self) -> Point { + Point::Specific(self.seq, self.head_id_or_default()) + } } impl<'de> Deserialize<'de> for HydraMessage { @@ -35,9 +54,20 @@ impl<'de> Deserialize<'de> for HydraMessage { .as_u64() .ok_or_else(|| de::Error::custom("seq should be a u64"))?; + let head_id_str: Option<&str> = map + .get("head_id") + .map(|v| v.as_str().ok_or_else(|| de::Error::custom("head_id should be a string"))) + .transpose()?; + + let head_id = head_id_str + .map(|s| hex::decode(s).map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded headId")))) + .transpose()?; + let payload = HydraMessagePayload::deserialize(&map).map_err(de::Error::custom)?; - Ok(HydraMessage { seq, payload }) + let raw_json = map; + + Ok(HydraMessage { seq, payload, raw_json, head_id }) } } @@ -45,12 +75,12 @@ impl<'de> Deserialize<'de> for HydraMessage { #[serde(tag = "tag", rename_all = "PascalCase")] pub enum HydraMessagePayload { #[serde(deserialize_with = "deserialize_tx_valid")] - TxValid { tx: Vec, head_id: Vec }, + TxValid { tx: Vec }, #[serde(other)] Other, } -fn deserialize_tx_valid<'de, D>(deserializer: D) -> Result<(Vec, Vec), D::Error> +fn deserialize_tx_valid<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { @@ -58,7 +88,6 @@ where #[serde(rename_all = "camelCase")] pub struct TxValidJson { transaction: TxCborJson, - head_id: String, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -70,10 +99,7 @@ where let cbor = hex::decode(msg.transaction.cbor_hex) .map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded cbor")))?; - let head_id = hex::decode(msg.head_id) - .map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded headId")))?; - - Ok((cbor, head_id)) + Ok(cbor) } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -116,17 +142,16 @@ impl Worker { stage: &mut Stage, next: HydraMessage, ) -> Result<(), WorkerError> { - match next.payload { - HydraMessagePayload::TxValid { tx, head_id } => { - // As a first implementation, we'll treat the msg seq number - // as a slot number, and the head id as a block hash. - // - // This means all points on the same chain will share the same block hash, but hopefully - // this shouldn't matter. - let slot = next.seq; - let hash = head_id; - let point = Point::Specific(slot, hash); + let point = next.pseudo_point(); + + // First, apply raw json messages regardless of message type + let json_evt = ChainEvent::Apply(point.clone(), Record::GenericJson(next.raw_json.clone())); + stage.output.send(json_evt.into()).await.or_panic()?; + stage.ops_count.inc(1); + // Apply CborTx events for any txs + match next.payload { + HydraMessagePayload::TxValid { tx } => { let evt = ChainEvent::Apply(point.clone(), Record::CborTx(tx)); stage.output.send(evt.into()).await.or_panic()?; stage.ops_count.inc(1); From 98a50d7cc0f088dbbf3217000d62bdad43a8360b Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 17 Oct 2024 13:36:59 +0200 Subject: [PATCH 14/53] fixing deserializer and tests --- src/sources/hydra.rs | 34 ++++++++++++++++++++++++---------- tests/hydra.rs | 21 +++++++++++++++++++-- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 571d07b3..22eeab71 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -21,8 +21,7 @@ pub struct HydraMessage { pub seq: u64, pub head_id: Option>, pub payload: HydraMessagePayload, - pub raw_json: Value - + pub raw_json: Value, } impl HydraMessage { @@ -55,19 +54,30 @@ impl<'de> Deserialize<'de> for HydraMessage { .ok_or_else(|| de::Error::custom("seq should be a u64"))?; let head_id_str: Option<&str> = map - .get("head_id") - .map(|v| v.as_str().ok_or_else(|| de::Error::custom("head_id should be a string"))) + .get("headId") + .map(|v| { + v.as_str() + .ok_or_else(|| de::Error::custom("head_id should be a string")) + }) .transpose()?; let head_id = head_id_str - .map(|s| hex::decode(s).map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded headId")))) + .map(|s| { + hex::decode(s) + .map_err(|_e| serde::de::Error::custom(format!("Expected hex-encoded headId"))) + }) .transpose()?; let payload = HydraMessagePayload::deserialize(&map).map_err(de::Error::custom)?; let raw_json = map; - Ok(HydraMessage { seq, payload, raw_json, head_id }) + Ok(HydraMessage { + seq, + payload, + raw_json, + head_id, + }) } } @@ -195,7 +205,7 @@ impl gasket::framework::Worker for Worker { let (socket, _) = connect_async(url).await.expect("Can't connect"); let worker = Self { socket, - intersect: intersect_from_config(&stage.intersect) + intersect: intersect_from_config(&stage.intersect), }; Ok(worker) @@ -219,12 +229,16 @@ impl gasket::framework::Worker for Worker { // TODO: search for the intersection point to ensure // we're on the same chain. match &self.intersect { - Point::Specific(slot,_hash) if &hydra_message.seq <= slot => { - debug!("Skipping message {} before or at intersection {}", hydra_message.seq, slot); + Point::Specific(slot, _hash) if &hydra_message.seq <= slot => { + debug!( + "Skipping message {} before or at intersection {}", + hydra_message.seq, slot + ); Ok(()) } - Point::Origin | Point::Specific(_, _) => + Point::Origin | Point::Specific(_, _) => { self.process_next(stage, hydra_message).await + } } } Err(err) => { diff --git a/tests/hydra.rs b/tests/hydra.rs index 1076a5eb..76396735 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -1,6 +1,7 @@ use std::fs; use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; +use serde_json::json; type TestResult = Result<(), Box>; @@ -19,7 +20,9 @@ fn test_event_deserialization(expected: HydraMessage, input: &str) -> TestResult fn hydra_scenario_1() -> TestResult { let msgs = [HydraMessage { seq: 0, + head_id: Some(vec![0u8; 32]), payload: HydraMessagePayload::Other, + raw_json: "".into(), }]; run_scenario(&msgs, "tests/hydra/scenario_1.txt") } @@ -28,7 +31,9 @@ fn hydra_scenario_1() -> TestResult { fn hydra_scenario_2() -> TestResult { let msgs = [HydraMessage { seq: 0, + head_id: Some(vec![0u8; 32]), payload: HydraMessagePayload::Other, + raw_json: "".into(), }]; run_scenario(&msgs, "tests/hydra/scenario_2.txt") } @@ -37,13 +42,25 @@ fn hydra_scenario_2() -> TestResult { fn tx_valid_evt() -> TestResult { let evt = HydraMessage { seq: 15, + head_id: Some(hex::decode("84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab").unwrap() + .to_vec()), payload: HydraMessagePayload::TxValid { tx: hex::decode("84a300d9010281825820635ffa4d3f8b5ccd60a89918866a5bb0776966572324da9a86870f79dcce4aad01018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a0098968082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a039387000200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840c1f23b630cf3d0ffe4186436225906c81bcddb0a27a632696035d4bb2d32e646c81759789c35c940b9695a87a0978a0408cff550c8d8f9ab4ac6d6d29b82a109f5f6") .unwrap() .to_vec(), - head_id: hex::decode("84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab").unwrap() - .to_vec(), }, + raw_json: json!( + { "headId": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab" + , "seq": 15 + , "tag": "TxValid" + , "timestamp": "2024-10-03T11:38:45.449663464Z" + , "transaction": + { "cborHex": "84a300d9010281825820635ffa4d3f8b5ccd60a89918866a5bb0776966572324da9a86870f79dcce4aad01018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a0098968082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a039387000200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840c1f23b630cf3d0ffe4186436225906c81bcddb0a27a632696035d4bb2d32e646c81759789c35c940b9695a87a0978a0408cff550c8d8f9ab4ac6d6d29b82a109f5f6" + , "description": "Ledger Cddl Format" + , "txId": "08bb77374329ca28cd3023cace2948d0fc23e2812e8998c966db8b457e6390fe" + , "type": "Witnessed Tx ConwayEra" + } + }), }; let raw_str = r#" From 5b7b885343792639229c180eea994cc208b5eb90 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 17 Oct 2024 15:10:19 +0200 Subject: [PATCH 15/53] make payload value optional and handle PeerConnected --- src/sources/hydra.rs | 17 +++++++++++------ tests/hydra.rs | 33 +++++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 22eeab71..52b1066c 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -20,7 +20,7 @@ use crate::framework::*; pub struct HydraMessage { pub seq: u64, pub head_id: Option>, - pub payload: HydraMessagePayload, + pub payload: Option, pub raw_json: Value, } @@ -57,7 +57,7 @@ impl<'de> Deserialize<'de> for HydraMessage { .get("headId") .map(|v| { v.as_str() - .ok_or_else(|| de::Error::custom("head_id should be a string")) + .ok_or_else(|| de::Error::custom("headId should be a string")) }) .transpose()?; @@ -68,8 +68,11 @@ impl<'de> Deserialize<'de> for HydraMessage { }) .transpose()?; - let payload = HydraMessagePayload::deserialize(&map).map_err(de::Error::custom)?; - + let payload0 = HydraMessagePayload::deserialize(&map).map_err(de::Error::custom)?; + let payload = match payload0 { + HydraMessagePayload::Other => None, + _ => Some(payload0), + }; let raw_json = map; Ok(HydraMessage { @@ -86,6 +89,8 @@ impl<'de> Deserialize<'de> for HydraMessage { pub enum HydraMessagePayload { #[serde(deserialize_with = "deserialize_tx_valid")] TxValid { tx: Vec }, + #[serde(skip_deserializing)] + PeerConnected, #[serde(other)] Other, } @@ -161,7 +166,7 @@ impl Worker { // Apply CborTx events for any txs match next.payload { - HydraMessagePayload::TxValid { tx } => { + Some(HydraMessagePayload::TxValid { tx }) => { let evt = ChainEvent::Apply(point.clone(), Record::CborTx(tx)); stage.output.send(evt.into()).await.or_panic()?; stage.ops_count.inc(1); @@ -170,7 +175,7 @@ impl Worker { stage.current_slot.set(point.slot_or_default() as i64); stage.ops_count.inc(1); } - HydraMessagePayload::Other => (), + _ => (), }; Ok(()) } diff --git a/tests/hydra.rs b/tests/hydra.rs index 76396735..1c1bb73d 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -21,7 +21,7 @@ fn hydra_scenario_1() -> TestResult { let msgs = [HydraMessage { seq: 0, head_id: Some(vec![0u8; 32]), - payload: HydraMessagePayload::Other, + payload: None, raw_json: "".into(), }]; run_scenario(&msgs, "tests/hydra/scenario_1.txt") @@ -32,7 +32,7 @@ fn hydra_scenario_2() -> TestResult { let msgs = [HydraMessage { seq: 0, head_id: Some(vec![0u8; 32]), - payload: HydraMessagePayload::Other, + payload: None, raw_json: "".into(), }]; run_scenario(&msgs, "tests/hydra/scenario_2.txt") @@ -44,11 +44,11 @@ fn tx_valid_evt() -> TestResult { seq: 15, head_id: Some(hex::decode("84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab").unwrap() .to_vec()), - payload: HydraMessagePayload::TxValid { + payload: Some(HydraMessagePayload::TxValid { tx: hex::decode("84a300d9010281825820635ffa4d3f8b5ccd60a89918866a5bb0776966572324da9a86870f79dcce4aad01018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a0098968082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a039387000200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840c1f23b630cf3d0ffe4186436225906c81bcddb0a27a632696035d4bb2d32e646c81759789c35c940b9695a87a0978a0408cff550c8d8f9ab4ac6d6d29b82a109f5f6") .unwrap() .to_vec(), - }, + }), raw_json: json!( { "headId": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab" , "seq": 15 @@ -79,3 +79,28 @@ fn tx_valid_evt() -> TestResult { "#; test_event_deserialization(evt, &raw_str) } + +#[test] +fn peer_connected_evt() -> TestResult { + let evt = HydraMessage { + seq: 0, + payload: None, + head_id: None, + raw_json: json!( + { "peer": "3" + , "seq": 0 + , "tag": "PeerConnected" + , "timestamp": "2024-10-08T13:01:20.556003751Z" + }), + }; + + let raw_str = r#" + { + "peer": "3", + "seq": 0, + "tag": "PeerConnected", + "timestamp": "2024-10-08T13:01:20.556003751Z" + } +"#; + test_event_deserialization(evt, &raw_str) +} From 4a929ad268eb1c5041b0259544d26b4716184307 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 17 Oct 2024 15:33:31 +0200 Subject: [PATCH 16/53] handle Idle --- src/sources/hydra.rs | 6 ++++-- tests/hydra.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 52b1066c..7f4f0f40 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -70,8 +70,8 @@ impl<'de> Deserialize<'de> for HydraMessage { let payload0 = HydraMessagePayload::deserialize(&map).map_err(de::Error::custom)?; let payload = match payload0 { - HydraMessagePayload::Other => None, - _ => Some(payload0), + HydraMessagePayload::TxValid { .. } => Some(payload0), + _ => None, }; let raw_json = map; @@ -91,6 +91,8 @@ pub enum HydraMessagePayload { TxValid { tx: Vec }, #[serde(skip_deserializing)] PeerConnected, + #[serde(alias = "Greetings")] + Idle, #[serde(other)] Other, } diff --git a/tests/hydra.rs b/tests/hydra.rs index 1c1bb73d..329a90e6 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -104,3 +104,36 @@ fn peer_connected_evt() -> TestResult { "#; test_event_deserialization(evt, &raw_str) } + +#[test] +fn idle_evt() -> TestResult { + let evt = HydraMessage { + seq: 2, + payload: None, + head_id: None, + raw_json: json!( + { "headStatus": "Idle" + , "hydraNodeVersion": "0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425" + , "me": + { "vkey": "b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb" + } + , "seq": 2 + , "tag": "Greetings" + , "timestamp": "2024-10-08T13:04:56.445761285Z" + }), + }; + + let raw_str = r#" + { + "headStatus": "Idle", + "hydraNodeVersion": "0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425", + "me": { + "vkey": "b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb" + }, + "seq": 2, + "tag": "Greetings", + "timestamp": "2024-10-08T13:04:56.445761285Z" + } +"#; + test_event_deserialization(evt, &raw_str) +} From b02b58d18617aafa9c130b61300b2350445f7db7 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 17 Oct 2024 15:37:03 +0200 Subject: [PATCH 17/53] add other events --- src/sources/hydra.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 7f4f0f40..a6c5653d 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -92,7 +92,23 @@ pub enum HydraMessagePayload { #[serde(skip_deserializing)] PeerConnected, #[serde(alias = "Greetings")] + #[serde(skip_deserializing)] Idle, + #[serde(skip_deserializing)] + HeadIsInitializing, + #[serde(skip_deserializing)] + Committed, + #[serde(skip_deserializing)] + HeadIsOpen, + #[serde(skip_deserializing)] + HeadIsClosed, + #[serde(skip_deserializing)] + SnapshotConfirmed, + #[serde(skip_deserializing)] + ReadyToFanout, + #[serde(skip_deserializing)] + HeadIsFinalized, + #[serde(other)] Other, } From 48fbfd8a3ff8978566cb1bc9b0fcefe3a933465e Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 17 Oct 2024 15:42:57 +0200 Subject: [PATCH 18/53] add test for Committed --- tests/hydra.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tests/hydra.rs b/tests/hydra.rs index 329a90e6..cb67aaf1 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -137,3 +137,57 @@ fn idle_evt() -> TestResult { "#; test_event_deserialization(evt, &raw_str) } + +#[test] +fn committed_evt() -> TestResult { + let evt = HydraMessage { + seq: 3, + payload: None, + head_id: Some( + hex::decode("84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab") + .unwrap() + .to_vec(), + ), + raw_json: json!( + { "headId": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab" + , "party": {"vkey": "b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"} + , "seq": 3 + , "tag": "Committed" + , "timestamp": "2024-10-08T13:05:56.918549005Z" + , "utxo": {"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0": + {"address": "addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z" + , "datum": null + , "datumhash": null + , "inlineDatum": null + , "referenceScript": null + , "value": {"lovelace": 100000000} + } + } + }), + }; + + let raw_str = r#" + { + "headId": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab", + "party": { + "vkey": "b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb" + }, + "seq": 3, + "tag": "Committed", + "timestamp": "2024-10-08T13:05:56.918549005Z", + "utxo": { + "c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0": { + "address": "addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z", + "datum": null, + "datumhash": null, + "inlineDatum": null, + "referenceScript": null, + "value": { + "lovelace": 100000000 + } + } + } + } +"#; + test_event_deserialization(evt, &raw_str) +} From 8583de369880ef88adbc6f1a0f1e719ad0a186f6 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Fri, 18 Oct 2024 10:06:02 +0200 Subject: [PATCH 19/53] Drop unneeded `Optional` from `payload` field --- src/sources/hydra.rs | 10 +++------- tests/hydra.rs | 35 ++++++----------------------------- 2 files changed, 9 insertions(+), 36 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index a6c5653d..3b391620 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -20,7 +20,7 @@ use crate::framework::*; pub struct HydraMessage { pub seq: u64, pub head_id: Option>, - pub payload: Option, + pub payload: HydraMessagePayload, pub raw_json: Value, } @@ -68,11 +68,7 @@ impl<'de> Deserialize<'de> for HydraMessage { }) .transpose()?; - let payload0 = HydraMessagePayload::deserialize(&map).map_err(de::Error::custom)?; - let payload = match payload0 { - HydraMessagePayload::TxValid { .. } => Some(payload0), - _ => None, - }; + let payload = HydraMessagePayload::deserialize(&map).map_err(de::Error::custom)?; let raw_json = map; Ok(HydraMessage { @@ -184,7 +180,7 @@ impl Worker { // Apply CborTx events for any txs match next.payload { - Some(HydraMessagePayload::TxValid { tx }) => { + HydraMessagePayload::TxValid { tx } => { let evt = ChainEvent::Apply(point.clone(), Record::CborTx(tx)); stage.output.send(evt.into()).await.or_panic()?; stage.ops_count.inc(1); diff --git a/tests/hydra.rs b/tests/hydra.rs index cb67aaf1..c43f4ab4 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -7,7 +7,7 @@ type TestResult = Result<(), Box>; fn run_scenario(_expected_msgs: &[HydraMessage], expected_file: &str) -> TestResult { let _file = fs::read_to_string(expected_file)?; - Ok(()) + panic!("unimplemented: run_scenario") } fn test_event_deserialization(expected: HydraMessage, input: &str) -> TestResult { @@ -15,40 +15,17 @@ fn test_event_deserialization(expected: HydraMessage, input: &str) -> TestResult assert_eq!(deserialized, expected); Ok(()) } - -#[test] -fn hydra_scenario_1() -> TestResult { - let msgs = [HydraMessage { - seq: 0, - head_id: Some(vec![0u8; 32]), - payload: None, - raw_json: "".into(), - }]; - run_scenario(&msgs, "tests/hydra/scenario_1.txt") -} - -#[test] -fn hydra_scenario_2() -> TestResult { - let msgs = [HydraMessage { - seq: 0, - head_id: Some(vec![0u8; 32]), - payload: None, - raw_json: "".into(), - }]; - run_scenario(&msgs, "tests/hydra/scenario_2.txt") -} - #[test] fn tx_valid_evt() -> TestResult { let evt = HydraMessage { seq: 15, head_id: Some(hex::decode("84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab").unwrap() .to_vec()), - payload: Some(HydraMessagePayload::TxValid { + payload: HydraMessagePayload::TxValid { tx: hex::decode("84a300d9010281825820635ffa4d3f8b5ccd60a89918866a5bb0776966572324da9a86870f79dcce4aad01018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a0098968082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a039387000200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840c1f23b630cf3d0ffe4186436225906c81bcddb0a27a632696035d4bb2d32e646c81759789c35c940b9695a87a0978a0408cff550c8d8f9ab4ac6d6d29b82a109f5f6") .unwrap() .to_vec(), - }), + }, raw_json: json!( { "headId": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab" , "seq": 15 @@ -84,7 +61,7 @@ fn tx_valid_evt() -> TestResult { fn peer_connected_evt() -> TestResult { let evt = HydraMessage { seq: 0, - payload: None, + payload: HydraMessagePayload::Other, head_id: None, raw_json: json!( { "peer": "3" @@ -109,7 +86,7 @@ fn peer_connected_evt() -> TestResult { fn idle_evt() -> TestResult { let evt = HydraMessage { seq: 2, - payload: None, + payload: HydraMessagePayload::Other, head_id: None, raw_json: json!( { "headStatus": "Idle" @@ -142,7 +119,7 @@ fn idle_evt() -> TestResult { fn committed_evt() -> TestResult { let evt = HydraMessage { seq: 3, - payload: None, + payload: HydraMessagePayload::Other, head_id: Some( hex::decode("84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab") .unwrap() From fba0423f3ab8ce3695e26e1bf875aac627345b6e Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Fri, 18 Oct 2024 10:12:57 +0200 Subject: [PATCH 20/53] Drop unneeded constructors of `HydraMessagePayload` I believe the `skip_deserializing` turn messages of these types into the `Other` payload anyway, so having them here is confusing. --- src/sources/hydra.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 3b391620..8d1bcf10 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -85,25 +85,6 @@ impl<'de> Deserialize<'de> for HydraMessage { pub enum HydraMessagePayload { #[serde(deserialize_with = "deserialize_tx_valid")] TxValid { tx: Vec }, - #[serde(skip_deserializing)] - PeerConnected, - #[serde(alias = "Greetings")] - #[serde(skip_deserializing)] - Idle, - #[serde(skip_deserializing)] - HeadIsInitializing, - #[serde(skip_deserializing)] - Committed, - #[serde(skip_deserializing)] - HeadIsOpen, - #[serde(skip_deserializing)] - HeadIsClosed, - #[serde(skip_deserializing)] - SnapshotConfirmed, - #[serde(skip_deserializing)] - ReadyToFanout, - #[serde(skip_deserializing)] - HeadIsFinalized, #[serde(other)] Other, From 8144d570a85ca9f0b96205676c7ecc6a15901865 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Tue, 22 Oct 2024 16:17:33 +0200 Subject: [PATCH 21/53] introduce HydraMessages --- Cargo.lock | 31 ++++++++++++----------- Cargo.toml | 1 + src/sources/hydra.rs | 7 +++++- tests/hydra.rs | 60 ++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 78 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e65c217..2a9ab06f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -918,9 +918,9 @@ checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64-simd" @@ -2206,7 +2206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a63bfc6d371d3b51d6094fd96c4c32a084ceefece3b4f4b328f30067d29da064" dependencies = [ "anyhow", - "base64 0.22.0", + "base64 0.22.1", "bytemuck", "extism-convert-macros", "prost 0.12.3", @@ -2234,7 +2234,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c7d16695dc6b72418e23b58c943411a08264332af403ae9870997b4d495c3d" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "serde", "serde_json", ] @@ -3807,7 +3807,7 @@ dependencies = [ "serde", "serde_bytes", "serde_json", - "serde_with 3.8.1", + "serde_with 3.11.0", "serde_yaml", "sha2", "slog", @@ -4147,6 +4147,7 @@ dependencies = [ "reqwest 0.11.24", "serde", "serde_json", + "serde_with 3.11.0", "sqlx", "strum 0.24.1", "strum_macros 0.25.3", @@ -4301,7 +4302,7 @@ version = "0.30.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12dc7f456f61479407f22afd29a58671c148c50c703b16ef09653406d131f0e0" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "hex", "num-rational", "pallas-addresses 0.30.2", @@ -4310,7 +4311,7 @@ dependencies = [ "pallas-primitives 0.30.2", "serde", "serde_json", - "serde_with 3.8.1", + "serde_with 3.11.0", ] [[package]] @@ -5282,7 +5283,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", @@ -5578,7 +5579,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "rustls-pki-types", ] @@ -5821,11 +5822,11 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", @@ -5833,7 +5834,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "serde_with_macros 3.8.1", + "serde_with_macros 3.11.0", "time", ] @@ -5863,9 +5864,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling 0.20.9", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 186ec51d..56194edf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ handlebars = "^5.1" config = { version = "0.13.2", default-features = false, features = ["toml", "yaml", "json"] } serde = { version = "1.0.152", features = ["derive"] } serde_json = { version = "1.0.104", features = ["arbitrary_precision"] } +serde_with = "3.11.0" strum = "0.24" strum_macros = "0.25" unicode-truncate = "0.2.0" diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 8d1bcf10..7707e404 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -13,10 +13,11 @@ use tokio_tungstenite::{connect_async, tungstenite::protocol::Message}; use serde::de::{self}; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::Value; +use serde_with::{formats::PreferMany, serde_as, OneOrMany}; use crate::framework::*; -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Debug, Clone)] pub struct HydraMessage { pub seq: u64, pub head_id: Option>, @@ -112,6 +113,10 @@ where Ok(cbor) } +#[serde_as] +#[derive(Deserialize, PartialEq, Debug, Clone)] +pub struct HydraMessages(#[serde_as(as = "OneOrMany<_, PreferMany>")] pub Vec); + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Snapshot { number: u64, diff --git a/tests/hydra.rs b/tests/hydra.rs index c43f4ab4..15430f76 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -1,20 +1,37 @@ use std::fs; -use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; +use oura::sources::hydra::{HydraMessage, HydraMessagePayload, HydraMessages}; use serde_json::json; type TestResult = Result<(), Box>; -fn run_scenario(_expected_msgs: &[HydraMessage], expected_file: &str) -> TestResult { - let _file = fs::read_to_string(expected_file)?; - panic!("unimplemented: run_scenario") -} +//fn run_scenario(expected_msgs: &Vec, expected_file: &str) -> TestResult { +// let input = fs::read_to_string(expected_file)?; +// let deserialized: HydraMessages = serde_json::from_str(&input)?; +// println!("deserialized {:?}", deserialized); +// assert_eq!( +// deserialized +// .0 +// .iter() +// .map(|msg| msg.payload.clone()) +// .collect::>(), +// *expected_msgs +// ); +// Ok(()) +//} fn test_event_deserialization(expected: HydraMessage, input: &str) -> TestResult { let deserialized: HydraMessage = serde_json::from_str(&input)?; assert_eq!(deserialized, expected); Ok(()) } + +fn test_events_deserialization(expected: HydraMessages, input: &str) -> TestResult { + let deserialized: HydraMessages = serde_json::from_str(&input)?; + assert_eq!(deserialized, expected); + Ok(()) +} + #[test] fn tx_valid_evt() -> TestResult { let evt = HydraMessage { @@ -168,3 +185,36 @@ fn committed_evt() -> TestResult { "#; test_event_deserialization(evt, &raw_str) } + +#[test] +fn one_hydra_message() -> TestResult { + let evts = HydraMessages(vec![HydraMessage { + seq: 2, + payload: HydraMessagePayload::Other, + head_id: None, + raw_json: json!( + { "headStatus": "Idle" + , "hydraNodeVersion": "0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425" + , "me": + { "vkey": "b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb" + } + , "seq": 2 + , "tag": "Greetings" + , "timestamp": "2024-10-08T13:04:56.445761285Z" + }), + }]); + + let raw_str = r#" + { + "headStatus": "Idle", + "hydraNodeVersion": "0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425", + "me": { + "vkey": "b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb" + }, + "seq": 2, + "tag": "Greetings", + "timestamp": "2024-10-08T13:04:56.445761285Z" + } +"#; + test_events_deserialization(evts, &raw_str) +} From 97e1da104bb6a7fba3d4f9f2dcbab9e97e0d2839 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 24 Oct 2024 13:05:29 +0200 Subject: [PATCH 22/53] add two valid events test --- Cargo.lock | 1 - Cargo.toml | 1 - src/sources/hydra.rs | 5 --- tests/hydra.rs | 90 +++++++++++++++++++++----------------------- 4 files changed, 43 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a9ab06f..493f4386 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4147,7 +4147,6 @@ dependencies = [ "reqwest 0.11.24", "serde", "serde_json", - "serde_with 3.11.0", "sqlx", "strum 0.24.1", "strum_macros 0.25.3", diff --git a/Cargo.toml b/Cargo.toml index 56194edf..186ec51d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,6 @@ handlebars = "^5.1" config = { version = "0.13.2", default-features = false, features = ["toml", "yaml", "json"] } serde = { version = "1.0.152", features = ["derive"] } serde_json = { version = "1.0.104", features = ["arbitrary_precision"] } -serde_with = "3.11.0" strum = "0.24" strum_macros = "0.25" unicode-truncate = "0.2.0" diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 7707e404..41e750dd 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -13,7 +13,6 @@ use tokio_tungstenite::{connect_async, tungstenite::protocol::Message}; use serde::de::{self}; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::Value; -use serde_with::{formats::PreferMany, serde_as, OneOrMany}; use crate::framework::*; @@ -113,10 +112,6 @@ where Ok(cbor) } -#[serde_as] -#[derive(Deserialize, PartialEq, Debug, Clone)] -pub struct HydraMessages(#[serde_as(as = "OneOrMany<_, PreferMany>")] pub Vec); - #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Snapshot { number: u64, diff --git a/tests/hydra.rs b/tests/hydra.rs index 15430f76..22fa47f1 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -1,33 +1,20 @@ -use std::fs; - -use oura::sources::hydra::{HydraMessage, HydraMessagePayload, HydraMessages}; +use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; use serde_json::json; type TestResult = Result<(), Box>; -//fn run_scenario(expected_msgs: &Vec, expected_file: &str) -> TestResult { -// let input = fs::read_to_string(expected_file)?; -// let deserialized: HydraMessages = serde_json::from_str(&input)?; -// println!("deserialized {:?}", deserialized); -// assert_eq!( -// deserialized -// .0 -// .iter() -// .map(|msg| msg.payload.clone()) -// .collect::>(), -// *expected_msgs -// ); -// Ok(()) -//} - -fn test_event_deserialization(expected: HydraMessage, input: &str) -> TestResult { - let deserialized: HydraMessage = serde_json::from_str(&input)?; - assert_eq!(deserialized, expected); +fn test_events_deserialisation(expected_msgs: Vec, input: &str) -> TestResult { + let mut deserialized: Vec = Vec::new(); + for line in input.lines() { + let msg: HydraMessage = serde_json::from_str(&line)?; + deserialized.push(msg); + } + assert_eq!(deserialized, expected_msgs); Ok(()) } -fn test_events_deserialization(expected: HydraMessages, input: &str) -> TestResult { - let deserialized: HydraMessages = serde_json::from_str(&input)?; +fn test_event_deserialization(expected: HydraMessage, input: &str) -> TestResult { + let deserialized: HydraMessage = serde_json::from_str(&input)?; assert_eq!(deserialized, expected); Ok(()) } @@ -187,34 +174,43 @@ fn committed_evt() -> TestResult { } #[test] -fn one_hydra_message() -> TestResult { - let evts = HydraMessages(vec![HydraMessage { - seq: 2, +fn two_valid_evts() -> TestResult { + let evts = vec![ + HydraMessage { + seq: 7, + head_id: Some(hex::decode("84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab").unwrap() + .to_vec()), + payload: HydraMessagePayload::TxValid { + tx: hex::decode("84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858401b13ee550f3167a1b94796f2a2f5e22d782d628336a7797c5b798f358fa564dbe92ea75a4e2449eb2cef59c097d8497545ef1e4ea441b88a481194323ae7c608f5f6") + .unwrap() + .to_vec(), + }, + raw_json: json!( + { "headId": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab" + , "seq": 7 + , "tag": "TxValid" + , "timestamp": "2024-10-08T13:07:18.008847436Z" + , "transaction": + { "cborHex": "84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858401b13ee550f3167a1b94796f2a2f5e22d782d628336a7797c5b798f358fa564dbe92ea75a4e2449eb2cef59c097d8497545ef1e4ea441b88a481194323ae7c608f5f6" + , "description": "Ledger Cddl Format" + , "txId": "633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1" + , "type": "Witnessed Tx ConwayEra" + } + }), + }, HydraMessage { + seq: 0, payload: HydraMessagePayload::Other, head_id: None, raw_json: json!( - { "headStatus": "Idle" - , "hydraNodeVersion": "0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425" - , "me": - { "vkey": "b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb" - } - , "seq": 2 - , "tag": "Greetings" - , "timestamp": "2024-10-08T13:04:56.445761285Z" + { "peer": "3" + , "seq": 0 + , "tag": "PeerConnected" + , "timestamp": "2024-10-08T13:01:20.556003751Z" }), - }]); + }]; - let raw_str = r#" - { - "headStatus": "Idle", - "hydraNodeVersion": "0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425", - "me": { - "vkey": "b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb" - }, - "seq": 2, - "tag": "Greetings", - "timestamp": "2024-10-08T13:04:56.445761285Z" - } + let raw_str = r#"{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":7,"tag":"TxValid","timestamp":"2024-10-08T13:07:18.008847436Z","transaction":{"cborHex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858401b13ee550f3167a1b94796f2a2f5e22d782d628336a7797c5b798f358fa564dbe92ea75a4e2449eb2cef59c097d8497545ef1e4ea441b88a481194323ae7c608f5f6","description":"Ledger Cddl Format","txId":"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1","type":"Witnessed Tx ConwayEra"}} +{"peer":"3","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.556003751Z"} "#; - test_events_deserialization(evts, &raw_str) + test_events_deserialisation(evts, &raw_str) } From 10ea7b45155c557ee9b27da4248ae074a0e2256d Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 24 Oct 2024 13:09:26 +0200 Subject: [PATCH 23/53] add three valid events test --- tests/hydra.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/hydra.rs b/tests/hydra.rs index 22fa47f1..f2bdbf50 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -214,3 +214,52 @@ fn two_valid_evts() -> TestResult { "#; test_events_deserialisation(evts, &raw_str) } + +#[test] +fn three_valid_evts() -> TestResult { + let evts = vec![ + HydraMessage { + seq: 0, + payload: HydraMessagePayload::Other, + head_id: None, + raw_json: json!( + { "peer": "3" + , "seq": 0 + , "tag": "PeerConnected" + , "timestamp": "2024-10-08T13:01:20.556003751Z" + }), + }, + HydraMessage { + seq: 1, + payload: HydraMessagePayload::Other, + head_id: None, + raw_json: json!( + { "peer": "2" + , "seq": 1 + , "tag": "PeerConnected" + , "timestamp": "2024-10-08T13:01:20.559653645Z" + }), + }, + HydraMessage { + seq: 2, + payload: HydraMessagePayload::Other, + head_id: None, + raw_json: json!( + { "headStatus": "Idle" + , "hydraNodeVersion": "0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425" + , "me": + { "vkey": "b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb" + } + , "seq": 2 + , "tag": "Greetings" + , "timestamp": "2024-10-08T13:04:56.445761285Z" + }), + }, + ]; + + let raw_str = r#"{"peer":"3","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.556003751Z"} +{"peer":"2","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.559653645Z"} +{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:04:56.445761285Z"} +"#; + test_events_deserialisation(evts, &raw_str) +} From ec4486386087df72254af0e021d05314bf0d9b49 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 24 Oct 2024 14:02:58 +0200 Subject: [PATCH 24/53] handle incorrect events in tests --- tests/hydra.rs | 91 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 13 deletions(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index f2bdbf50..8cba2d03 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -3,11 +3,23 @@ use serde_json::json; type TestResult = Result<(), Box>; -fn test_events_deserialisation(expected_msgs: Vec, input: &str) -> TestResult { - let mut deserialized: Vec = Vec::new(); +#[derive(Debug, PartialEq)] +enum LineParseResult { + LineParsed(HydraMessage), + LineNotParsed, +} + +fn test_events_deserialisation(expected_msgs: Vec, input: &str) -> TestResult { + let mut deserialized: Vec = Vec::new(); for line in input.lines() { - let msg: HydraMessage = serde_json::from_str(&line)?; - deserialized.push(msg); + match serde_json::from_str(&line) { + Ok(msg) => { + deserialized.push(LineParseResult::LineParsed(msg)); + } + _ => { + deserialized.push(LineParseResult::LineNotParsed); + } + } } assert_eq!(deserialized, expected_msgs); Ok(()) @@ -176,7 +188,7 @@ fn committed_evt() -> TestResult { #[test] fn two_valid_evts() -> TestResult { let evts = vec![ - HydraMessage { + LineParseResult::LineParsed(HydraMessage { seq: 7, head_id: Some(hex::decode("84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab").unwrap() .to_vec()), @@ -197,7 +209,7 @@ fn two_valid_evts() -> TestResult { , "type": "Witnessed Tx ConwayEra" } }), - }, HydraMessage { + }), LineParseResult::LineParsed(HydraMessage { seq: 0, payload: HydraMessagePayload::Other, head_id: None, @@ -207,7 +219,7 @@ fn two_valid_evts() -> TestResult { , "tag": "PeerConnected" , "timestamp": "2024-10-08T13:01:20.556003751Z" }), - }]; + })]; let raw_str = r#"{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":7,"tag":"TxValid","timestamp":"2024-10-08T13:07:18.008847436Z","transaction":{"cborHex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858401b13ee550f3167a1b94796f2a2f5e22d782d628336a7797c5b798f358fa564dbe92ea75a4e2449eb2cef59c097d8497545ef1e4ea441b88a481194323ae7c608f5f6","description":"Ledger Cddl Format","txId":"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1","type":"Witnessed Tx ConwayEra"}} {"peer":"3","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.556003751Z"} @@ -218,7 +230,7 @@ fn two_valid_evts() -> TestResult { #[test] fn three_valid_evts() -> TestResult { let evts = vec![ - HydraMessage { + LineParseResult::LineParsed(HydraMessage { seq: 0, payload: HydraMessagePayload::Other, head_id: None, @@ -228,8 +240,8 @@ fn three_valid_evts() -> TestResult { , "tag": "PeerConnected" , "timestamp": "2024-10-08T13:01:20.556003751Z" }), - }, - HydraMessage { + }), + LineParseResult::LineParsed(HydraMessage { seq: 1, payload: HydraMessagePayload::Other, head_id: None, @@ -239,8 +251,8 @@ fn three_valid_evts() -> TestResult { , "tag": "PeerConnected" , "timestamp": "2024-10-08T13:01:20.559653645Z" }), - }, - HydraMessage { + }), + LineParseResult::LineParsed(HydraMessage { seq: 2, payload: HydraMessagePayload::Other, head_id: None, @@ -254,11 +266,64 @@ fn three_valid_evts() -> TestResult { , "tag": "Greetings" , "timestamp": "2024-10-08T13:04:56.445761285Z" }), - }, + }), + ]; + + let raw_str = r#"{"peer":"3","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.556003751Z"} +{"peer":"2","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.559653645Z"} +{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:04:56.445761285Z"} +"#; + test_events_deserialisation(evts, &raw_str) +} + +#[test] +fn three_valid_two_invalid_evts() -> TestResult { + let evts = vec![ + LineParseResult::LineParsed(HydraMessage { + seq: 0, + payload: HydraMessagePayload::Other, + head_id: None, + raw_json: json!( + { "peer": "3" + , "seq": 0 + , "tag": "PeerConnected" + , "timestamp": "2024-10-08T13:01:20.556003751Z" + }), + }), + LineParseResult::LineParsed(HydraMessage { + seq: 1, + payload: HydraMessagePayload::Other, + head_id: None, + raw_json: json!( + { "peer": "2" + , "seq": 1 + , "tag": "PeerConnected" + , "timestamp": "2024-10-08T13:01:20.559653645Z" + }), + }), + LineParseResult::LineNotParsed, + LineParseResult::LineNotParsed, + LineParseResult::LineParsed(HydraMessage { + seq: 2, + payload: HydraMessagePayload::Other, + head_id: None, + raw_json: json!( + { "headStatus": "Idle" + , "hydraNodeVersion": "0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425" + , "me": + { "vkey": "b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb" + } + , "seq": 2 + , "tag": "Greetings" + , "timestamp": "2024-10-08T13:04:56.445761285Z" + }), + }), ]; let raw_str = r#"{"peer":"3","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.556003751Z"} {"peer":"2","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.559653645Z"} +1 +2 {"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:04:56.445761285Z"} "#; test_events_deserialisation(evts, &raw_str) From f200d3301518468cbc1f27185fb1bd22c2be38a2 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 24 Oct 2024 14:30:05 +0200 Subject: [PATCH 25/53] add test_scenario --- tests/hydra.rs | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index 8cba2d03..a634f862 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -1,16 +1,41 @@ +use std::fs; + use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; use serde_json::json; type TestResult = Result<(), Box>; #[derive(Debug, PartialEq)] -enum LineParseResult { - LineParsed(HydraMessage), +enum LineParseResult { + LineParsed(T), LineNotParsed, } -fn test_events_deserialisation(expected_msgs: Vec, input: &str) -> TestResult { - let mut deserialized: Vec = Vec::new(); +fn test_events_deserialisation( + expected_msgs: Vec>, + input: &str, +) -> TestResult { + let mut deserialized: Vec> = Vec::new(); + for line in input.lines() { + match serde_json::from_str(&line) { + Ok(msg) => { + deserialized.push(LineParseResult::LineParsed(msg)); + } + _ => { + deserialized.push(LineParseResult::LineNotParsed); + } + } + } + assert_eq!(deserialized, expected_msgs); + Ok(()) +} + +fn test_scenario( + expected_msgs: Vec>, + file: &str, +) -> TestResult { + let mut deserialized: Vec> = Vec::new(); + let input = fs::read_to_string(file)?; for line in input.lines() { match serde_json::from_str(&line) { Ok(msg) => { From 35f91ddb79993b562a961597a787896da039d7a6 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 24 Oct 2024 14:39:50 +0200 Subject: [PATCH 26/53] add scenario_1 test --- tests/hydra.rs | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index a634f862..7cc359aa 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -37,9 +37,9 @@ fn test_scenario( let mut deserialized: Vec> = Vec::new(); let input = fs::read_to_string(file)?; for line in input.lines() { - match serde_json::from_str(&line) { + match serde_json::from_str::(&line) { Ok(msg) => { - deserialized.push(LineParseResult::LineParsed(msg)); + deserialized.push(LineParseResult::LineParsed(msg.payload)); } _ => { deserialized.push(LineParseResult::LineNotParsed); @@ -353,3 +353,37 @@ fn three_valid_two_invalid_evts() -> TestResult { "#; test_events_deserialisation(evts, &raw_str) } + +#[test] +fn scenario_1() -> TestResult { + let payloads = vec![ + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineNotParsed, + LineParseResult::LineParsed(HydraMessagePayload::TxValid { + tx: hex::decode("84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858401b13ee550f3167a1b94796f2a2f5e22d782d628336a7797c5b798f358fa564dbe92ea75a4e2449eb2cef59c097d8497545ef1e4ea441b88a481194323ae7c608f5f6") + .unwrap() + .to_vec(), + }), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineNotParsed, + LineParseResult::LineNotParsed, + LineParseResult::LineNotParsed, + LineParseResult::LineNotParsed + ]; + test_scenario(payloads, "tests/hydra/scenario_1.txt") +} From 0c70206588b11c1ec28a7536d5923ec3da230bab Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 24 Oct 2024 14:48:52 +0200 Subject: [PATCH 27/53] add scenario_2 test --- tests/hydra.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tests/hydra.rs b/tests/hydra.rs index 7cc359aa..787c215e 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -387,3 +387,56 @@ fn scenario_1() -> TestResult { ]; test_scenario(payloads, "tests/hydra/scenario_1.txt") } + +#[test] +fn scenario_2() -> TestResult { + let payloads = vec![ + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::TxValid { + tx: hex::decode("84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858407342c0c4de1b55bc9e56c86829a1fb5906e964f109fd698d37d5933ed230b1a878bfee20980bb90b48aa32c472fdd465c2eb770551b84de7041838415faed502f5f6") + .unwrap() + .to_vec(), + }), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineParsed(HydraMessagePayload::TxValid { + tx: hex::decode("84a300d901028182582065d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e5161701018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a0016e36082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a014810600200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf85840b991c62af8e2b2d06f821fb6064f98c2fc8909b0b2d81435c7e075a61fc92ee6c9224f23d817de35d5529f54034c2ab8dfaded387e99fc525344846bb5dc860af5f6") + .unwrap() + .to_vec(), + }), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineNotParsed, + LineParseResult::LineParsed(HydraMessagePayload::TxValid { + tx: hex::decode("84a300d90102818258207b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c69700018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a00a7d8c082581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a025317c00200a100d9010281825820aa268d154185c9ea06ea73442fd8143c34c1dd543b7142bcb132aac0d1ed6ece5840fc6e2b0750259deedd5a73eeadf481138bf82edc3425614871a0ef09bfcf8cae52a80240fb895a7e6a8ad94d4acb32dffe567ed0d338afcd7878f745737f420df5f6") + .unwrap() + .to_vec(), + }), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineParsed(HydraMessagePayload::TxValid { + tx: hex::decode("84a300d9010281825820c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d9700018282581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a00c65d4082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a052f83c00200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840ac8f1632d9a636d3627328ffd09cd32e1b654cbf318f0ce499a9870b05530041aa0badf07cd43fec8f1456537ada71227bea8123c1ed641ae3cb22b7313d5f08f5f6") + .unwrap() + .to_vec(), + }), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineParsed(HydraMessagePayload::Other), + LineParseResult::LineNotParsed, + LineParseResult::LineNotParsed, + LineParseResult::LineNotParsed, + LineParseResult::LineNotParsed + ]; + test_scenario(payloads, "tests/hydra/scenario_2.txt") +} From f237af20b0a4b5932c7b9fb6225678be2c517ad6 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Tue, 29 Oct 2024 13:06:10 +0100 Subject: [PATCH 28/53] add tokio runtime skeleton in integration testing --- tests/hydra.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/hydra.rs b/tests/hydra.rs index 787c215e..1c394475 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -1,7 +1,10 @@ use std::fs; +use std::time::Duration; use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; use serde_json::json; +use tokio::runtime::Runtime; +use tokio::time; type TestResult = Result<(), Box>; @@ -440,3 +443,31 @@ fn scenario_2() -> TestResult { ]; test_scenario(payloads, "tests/hydra/scenario_2.txt") } + +#[test] +fn integration_test() -> TestResult { + println!("from main thread BEFORE"); + + let rt = Runtime::new().unwrap(); + rt.block_on(async move { + println!("hello from the async block"); + async_function("task0").await; + + let task1 = tokio::spawn(async { async_function("task1").await }); + let task2 = tokio::spawn(async { async_function("task2").await }); + + let _ = task1.await; + let _ = task2.await; + }); + + println!("from main thread AFTER"); + + Ok(()) +} + +async fn async_function(name: &str) { + for i in 0..3 { + println!("{} : {}", name, i); + time::sleep(Duration::from_secs(1)).await; + } +} From e4e7656db59f9b269b1fde3cf3310c63e2f4e0db Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Tue, 29 Oct 2024 13:55:44 +0100 Subject: [PATCH 29/53] websocket server-client scaffolding --- Cargo.lock | 1 + Cargo.toml | 3 +++ tests/hydra.rs | 71 ++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 493f4386..d6b5ab31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4158,6 +4158,7 @@ dependencies = [ "tracing-subscriber", "tungstenite", "unicode-truncate", + "url", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 186ec51d..659c5217 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,3 +83,6 @@ tungstenite = "0.24.0" tokio-tungstenite = "0.24.0" futures-util = "0.3" bytes = "1.7.2" + +[dev-dependencies] +url = "2" diff --git a/tests/hydra.rs b/tests/hydra.rs index 1c394475..40217fff 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -1,10 +1,16 @@ use std::fs; use std::time::Duration; +use anyhow::Result; +use futures_util::{SinkExt, StreamExt}; use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; use serde_json::json; +use tokio::net::TcpListener; use tokio::runtime::Runtime; use tokio::time; +use tokio_tungstenite::tungstenite::protocol::Message; +use tokio_tungstenite::{accept_async, connect_async}; +use url::Url; type TestResult = Result<(), Box>; @@ -449,15 +455,22 @@ fn integration_test() -> TestResult { println!("from main thread BEFORE"); let rt = Runtime::new().unwrap(); - rt.block_on(async move { - println!("hello from the async block"); - async_function("task0").await; + let _ = rt.block_on(async move { + let addr = "127.0.0.1:8080".to_string(); + let listener = TcpListener::bind(&addr).await?; + println!("WebSocket server started on ws://{}", addr); - let task1 = tokio::spawn(async { async_function("task1").await }); - let task2 = tokio::spawn(async { async_function("task2").await }); + let web_socket_client = tokio::spawn(async { client().await }); - let _ = task1.await; - let _ = task2.await; + while let Ok((stream, _)) = listener.accept().await { + tokio::spawn(handle_connection(stream)); + } + + println!("from main thread BETWEEN"); + + let _ = web_socket_client.await; + + Ok::<(), std::io::Error>(()) }); println!("from main thread AFTER"); @@ -465,9 +478,45 @@ fn integration_test() -> TestResult { Ok(()) } -async fn async_function(name: &str) { - for i in 0..3 { - println!("{} : {}", name, i); - time::sleep(Duration::from_secs(1)).await; +async fn handle_connection(stream: tokio::net::TcpStream) -> Result<()> { + let mut ws_stream = accept_async(stream).await?; + println!("WebSocket server connection established"); + + while let Some(msg) = ws_stream.next().await { + let msg = msg?; + if msg.is_text() { + let received_text = msg.to_text()?; + println!("WebSocket server received message: {}", received_text); + time::sleep(Duration::from_secs(1)).await; + ws_stream + .send(Message::Text(received_text.to_string())) + .await?; + } } + + Ok(()) +} + +async fn client() -> Result<()> { + let url = Url::parse("ws://127.0.0.1:8080")?; + let (mut ws_stream, _) = connect_async(url.as_str()) + .await + .expect("Failed to connect"); + println!("WebSocket client connected"); + + // Sending a message to the server + let message = "Hello, Server!"; + ws_stream.send(Message::Text(message.into())).await?; + + // Receiving messages from the server + while let Some(msg) = ws_stream.next().await { + match msg? { + Message::Text(text) => { + println!("WebSocket client received message from server: {}", text); + } + _ => {} + } + } + + Ok(()) } From 18501fb60a8ebe4aa5f47f45e01359ed5243f6b4 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Tue, 29 Oct 2024 17:01:59 +0100 Subject: [PATCH 30/53] towards hydra emulation test --- tests/hydra.rs | 64 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index 40217fff..153e11c6 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -1,4 +1,5 @@ use std::fs; +use std::sync::mpsc; use std::time::Duration; use anyhow::Result; @@ -451,53 +452,58 @@ fn scenario_2() -> TestResult { } #[test] -fn integration_test() -> TestResult { - println!("from main thread BEFORE"); - +fn hydra_emulation_test() -> TestResult { let rt = Runtime::new().unwrap(); + let (tx, rx) = mpsc::channel(); let _ = rt.block_on(async move { let addr = "127.0.0.1:8080".to_string(); - let listener = TcpListener::bind(&addr).await?; + let server = TcpListener::bind(&addr).await?; println!("WebSocket server started on ws://{}", addr); - let web_socket_client = tokio::spawn(async { client().await }); - - while let Ok((stream, _)) = listener.accept().await { - tokio::spawn(handle_connection(stream)); - } + let file = "tests/hydra/scenario_2.txt"; + let to_send = fs::read_to_string(file)?; - println!("from main thread BETWEEN"); + let _ = tokio::spawn(async move { websocket_client(to_send, rx).await }); - let _ = web_socket_client.await; + while let Ok((stream, _)) = server.accept().await { + tokio::spawn(handle_connection(stream, &file, tx)); + time::sleep(Duration::from_secs(5)).await; + break; + } Ok::<(), std::io::Error>(()) }); - - println!("from main thread AFTER"); - Ok(()) } -async fn handle_connection(stream: tokio::net::TcpStream) -> Result<()> { +async fn handle_connection( + stream: tokio::net::TcpStream, + file: &str, + tx: mpsc::Sender, +) -> Result<()> { let mut ws_stream = accept_async(stream).await?; println!("WebSocket server connection established"); + let to_send = fs::read_to_string(file)?; + while let Some(msg) = ws_stream.next().await { let msg = msg?; if msg.is_text() { let received_text = msg.to_text()?; println!("WebSocket server received message: {}", received_text); - time::sleep(Duration::from_secs(1)).await; - ws_stream - .send(Message::Text(received_text.to_string())) - .await?; + let mut lines = 0; + for line in to_send.lines() { + ws_stream.send(Message::Text(line.to_string())).await?; + lines += 1; + } + tx.send(lines).unwrap(); } } Ok(()) } -async fn client() -> Result<()> { +async fn websocket_client(expected: String, rx: mpsc::Receiver) -> Result<()> { let url = Url::parse("ws://127.0.0.1:8080")?; let (mut ws_stream, _) = connect_async(url.as_str()) .await @@ -508,15 +514,31 @@ async fn client() -> Result<()> { let message = "Hello, Server!"; ws_stream.send(Message::Text(message.into())).await?; + let mut received = vec![]; + let mut msgs_number = 0; + // Receiving messages from the server while let Some(msg) = ws_stream.next().await { match msg? { Message::Text(text) => { - println!("WebSocket client received message from server: {}", text); + received.push(text); + //println!("WebSocket client received message from server: {}", text); } _ => {} } + if let Ok(size) = rx.try_recv() { + msgs_number = size; + } + if msgs_number == received.len() { + break; + } } + let mut joined = received.join("\n"); + joined.push_str("\n"); + + assert_eq!(joined, expected); + println!("WebSocket client disconnected"); + Ok(()) } From 4e4122585b196ecf7797a581f26173caae4f91b6 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Tue, 29 Oct 2024 17:17:49 +0100 Subject: [PATCH 31/53] finish hydra emulation testing --- tests/hydra.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index 153e11c6..aa198d5c 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -452,7 +452,19 @@ fn scenario_2() -> TestResult { } #[test] -fn hydra_emulation_test() -> TestResult { +fn hydra_emulation_scenario_1() -> TestResult { + hydra_emulation_test("tests/hydra/scenario_1.txt".to_string()) +} + +#[test] +fn hydra_emulation_scenario_2() -> TestResult { + hydra_emulation_test("tests/hydra/scenario_2.txt".to_string()) +} + +// Run: +// cargo test hydra_emulation -- --nocapture +// in order to see println +fn hydra_emulation_test(file: String) -> TestResult { let rt = Runtime::new().unwrap(); let (tx, rx) = mpsc::channel(); let _ = rt.block_on(async move { @@ -460,14 +472,13 @@ fn hydra_emulation_test() -> TestResult { let server = TcpListener::bind(&addr).await?; println!("WebSocket server started on ws://{}", addr); - let file = "tests/hydra/scenario_2.txt"; - let to_send = fs::read_to_string(file)?; + let to_send = fs::read_to_string(&file)?; let _ = tokio::spawn(async move { websocket_client(to_send, rx).await }); while let Ok((stream, _)) = server.accept().await { - tokio::spawn(handle_connection(stream, &file, tx)); - time::sleep(Duration::from_secs(5)).await; + tokio::spawn(handle_connection(stream, file, tx)); + time::sleep(Duration::from_secs(3)).await; break; } @@ -478,7 +489,7 @@ fn hydra_emulation_test() -> TestResult { async fn handle_connection( stream: tokio::net::TcpStream, - file: &str, + file: String, tx: mpsc::Sender, ) -> Result<()> { let mut ws_stream = accept_async(stream).await?; From f157adca9d9ef16cf9815ea69665523e6c1f7493 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Wed, 30 Oct 2024 14:23:29 +0100 Subject: [PATCH 32/53] try running binary --- Cargo.lock | 106 +++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + tests/hydra.rs | 39 ++++++++++++++++++ 3 files changed, 147 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index d6b5ab31..aba4838f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -174,6 +174,22 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +[[package]] +name = "assert_cmd" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "libc", + "predicates 3.1.2", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -1068,6 +1084,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bstr" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +dependencies = [ + "memchr", + "regex-automata 0.4.5", + "serde", +] + [[package]] name = "bumpalo" version = "3.15.3" @@ -1857,6 +1884,12 @@ dependencies = [ "cipher", ] +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "digest" version = "0.9.0" @@ -2343,6 +2376,15 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + [[package]] name = "flume" version = "0.10.14" @@ -3898,6 +3940,12 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -4106,6 +4154,7 @@ name = "oura" version = "2.0.0-alpha.4" dependencies = [ "anyhow", + "assert_cmd", "async-trait", "aws-config", "aws-sdk-lambda", @@ -4142,6 +4191,7 @@ dependencies = [ "net2", "openssl", "pallas", + "predicates 2.1.5", "r2d2_redis", "regex", "reqwest 0.11.24", @@ -4816,6 +4866,47 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "predicates" +version = "2.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" +dependencies = [ + "difflib", + "float-cmp", + "itertools 0.10.5", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" +dependencies = [ + "anstyle", + "difflib", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" + +[[package]] +name = "predicates-tree" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "prettyplease" version = "0.2.17" @@ -6551,6 +6642,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + [[package]] name = "textwrap" version = "0.16.1" @@ -7264,6 +7361,15 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "waker-fn" version = "1.1.1" diff --git a/Cargo.toml b/Cargo.toml index 659c5217..6c7f4ee7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,4 +85,6 @@ futures-util = "0.3" bytes = "1.7.2" [dev-dependencies] +assert_cmd = "2" +predicates = "2" url = "2" diff --git a/tests/hydra.rs b/tests/hydra.rs index aa198d5c..42278648 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -3,8 +3,10 @@ use std::sync::mpsc; use std::time::Duration; use anyhow::Result; +use assert_cmd::Command; use futures_util::{SinkExt, StreamExt}; use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; +use predicates::prelude::*; use serde_json::json; use tokio::net::TcpListener; use tokio::runtime::Runtime; @@ -461,6 +463,11 @@ fn hydra_emulation_scenario_2() -> TestResult { hydra_emulation_test("tests/hydra/scenario_2.txt".to_string()) } +#[test] +fn hydra_oura_stdout_scenario_1() -> TestResult { + hydra_emulation_oura_stdout_test("tests/hydra/scenario_1.txt".to_string()) +} + // Run: // cargo test hydra_emulation -- --nocapture // in order to see println @@ -487,6 +494,29 @@ fn hydra_emulation_test(file: String) -> TestResult { Ok(()) } +fn hydra_emulation_oura_stdout_test(file: String) -> TestResult { + let rt = Runtime::new().unwrap(); + let (tx, rx) = mpsc::channel(); + let _ = rt.block_on(async move { + let addr = "127.0.0.1:4001".to_string(); + let server = TcpListener::bind(&addr).await?; + println!("WebSocket server started on ws://{}", addr); + + let to_send = fs::read_to_string(&file)?; + + let _ = tokio::spawn(async move { oura_pipeline(to_send, rx).await }); + + while let Ok((stream, _)) = server.accept().await { + tokio::spawn(handle_connection(stream, file, tx)); + time::sleep(Duration::from_secs(3)).await; + break; + } + + Ok::<(), std::io::Error>(()) + }); + Ok(()) +} + async fn handle_connection( stream: tokio::net::TcpStream, file: String, @@ -553,3 +583,12 @@ async fn websocket_client(expected: String, rx: mpsc::Receiver) -> Result Ok(()) } + +async fn oura_pipeline(expected: String, rx: mpsc::Receiver) -> Result<()> { + let mut cmd = Command::cargo_bin("oura")?; + cmd.args(vec!["daemon", "--config", "examples/hydra/daemon.toml"]) + .assert() + .success() + .stdout(expected); + Ok(()) +} From 01fc6f1e0ee9e05d91bdd8487395206d90f18bce Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 31 Oct 2024 14:52:00 +0100 Subject: [PATCH 33/53] add oura integration test working --- tests/daemon.toml | 18 +++++++++ tests/hydra.rs | 88 ++++++++++++++++++++++++++++---------------- tests/hydra/logs.txt | 0 3 files changed, 75 insertions(+), 31 deletions(-) create mode 100644 tests/daemon.toml create mode 100644 tests/hydra/logs.txt diff --git a/tests/daemon.toml b/tests/daemon.toml new file mode 100644 index 00000000..bbf93f1b --- /dev/null +++ b/tests/daemon.toml @@ -0,0 +1,18 @@ +[source] +type = "Hydra" +hydra_socket_url = "ws://127.0.0.1:4001" +magic = 42 + +[intersect] +type = "Origin" + +[[filters]] +type = "IntoJson" + +[sink] +type = "FileRotate" +max_total_files = 1 +output_format = "JSONL" +output_path = "tests/hydra/logs.txt" +max_bytes_per_file = 5_000_000 +compress_files = true diff --git a/tests/hydra.rs b/tests/hydra.rs index 42278648..0068c758 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -465,7 +465,22 @@ fn hydra_emulation_scenario_2() -> TestResult { #[test] fn hydra_oura_stdout_scenario_1() -> TestResult { - hydra_emulation_oura_stdout_test("tests/hydra/scenario_1.txt".to_string()) + let events = vec![ + "PeerConnected".to_string(), + "PeerConnected".to_string(), + "Greetings".to_string(), + "HeadIsInitializing0".to_string(), + "Committed".to_string(), + "Committed".to_string(), + "Committed".to_string(), + "HeadIsOpen".to_string(), + "TxValid".to_string(), + "SnapshotConfirmed".to_string(), + "HeadIsClosed".to_string(), + "ReadyToFanout".to_string(), + "HeadIsFinalized".to_string(), + ]; + hydra_oura_stdout_test("tests/hydra/scenario_1.txt".to_string(), events) } // Run: @@ -475,7 +490,7 @@ fn hydra_emulation_test(file: String) -> TestResult { let rt = Runtime::new().unwrap(); let (tx, rx) = mpsc::channel(); let _ = rt.block_on(async move { - let addr = "127.0.0.1:8080".to_string(); + let addr = "127.0.0.1:4001".to_string(); let server = TcpListener::bind(&addr).await?; println!("WebSocket server started on ws://{}", addr); @@ -494,17 +509,18 @@ fn hydra_emulation_test(file: String) -> TestResult { Ok(()) } -fn hydra_emulation_oura_stdout_test(file: String) -> TestResult { +// Run: +// cargo test hydra_oura -- --nocapture +// in order to see println +fn hydra_oura_stdout_test(file: String, expected: Vec) -> TestResult { let rt = Runtime::new().unwrap(); - let (tx, rx) = mpsc::channel(); + let (tx, _rx) = mpsc::channel(); let _ = rt.block_on(async move { let addr = "127.0.0.1:4001".to_string(); let server = TcpListener::bind(&addr).await?; println!("WebSocket server started on ws://{}", addr); - let to_send = fs::read_to_string(&file)?; - - let _ = tokio::spawn(async move { oura_pipeline(to_send, rx).await }); + let _ = tokio::spawn(async move { oura_pipeline(expected).await }); while let Ok((stream, _)) = server.accept().await { tokio::spawn(handle_connection(stream, file, tx)); @@ -523,37 +539,26 @@ async fn handle_connection( tx: mpsc::Sender, ) -> Result<()> { let mut ws_stream = accept_async(stream).await?; - println!("WebSocket server connection established"); + println!("WebSocket server oura connection established"); let to_send = fs::read_to_string(file)?; - while let Some(msg) = ws_stream.next().await { - let msg = msg?; - if msg.is_text() { - let received_text = msg.to_text()?; - println!("WebSocket server received message: {}", received_text); - let mut lines = 0; - for line in to_send.lines() { - ws_stream.send(Message::Text(line.to_string())).await?; - lines += 1; - } - tx.send(lines).unwrap(); - } + let mut lines = 0; + for line in to_send.lines() { + ws_stream.send(Message::Text(line.to_string())).await?; + lines += 1; } + tx.send(lines).unwrap(); Ok(()) } async fn websocket_client(expected: String, rx: mpsc::Receiver) -> Result<()> { - let url = Url::parse("ws://127.0.0.1:8080")?; + let url = Url::parse("ws://127.0.0.1:4001")?; let (mut ws_stream, _) = connect_async(url.as_str()) .await .expect("Failed to connect"); - println!("WebSocket client connected"); - - // Sending a message to the server - let message = "Hello, Server!"; - ws_stream.send(Message::Text(message.into())).await?; + println!("WebSocket client oura connected"); let mut received = vec![]; let mut msgs_number = 0; @@ -579,16 +584,37 @@ async fn websocket_client(expected: String, rx: mpsc::Receiver) -> Result joined.push_str("\n"); assert_eq!(joined, expected); - println!("WebSocket client disconnected"); + println!("WebSocket client oura disconnected"); Ok(()) } -async fn oura_pipeline(expected: String, rx: mpsc::Receiver) -> Result<()> { +async fn oura_pipeline(expected: Vec) -> Result<()> { + println!("oura_pipeline online"); + + //Clean output file + let _ = std::process::Command::new("truncate") + .arg("-s 0") + .arg("tests/hydra/logs.txt") + .spawn(); + let mut cmd = Command::cargo_bin("oura")?; - cmd.args(vec!["daemon", "--config", "examples/hydra/daemon.toml"]) + cmd.args(vec!["daemon", "--config", "tests/daemon.toml"]) .assert() - .success() - .stdout(expected); + .success(); + + let jsons = fs::read_to_string("tests/hydra/logs.txt")?; + + let mut predicates = vec![]; + let mut count = 0; + + for json in jsons.lines() { + let predicate_fn = predicate::str::contains(&expected[count]); + predicates.push(predicate_fn.eval(json)); + count += 1; + } + + assert_eq!(predicates, vec![true; expected.len()]); + Ok(()) } diff --git a/tests/hydra/logs.txt b/tests/hydra/logs.txt new file mode 100644 index 00000000..e69de29b From 3a68004091bbb0522589bd1724ea985639b8bd56 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Thu, 31 Oct 2024 14:55:09 +0100 Subject: [PATCH 34/53] add scenario 2 refining testing plus gitignore spawn cmd process and fix typo truncate log file make sure result of tests is taken into account clean redundant tests --- Cargo.lock | 1 - Cargo.toml | 1 - examples/.gitignore | 3 +- tests/hydra.rs | 147 +++++++++++++++++-------------------------- tests/hydra/logs.txt | 23 +++++++ 5 files changed, 81 insertions(+), 94 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aba4838f..23019908 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4208,7 +4208,6 @@ dependencies = [ "tracing-subscriber", "tungstenite", "unicode-truncate", - "url", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 6c7f4ee7..da9bca01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,4 +87,3 @@ bytes = "1.7.2" [dev-dependencies] assert_cmd = "2" predicates = "2" -url = "2" diff --git a/examples/.gitignore b/examples/.gitignore index 162ee335..30e06623 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1 +1,2 @@ -scratchpad \ No newline at end of file +scratchpad +tests/hydra/logs.txt \ No newline at end of file diff --git a/tests/hydra.rs b/tests/hydra.rs index 0068c758..c1277633 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -4,16 +4,15 @@ use std::time::Duration; use anyhow::Result; use assert_cmd::Command; -use futures_util::{SinkExt, StreamExt}; +use futures_util::SinkExt; use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; use predicates::prelude::*; use serde_json::json; use tokio::net::TcpListener; use tokio::runtime::Runtime; use tokio::time; +use tokio_tungstenite::accept_async; use tokio_tungstenite::tungstenite::protocol::Message; -use tokio_tungstenite::{accept_async, connect_async}; -use url::Url; type TestResult = Result<(), Box>; @@ -453,28 +452,20 @@ fn scenario_2() -> TestResult { test_scenario(payloads, "tests/hydra/scenario_2.txt") } -#[test] -fn hydra_emulation_scenario_1() -> TestResult { - hydra_emulation_test("tests/hydra/scenario_1.txt".to_string()) -} - -#[test] -fn hydra_emulation_scenario_2() -> TestResult { - hydra_emulation_test("tests/hydra/scenario_2.txt".to_string()) -} - #[test] fn hydra_oura_stdout_scenario_1() -> TestResult { + let tx_event = r#"{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"hex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858401b13ee550f3167a1b94796f2a2f5e22d782d628336a7797c5b798f358fa564dbe92ea75a4e2449eb2cef59c097d8497545ef1e4ea441b88a481194323ae7c608f5f6"}}"#; let events = vec![ "PeerConnected".to_string(), "PeerConnected".to_string(), "Greetings".to_string(), - "HeadIsInitializing0".to_string(), + "HeadIsInitializing".to_string(), "Committed".to_string(), "Committed".to_string(), "Committed".to_string(), "HeadIsOpen".to_string(), "TxValid".to_string(), + tx_event.to_string(), "SnapshotConfirmed".to_string(), "HeadIsClosed".to_string(), "ReadyToFanout".to_string(), @@ -483,30 +474,38 @@ fn hydra_oura_stdout_scenario_1() -> TestResult { hydra_oura_stdout_test("tests/hydra/scenario_1.txt".to_string(), events) } -// Run: -// cargo test hydra_emulation -- --nocapture -// in order to see println -fn hydra_emulation_test(file: String) -> TestResult { - let rt = Runtime::new().unwrap(); - let (tx, rx) = mpsc::channel(); - let _ = rt.block_on(async move { - let addr = "127.0.0.1:4001".to_string(); - let server = TcpListener::bind(&addr).await?; - println!("WebSocket server started on ws://{}", addr); - - let to_send = fs::read_to_string(&file)?; - - let _ = tokio::spawn(async move { websocket_client(to_send, rx).await }); - - while let Ok((stream, _)) = server.accept().await { - tokio::spawn(handle_connection(stream, file, tx)); - time::sleep(Duration::from_secs(3)).await; - break; - } - - Ok::<(), std::io::Error>(()) - }); - Ok(()) +#[test] +fn hydra_oura_stdout_scenario_2() -> TestResult { + let tx_event_1 = r#"{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"hex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858407342c0c4de1b55bc9e56c86829a1fb5906e964f109fd698d37d5933ed230b1a878bfee20980bb90b48aa32c472fdd465c2eb770551b84de7041838415faed502f5f6"}}"#; + let tx_event_2 = r#"{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":9},"record":{"hex":"84a300d901028182582065d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e5161701018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a0016e36082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a014810600200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf85840b991c62af8e2b2d06f821fb6064f98c2fc8909b0b2d81435c7e075a61fc92ee6c9224f23d817de35d5529f54034c2ab8dfaded387e99fc525344846bb5dc860af5f6"}}"#; + let tx_event_3 = r#"{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":11},"record":{"hex":"84a300d90102818258207b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c69700018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a00a7d8c082581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a025317c00200a100d9010281825820aa268d154185c9ea06ea73442fd8143c34c1dd543b7142bcb132aac0d1ed6ece5840fc6e2b0750259deedd5a73eeadf481138bf82edc3425614871a0ef09bfcf8cae52a80240fb895a7e6a8ad94d4acb32dffe567ed0d338afcd7878f745737f420df5f6"}}"#; + let tx_event_4 = r#"{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":13},"record":{"hex":"84a300d9010281825820c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d9700018282581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a00c65d4082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a052f83c00200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840ac8f1632d9a636d3627328ffd09cd32e1b654cbf318f0ce499a9870b05530041aa0badf07cd43fec8f1456537ada71227bea8123c1ed641ae3cb22b7313d5f08f5f6"}}"#; + let events = vec![ + "PeerConnected".to_string(), + "PeerConnected".to_string(), + "Greetings".to_string(), + "HeadIsInitializing".to_string(), + "Committed".to_string(), + "Committed".to_string(), + "Committed".to_string(), + "HeadIsOpen".to_string(), + "TxValid".to_string(), + tx_event_1.to_string(), + "SnapshotConfirmed".to_string(), + "TxValid".to_string(), + tx_event_2.to_string(), + "SnapshotConfirmed".to_string(), + "TxValid".to_string(), + tx_event_3.to_string(), + "SnapshotConfirmed".to_string(), + "TxValid".to_string(), + tx_event_4.to_string(), + "SnapshotConfirmed".to_string(), + "HeadIsClosed".to_string(), + "ReadyToFanout".to_string(), + "HeadIsFinalized".to_string(), + ]; + hydra_oura_stdout_test("tests/hydra/scenario_2.txt".to_string(), events) } // Run: @@ -520,7 +519,7 @@ fn hydra_oura_stdout_test(file: String, expected: Vec) -> TestResult { let server = TcpListener::bind(&addr).await?; println!("WebSocket server started on ws://{}", addr); - let _ = tokio::spawn(async move { oura_pipeline(expected).await }); + let _ = tokio::spawn(async move { oura_pipeline().await }); while let Ok((stream, _)) = server.accept().await { tokio::spawn(handle_connection(stream, file, tx)); @@ -528,6 +527,16 @@ fn hydra_oura_stdout_test(file: String, expected: Vec) -> TestResult { break; } + let jsons = fs::read_to_string("tests/hydra/logs.txt")?; + let mut predicates = vec![]; + let mut count = 0; + for json in jsons.lines() { + let predicate_fn = predicate::str::contains(&expected[count]); + predicates.push(predicate_fn.eval(json)); + count += 1; + } + assert_eq!(predicates, vec![true; expected.len()]); + Ok::<(), std::io::Error>(()) }); Ok(()) @@ -553,68 +562,24 @@ async fn handle_connection( Ok(()) } -async fn websocket_client(expected: String, rx: mpsc::Receiver) -> Result<()> { - let url = Url::parse("ws://127.0.0.1:4001")?; - let (mut ws_stream, _) = connect_async(url.as_str()) - .await - .expect("Failed to connect"); - println!("WebSocket client oura connected"); - - let mut received = vec![]; - let mut msgs_number = 0; - - // Receiving messages from the server - while let Some(msg) = ws_stream.next().await { - match msg? { - Message::Text(text) => { - received.push(text); - //println!("WebSocket client received message from server: {}", text); - } - _ => {} - } - if let Ok(size) = rx.try_recv() { - msgs_number = size; - } - if msgs_number == received.len() { - break; - } - } - - let mut joined = received.join("\n"); - joined.push_str("\n"); - - assert_eq!(joined, expected); - println!("WebSocket client oura disconnected"); - - Ok(()) -} - -async fn oura_pipeline(expected: Vec) -> Result<()> { - println!("oura_pipeline online"); - +async fn oura_pipeline() -> Result<()> { //Clean output file let _ = std::process::Command::new("truncate") .arg("-s 0") .arg("tests/hydra/logs.txt") .spawn(); + tokio::spawn(invoke_pipeline()); + time::sleep(Duration::from_secs(1)).await; + + Ok(()) +} + +async fn invoke_pipeline() -> Result<()> { let mut cmd = Command::cargo_bin("oura")?; cmd.args(vec!["daemon", "--config", "tests/daemon.toml"]) .assert() .success(); - let jsons = fs::read_to_string("tests/hydra/logs.txt")?; - - let mut predicates = vec![]; - let mut count = 0; - - for json in jsons.lines() { - let predicate_fn = predicate::str::contains(&expected[count]); - predicates.push(predicate_fn.eval(json)); - count += 1; - } - - assert_eq!(predicates, vec![true; expected.len()]); - Ok(()) } diff --git a/tests/hydra/logs.txt b/tests/hydra/logs.txt index e69de29b..e0eff470 100644 --- a/tests/hydra/logs.txt +++ b/tests/hydra/logs.txt @@ -0,0 +1,23 @@ +{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":0},"record":{"peer":"2","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.954897681Z"}} +{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":1},"record":{"peer":"3","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.98647342Z"}} +{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":2},"record":{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:21:28.141876427Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":2},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","parties":[{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"}],"seq":2,"tag":"HeadIsInitializing","timestamp":"2024-10-08T13:22:05.725778923Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":3},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":3,"tag":"Committed","timestamp":"2024-10-08T13:22:11.016254447Z","utxo":{"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":4},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},"seq":4,"tag":"Committed","timestamp":"2024-10-08T13:22:18.915120931Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":5},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"},"seq":5,"tag":"Committed","timestamp":"2024-10-08T13:22:30.313144555Z","utxo":{"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":6},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":6,"tag":"HeadIsOpen","timestamp":"2024-10-08T13:22:30.520745142Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}},"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":7,"tag":"TxValid","timestamp":"2024-10-08T13:22:44.316966394Z","transaction":{"cborHex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858407342c0c4de1b55bc9e56c86829a1fb5906e964f109fd698d37d5933ed230b1a878bfee20980bb90b48aa32c472fdd465c2eb770551b84de7041838415faed502f5f6","description":"Ledger Cddl Format","txId":"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617","type":"Witnessed Tx ConwayEra"}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"hex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858407342c0c4de1b55bc9e56c86829a1fb5906e964f109fd698d37d5933ed230b1a878bfee20980bb90b48aa32c472fdd465c2eb770551b84de7041838415faed502f5f6"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":8},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":8,"signatures":{"multiSignature":["e9eaa5edf35b35872c94d9b11b1074e8dc737a24ad5956a7c982ee7eb3d2bfe31def724b8a8e586e30806b50ed55984e331a3fae986bc12e6e705e1138164400","7058aca64e437169677db810048bbfc1e0714bbf348cd43c37c46f3d836dc251e09ca7d2a2d6c89e87b2e7d7f4b110024ecbcec59f694370079a069df1903d03","e55bfb59691c93dfd6343a034cf9c78b03261e7d51a16e61e8fd7257378b563b8de6568abd88ddeb532d109e3ad33c6454b268b6ee6b29849786ac5691898603"]},"snapshot":{"confirmedTransactions":["65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":1,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":23000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:22:44.360477345Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":9},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":9,"tag":"TxValid","timestamp":"2024-10-08T13:23:18.169555579Z","transaction":{"cborHex":"84a300d901028182582065d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e5161701018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a0016e36082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a014810600200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf85840b991c62af8e2b2d06f821fb6064f98c2fc8909b0b2d81435c7e075a61fc92ee6c9224f23d817de35d5529f54034c2ab8dfaded387e99fc525344846bb5dc860af5f6","description":"Ledger Cddl Format","txId":"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af","type":"Witnessed Tx ConwayEra"}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":9},"record":{"hex":"84a300d901028182582065d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e5161701018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a0016e36082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a014810600200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf85840b991c62af8e2b2d06f821fb6064f98c2fc8909b0b2d81435c7e075a61fc92ee6c9224f23d817de35d5529f54034c2ab8dfaded387e99fc525344846bb5dc860af5f6"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":10},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":10,"signatures":{"multiSignature":["5897602f543c3692cfb691119b2e9feb22e2302333b3200f95fa65feffaa0846abeb293afc8dcbd4ba2ac4b0ba1df729730d2e3b5e69a652f99b52fa15729209","d2268afebbbde31886cf8ce1c7b827f92a1c675bc9dee5603d6d87d7c30d9f7ae46d596095a6e03624d2526fe101b026c9c765abb7e2603b06ffb4fa6ecc6b0e","b3342f10a0678c24bff40ab5d394b8d7382419b826bfbbc3c019a8c4fd20d6d4db9eec29d72fb58ceb09dfe6720ae5c8ade77fd49e2a4b7e884beeb93f027b00"]},"snapshot":{"confirmedTransactions":["a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":2,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:23:18.220733933Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":11},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":11,"tag":"TxValid","timestamp":"2024-10-08T13:24:09.770902618Z","transaction":{"cborHex":"84a300d90102818258207b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c69700018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a00a7d8c082581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a025317c00200a100d9010281825820aa268d154185c9ea06ea73442fd8143c34c1dd543b7142bcb132aac0d1ed6ece5840fc6e2b0750259deedd5a73eeadf481138bf82edc3425614871a0ef09bfcf8cae52a80240fb895a7e6a8ad94d4acb32dffe567ed0d338afcd7878f745737f420df5f6","description":"Ledger Cddl Format","txId":"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce","type":"Witnessed Tx ConwayEra"}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":11},"record":{"hex":"84a300d90102818258207b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c69700018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a00a7d8c082581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a025317c00200a100d9010281825820aa268d154185c9ea06ea73442fd8143c34c1dd543b7142bcb132aac0d1ed6ece5840fc6e2b0750259deedd5a73eeadf481138bf82edc3425614871a0ef09bfcf8cae52a80240fb895a7e6a8ad94d4acb32dffe567ed0d338afcd7878f745737f420df5f6"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":12},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":12,"signatures":{"multiSignature":["aa0673de465f1e7f4ca472b85315243ca2327f15778b3625b8a225563fd4dbb083e2ff9e50bb3a4680a3d1a3da89a839ed841f18c3f85770bf669fe268418608","c682e3bc61e3bf78db64a6bfdd48588e3aafcba62bdb507b8f6b56b364985e575d7185505f33597a45782edff46687d67281e65cf19c7dbbbc68b80b4ed92605","7efc7a1846184214ea2d6748f3db82a34c3be0d9af310d685a47f24e2694223b03611111902512c5674729553440c57755f340694589ccc94e093732b9630908"]},"snapshot":{"confirmedTransactions":["de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":3,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:24:09.825917124Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":13},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":13,"tag":"TxValid","timestamp":"2024-10-08T13:24:30.136780836Z","transaction":{"cborHex":"84a300d9010281825820c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d9700018282581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a00c65d4082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a052f83c00200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840ac8f1632d9a636d3627328ffd09cd32e1b654cbf318f0ce499a9870b05530041aa0badf07cd43fec8f1456537ada71227bea8123c1ed641ae3cb22b7313d5f08f5f6","description":"Ledger Cddl Format","txId":"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74","type":"Witnessed Tx ConwayEra"}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":13},"record":{"hex":"84a300d9010281825820c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d9700018282581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a00c65d4082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a052f83c00200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840ac8f1632d9a636d3627328ffd09cd32e1b654cbf318f0ce499a9870b05530041aa0badf07cd43fec8f1456537ada71227bea8123c1ed641ae3cb22b7313d5f08f5f6"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":14},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":14,"signatures":{"multiSignature":["cdd5844d70c2ad9d6e6981f922757cc5aff7785b425ffcbff83347f2ad9545c646bae9c75f6b65d23aad9452e17704d76cbd5e948408e73277cafa2858cb9104","a1551898f0c4b0f2a9b5a94998a18b9ca962dc92f24d4e5308a0dd449eaf1661c1e075fbc9895ad6f0bbbcd141eb251c9e08493d04adff01125a15906f919701","976e8a5fc707c4e048d266344a2af1a43e94dd7ca29f395d1735c70562ff915af22e9b9829f5058eb02d734e625bd30ada7cbb49060098ad27d6c8a747e9740f"]},"snapshot":{"confirmedTransactions":["bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":4,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":13000000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#1":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":87000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:24:30.186588075Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":15},"record":{"contestationDeadline":"2024-10-08T13:24:42.6Z","headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":15,"snapshotNumber":4,"tag":"HeadIsClosed","timestamp":"2024-10-08T13:24:36.81629911Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":16},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":16,"tag":"ReadyToFanout","timestamp":"2024-10-08T13:24:42.708785607Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":17},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":17,"tag":"HeadIsFinalized","timestamp":"2024-10-08T13:25:02.420848196Z","utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":13000000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#1":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":87000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}}}} From ab725ec6ece039ee973f8fd7bb54a3db61d4706a Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Wed, 6 Nov 2024 17:10:31 +0100 Subject: [PATCH 35/53] add golden --- Cargo.lock | 32 +------------------ Cargo.toml | 1 - tests/hydra.rs | 66 +++++----------------------------------- tests/hydra/golden_1.txt | 14 +++++++++ tests/hydra/golden_2.txt | 23 ++++++++++++++ tests/hydra/logs.txt | 23 -------------- 6 files changed, 45 insertions(+), 114 deletions(-) create mode 100644 tests/hydra/golden_1.txt create mode 100644 tests/hydra/golden_2.txt diff --git a/Cargo.lock b/Cargo.lock index 23019908..9681184e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,7 +184,7 @@ dependencies = [ "bstr", "doc-comment", "libc", - "predicates 3.1.2", + "predicates", "predicates-core", "predicates-tree", "wait-timeout", @@ -2376,15 +2376,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "float-cmp" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" -dependencies = [ - "num-traits", -] - [[package]] name = "flume" version = "0.10.14" @@ -3940,12 +3931,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "normalize-line-endings" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -4191,7 +4176,6 @@ dependencies = [ "net2", "openssl", "pallas", - "predicates 2.1.5", "r2d2_redis", "regex", "reqwest 0.11.24", @@ -4865,20 +4849,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "predicates" -version = "2.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" -dependencies = [ - "difflib", - "float-cmp", - "itertools 0.10.5", - "normalize-line-endings", - "predicates-core", - "regex", -] - [[package]] name = "predicates" version = "3.1.2" diff --git a/Cargo.toml b/Cargo.toml index da9bca01..10ea44f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,4 +86,3 @@ bytes = "1.7.2" [dev-dependencies] assert_cmd = "2" -predicates = "2" diff --git a/tests/hydra.rs b/tests/hydra.rs index c1277633..23608614 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -6,7 +6,6 @@ use anyhow::Result; use assert_cmd::Command; use futures_util::SinkExt; use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; -use predicates::prelude::*; use serde_json::json; use tokio::net::TcpListener; use tokio::runtime::Runtime; @@ -454,64 +453,20 @@ fn scenario_2() -> TestResult { #[test] fn hydra_oura_stdout_scenario_1() -> TestResult { - let tx_event = r#"{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"hex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858401b13ee550f3167a1b94796f2a2f5e22d782d628336a7797c5b798f358fa564dbe92ea75a4e2449eb2cef59c097d8497545ef1e4ea441b88a481194323ae7c608f5f6"}}"#; - let events = vec![ - "PeerConnected".to_string(), - "PeerConnected".to_string(), - "Greetings".to_string(), - "HeadIsInitializing".to_string(), - "Committed".to_string(), - "Committed".to_string(), - "Committed".to_string(), - "HeadIsOpen".to_string(), - "TxValid".to_string(), - tx_event.to_string(), - "SnapshotConfirmed".to_string(), - "HeadIsClosed".to_string(), - "ReadyToFanout".to_string(), - "HeadIsFinalized".to_string(), - ]; - hydra_oura_stdout_test("tests/hydra/scenario_1.txt".to_string(), events) + let golden_jsons = fs::read_to_string("tests/hydra/golden_1.txt")?; + hydra_oura_stdout_test("tests/hydra/scenario_1.txt".to_string(), golden_jsons) } #[test] fn hydra_oura_stdout_scenario_2() -> TestResult { - let tx_event_1 = r#"{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"hex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858407342c0c4de1b55bc9e56c86829a1fb5906e964f109fd698d37d5933ed230b1a878bfee20980bb90b48aa32c472fdd465c2eb770551b84de7041838415faed502f5f6"}}"#; - let tx_event_2 = r#"{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":9},"record":{"hex":"84a300d901028182582065d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e5161701018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a0016e36082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a014810600200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf85840b991c62af8e2b2d06f821fb6064f98c2fc8909b0b2d81435c7e075a61fc92ee6c9224f23d817de35d5529f54034c2ab8dfaded387e99fc525344846bb5dc860af5f6"}}"#; - let tx_event_3 = r#"{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":11},"record":{"hex":"84a300d90102818258207b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c69700018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a00a7d8c082581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a025317c00200a100d9010281825820aa268d154185c9ea06ea73442fd8143c34c1dd543b7142bcb132aac0d1ed6ece5840fc6e2b0750259deedd5a73eeadf481138bf82edc3425614871a0ef09bfcf8cae52a80240fb895a7e6a8ad94d4acb32dffe567ed0d338afcd7878f745737f420df5f6"}}"#; - let tx_event_4 = r#"{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":13},"record":{"hex":"84a300d9010281825820c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d9700018282581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a00c65d4082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a052f83c00200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840ac8f1632d9a636d3627328ffd09cd32e1b654cbf318f0ce499a9870b05530041aa0badf07cd43fec8f1456537ada71227bea8123c1ed641ae3cb22b7313d5f08f5f6"}}"#; - let events = vec![ - "PeerConnected".to_string(), - "PeerConnected".to_string(), - "Greetings".to_string(), - "HeadIsInitializing".to_string(), - "Committed".to_string(), - "Committed".to_string(), - "Committed".to_string(), - "HeadIsOpen".to_string(), - "TxValid".to_string(), - tx_event_1.to_string(), - "SnapshotConfirmed".to_string(), - "TxValid".to_string(), - tx_event_2.to_string(), - "SnapshotConfirmed".to_string(), - "TxValid".to_string(), - tx_event_3.to_string(), - "SnapshotConfirmed".to_string(), - "TxValid".to_string(), - tx_event_4.to_string(), - "SnapshotConfirmed".to_string(), - "HeadIsClosed".to_string(), - "ReadyToFanout".to_string(), - "HeadIsFinalized".to_string(), - ]; - hydra_oura_stdout_test("tests/hydra/scenario_2.txt".to_string(), events) + let golden_jsons = fs::read_to_string("tests/hydra/golden_2.txt")?; + hydra_oura_stdout_test("tests/hydra/scenario_2.txt".to_string(), golden_jsons) } // Run: // cargo test hydra_oura -- --nocapture // in order to see println -fn hydra_oura_stdout_test(file: String, expected: Vec) -> TestResult { +fn hydra_oura_stdout_test(file: String, expected: String) -> TestResult { let rt = Runtime::new().unwrap(); let (tx, _rx) = mpsc::channel(); let _ = rt.block_on(async move { @@ -527,15 +482,8 @@ fn hydra_oura_stdout_test(file: String, expected: Vec) -> TestResult { break; } - let jsons = fs::read_to_string("tests/hydra/logs.txt")?; - let mut predicates = vec![]; - let mut count = 0; - for json in jsons.lines() { - let predicate_fn = predicate::str::contains(&expected[count]); - predicates.push(predicate_fn.eval(json)); - count += 1; - } - assert_eq!(predicates, vec![true; expected.len()]); + let emitted_jsons = fs::read_to_string("tests/hydra/logs.txt")?; + assert_eq!(emitted_jsons, expected); Ok::<(), std::io::Error>(()) }); diff --git a/tests/hydra/golden_1.txt b/tests/hydra/golden_1.txt new file mode 100644 index 00000000..c7fe2453 --- /dev/null +++ b/tests/hydra/golden_1.txt @@ -0,0 +1,14 @@ +{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":0},"record":{"peer":"3","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.556003751Z"}} +{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":1},"record":{"peer":"2","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.559653645Z"}} +{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":2},"record":{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:04:56.445761285Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":2},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","parties":[{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"}],"seq":2,"tag":"HeadIsInitializing","timestamp":"2024-10-08T13:05:47.330461177Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":3},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":3,"tag":"Committed","timestamp":"2024-10-08T13:05:56.918549005Z","utxo":{"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":4},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},"seq":4,"tag":"Committed","timestamp":"2024-10-08T13:06:05.615623261Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":5},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"},"seq":5,"tag":"Committed","timestamp":"2024-10-08T13:06:17.51514695Z","utxo":{"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":6},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":6,"tag":"HeadIsOpen","timestamp":"2024-10-08T13:06:18.687120539Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}},"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":7,"tag":"TxValid","timestamp":"2024-10-08T13:07:18.008847436Z","transaction":{"cborHex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858401b13ee550f3167a1b94796f2a2f5e22d782d628336a7797c5b798f358fa564dbe92ea75a4e2449eb2cef59c097d8497545ef1e4ea441b88a481194323ae7c608f5f6","description":"Ledger Cddl Format","txId":"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1","type":"Witnessed Tx ConwayEra"}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"hex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858401b13ee550f3167a1b94796f2a2f5e22d782d628336a7797c5b798f358fa564dbe92ea75a4e2449eb2cef59c097d8497545ef1e4ea441b88a481194323ae7c608f5f6"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":8},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":8,"signatures":{"multiSignature":["71c368f5f9b124d6b327132fbbf7e92939a88ddcc26e2e06ee17f23318b2bb9c8fa87ebb92d63b6d9cf53ff7612140ea5b7084951ec422d41f909b97f5e64904","51d78ed466a67c4acacf588772d3cc6bf72325e83c318c5ac6a1d90a10ba132a225fa48240570b6254df2c831f952a72213984d0953b22d49a1de1fbfb38540a","993126e89e417fcff9135d7cedc9fa2b46dcf1c9d2ccaa64e5400b782ef40643afe69e73983ee3517492f1816dc99a5dd29002ca9b2d5182bd24e00c9e40b105"]},"snapshot":{"confirmedTransactions":["633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":1,"utxo":{"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":23000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:07:18.064534686Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":9},"record":{"contestationDeadline":"2024-10-08T13:07:37.7Z","headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":9,"snapshotNumber":1,"tag":"HeadIsClosed","timestamp":"2024-10-08T13:07:31.814065753Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":10},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":10,"tag":"ReadyToFanout","timestamp":"2024-10-08T13:07:37.807683329Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":11},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":11,"tag":"HeadIsFinalized","timestamp":"2024-10-08T13:07:40.815046135Z","utxo":{"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"633777d68a85fe989f88aa839aa84743f64d68a931192c41f4df8ed0f16e03d1#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":23000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}}}} diff --git a/tests/hydra/golden_2.txt b/tests/hydra/golden_2.txt new file mode 100644 index 00000000..e0eff470 --- /dev/null +++ b/tests/hydra/golden_2.txt @@ -0,0 +1,23 @@ +{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":0},"record":{"peer":"2","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.954897681Z"}} +{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":1},"record":{"peer":"3","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.98647342Z"}} +{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":2},"record":{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:21:28.141876427Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":2},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","parties":[{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"}],"seq":2,"tag":"HeadIsInitializing","timestamp":"2024-10-08T13:22:05.725778923Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":3},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":3,"tag":"Committed","timestamp":"2024-10-08T13:22:11.016254447Z","utxo":{"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":4},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},"seq":4,"tag":"Committed","timestamp":"2024-10-08T13:22:18.915120931Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":5},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"},"seq":5,"tag":"Committed","timestamp":"2024-10-08T13:22:30.313144555Z","utxo":{"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":6},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":6,"tag":"HeadIsOpen","timestamp":"2024-10-08T13:22:30.520745142Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}},"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":7,"tag":"TxValid","timestamp":"2024-10-08T13:22:44.316966394Z","transaction":{"cborHex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858407342c0c4de1b55bc9e56c86829a1fb5906e964f109fd698d37d5933ed230b1a878bfee20980bb90b48aa32c472fdd465c2eb770551b84de7041838415faed502f5f6","description":"Ledger Cddl Format","txId":"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617","type":"Witnessed Tx ConwayEra"}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"hex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858407342c0c4de1b55bc9e56c86829a1fb5906e964f109fd698d37d5933ed230b1a878bfee20980bb90b48aa32c472fdd465c2eb770551b84de7041838415faed502f5f6"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":8},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":8,"signatures":{"multiSignature":["e9eaa5edf35b35872c94d9b11b1074e8dc737a24ad5956a7c982ee7eb3d2bfe31def724b8a8e586e30806b50ed55984e331a3fae986bc12e6e705e1138164400","7058aca64e437169677db810048bbfc1e0714bbf348cd43c37c46f3d836dc251e09ca7d2a2d6c89e87b2e7d7f4b110024ecbcec59f694370079a069df1903d03","e55bfb59691c93dfd6343a034cf9c78b03261e7d51a16e61e8fd7257378b563b8de6568abd88ddeb532d109e3ad33c6454b268b6ee6b29849786ac5691898603"]},"snapshot":{"confirmedTransactions":["65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":1,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":23000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:22:44.360477345Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":9},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":9,"tag":"TxValid","timestamp":"2024-10-08T13:23:18.169555579Z","transaction":{"cborHex":"84a300d901028182582065d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e5161701018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a0016e36082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a014810600200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf85840b991c62af8e2b2d06f821fb6064f98c2fc8909b0b2d81435c7e075a61fc92ee6c9224f23d817de35d5529f54034c2ab8dfaded387e99fc525344846bb5dc860af5f6","description":"Ledger Cddl Format","txId":"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af","type":"Witnessed Tx ConwayEra"}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":9},"record":{"hex":"84a300d901028182582065d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e5161701018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a0016e36082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a014810600200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf85840b991c62af8e2b2d06f821fb6064f98c2fc8909b0b2d81435c7e075a61fc92ee6c9224f23d817de35d5529f54034c2ab8dfaded387e99fc525344846bb5dc860af5f6"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":10},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":10,"signatures":{"multiSignature":["5897602f543c3692cfb691119b2e9feb22e2302333b3200f95fa65feffaa0846abeb293afc8dcbd4ba2ac4b0ba1df729730d2e3b5e69a652f99b52fa15729209","d2268afebbbde31886cf8ce1c7b827f92a1c675bc9dee5603d6d87d7c30d9f7ae46d596095a6e03624d2526fe101b026c9c765abb7e2603b06ffb4fa6ecc6b0e","b3342f10a0678c24bff40ab5d394b8d7382419b826bfbbc3c019a8c4fd20d6d4db9eec29d72fb58ceb09dfe6720ae5c8ade77fd49e2a4b7e884beeb93f027b00"]},"snapshot":{"confirmedTransactions":["a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":2,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:23:18.220733933Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":11},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":11,"tag":"TxValid","timestamp":"2024-10-08T13:24:09.770902618Z","transaction":{"cborHex":"84a300d90102818258207b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c69700018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a00a7d8c082581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a025317c00200a100d9010281825820aa268d154185c9ea06ea73442fd8143c34c1dd543b7142bcb132aac0d1ed6ece5840fc6e2b0750259deedd5a73eeadf481138bf82edc3425614871a0ef09bfcf8cae52a80240fb895a7e6a8ad94d4acb32dffe567ed0d338afcd7878f745737f420df5f6","description":"Ledger Cddl Format","txId":"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce","type":"Witnessed Tx ConwayEra"}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":11},"record":{"hex":"84a300d90102818258207b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c69700018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a00a7d8c082581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a025317c00200a100d9010281825820aa268d154185c9ea06ea73442fd8143c34c1dd543b7142bcb132aac0d1ed6ece5840fc6e2b0750259deedd5a73eeadf481138bf82edc3425614871a0ef09bfcf8cae52a80240fb895a7e6a8ad94d4acb32dffe567ed0d338afcd7878f745737f420df5f6"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":12},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":12,"signatures":{"multiSignature":["aa0673de465f1e7f4ca472b85315243ca2327f15778b3625b8a225563fd4dbb083e2ff9e50bb3a4680a3d1a3da89a839ed841f18c3f85770bf669fe268418608","c682e3bc61e3bf78db64a6bfdd48588e3aafcba62bdb507b8f6b56b364985e575d7185505f33597a45782edff46687d67281e65cf19c7dbbbc68b80b4ed92605","7efc7a1846184214ea2d6748f3db82a34c3be0d9af310d685a47f24e2694223b03611111902512c5674729553440c57755f340694589ccc94e093732b9630908"]},"snapshot":{"confirmedTransactions":["de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":3,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:24:09.825917124Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":13},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":13,"tag":"TxValid","timestamp":"2024-10-08T13:24:30.136780836Z","transaction":{"cborHex":"84a300d9010281825820c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d9700018282581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a00c65d4082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a052f83c00200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840ac8f1632d9a636d3627328ffd09cd32e1b654cbf318f0ce499a9870b05530041aa0badf07cd43fec8f1456537ada71227bea8123c1ed641ae3cb22b7313d5f08f5f6","description":"Ledger Cddl Format","txId":"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74","type":"Witnessed Tx ConwayEra"}}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":13},"record":{"hex":"84a300d9010281825820c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d9700018282581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a00c65d4082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a052f83c00200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840ac8f1632d9a636d3627328ffd09cd32e1b654cbf318f0ce499a9870b05530041aa0badf07cd43fec8f1456537ada71227bea8123c1ed641ae3cb22b7313d5f08f5f6"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":14},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":14,"signatures":{"multiSignature":["cdd5844d70c2ad9d6e6981f922757cc5aff7785b425ffcbff83347f2ad9545c646bae9c75f6b65d23aad9452e17704d76cbd5e948408e73277cafa2858cb9104","a1551898f0c4b0f2a9b5a94998a18b9ca962dc92f24d4e5308a0dd449eaf1661c1e075fbc9895ad6f0bbbcd141eb251c9e08493d04adff01125a15906f919701","976e8a5fc707c4e048d266344a2af1a43e94dd7ca29f395d1735c70562ff915af22e9b9829f5058eb02d734e625bd30ada7cbb49060098ad27d6c8a747e9740f"]},"snapshot":{"confirmedTransactions":["bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":4,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":13000000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#1":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":87000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:24:30.186588075Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":15},"record":{"contestationDeadline":"2024-10-08T13:24:42.6Z","headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":15,"snapshotNumber":4,"tag":"HeadIsClosed","timestamp":"2024-10-08T13:24:36.81629911Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":16},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":16,"tag":"ReadyToFanout","timestamp":"2024-10-08T13:24:42.708785607Z"}} +{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":17},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":17,"tag":"HeadIsFinalized","timestamp":"2024-10-08T13:25:02.420848196Z","utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":13000000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#1":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":87000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}}}} diff --git a/tests/hydra/logs.txt b/tests/hydra/logs.txt index e0eff470..e69de29b 100644 --- a/tests/hydra/logs.txt +++ b/tests/hydra/logs.txt @@ -1,23 +0,0 @@ -{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":0},"record":{"peer":"2","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.954897681Z"}} -{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":1},"record":{"peer":"3","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.98647342Z"}} -{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":2},"record":{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:21:28.141876427Z"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":2},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","parties":[{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"}],"seq":2,"tag":"HeadIsInitializing","timestamp":"2024-10-08T13:22:05.725778923Z"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":3},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":3,"tag":"Committed","timestamp":"2024-10-08T13:22:11.016254447Z","utxo":{"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}}}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":4},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},"seq":4,"tag":"Committed","timestamp":"2024-10-08T13:22:18.915120931Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}}}}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":5},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"},"seq":5,"tag":"Committed","timestamp":"2024-10-08T13:22:30.313144555Z","utxo":{"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":6},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":6,"tag":"HeadIsOpen","timestamp":"2024-10-08T13:22:30.520745142Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}},"f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d20#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":25000000}}}}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":7,"tag":"TxValid","timestamp":"2024-10-08T13:22:44.316966394Z","transaction":{"cborHex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858407342c0c4de1b55bc9e56c86829a1fb5906e964f109fd698d37d5933ed230b1a878bfee20980bb90b48aa32c472fdd465c2eb770551b84de7041838415faed502f5f6","description":"Ledger Cddl Format","txId":"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617","type":"Witnessed Tx ConwayEra"}}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":7},"record":{"hex":"84a300d9010281825820f0a39560ea80ccc68e8dffb6a4a077c8927811f06c5d9058d0fa2d1a8d047d2000018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a001e848082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a015ef3c00200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf858407342c0c4de1b55bc9e56c86829a1fb5906e964f109fd698d37d5933ed230b1a878bfee20980bb90b48aa32c472fdd465c2eb770551b84de7041838415faed502f5f6"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":8},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":8,"signatures":{"multiSignature":["e9eaa5edf35b35872c94d9b11b1074e8dc737a24ad5956a7c982ee7eb3d2bfe31def724b8a8e586e30806b50ed55984e331a3fae986bc12e6e705e1138164400","7058aca64e437169677db810048bbfc1e0714bbf348cd43c37c46f3d836dc251e09ca7d2a2d6c89e87b2e7d7f4b110024ecbcec59f694370079a069df1903d03","e55bfb59691c93dfd6343a034cf9c78b03261e7d51a16e61e8fd7257378b563b8de6568abd88ddeb532d109e3ad33c6454b268b6ee6b29849786ac5691898603"]},"snapshot":{"confirmedTransactions":["65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":1,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":23000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:22:44.360477345Z"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":9},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":9,"tag":"TxValid","timestamp":"2024-10-08T13:23:18.169555579Z","transaction":{"cborHex":"84a300d901028182582065d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e5161701018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a0016e36082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a014810600200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf85840b991c62af8e2b2d06f821fb6064f98c2fc8909b0b2d81435c7e075a61fc92ee6c9224f23d817de35d5529f54034c2ab8dfaded387e99fc525344846bb5dc860af5f6","description":"Ledger Cddl Format","txId":"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af","type":"Witnessed Tx ConwayEra"}}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":9},"record":{"hex":"84a300d901028182582065d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e5161701018282581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a0016e36082581d600d45f2b310a98e766cee2ab2f6756c91719bd7b35929cef058365b651a014810600200a100d90102818258200f193a88190f6dace0a3db1e0e50797a6e28cd4b6e289260dc96b5a8d7934bf85840b991c62af8e2b2d06f821fb6064f98c2fc8909b0b2d81435c7e075a61fc92ee6c9224f23d817de35d5529f54034c2ab8dfaded387e99fc525344846bb5dc860af5f6"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":10},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":10,"signatures":{"multiSignature":["5897602f543c3692cfb691119b2e9feb22e2302333b3200f95fa65feffaa0846abeb293afc8dcbd4ba2ac4b0ba1df729730d2e3b5e69a652f99b52fa15729209","d2268afebbbde31886cf8ce1c7b827f92a1c675bc9dee5603d6d87d7c30d9f7ae46d596095a6e03624d2526fe101b026c9c765abb7e2603b06ffb4fa6ecc6b0e","b3342f10a0678c24bff40ab5d394b8d7382419b826bfbbc3c019a8c4fd20d6d4db9eec29d72fb58ceb09dfe6720ae5c8ade77fd49e2a4b7e884beeb93f027b00"]},"snapshot":{"confirmedTransactions":["a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":2,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:23:18.220733933Z"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":11},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":11,"tag":"TxValid","timestamp":"2024-10-08T13:24:09.770902618Z","transaction":{"cborHex":"84a300d90102818258207b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c69700018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a00a7d8c082581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a025317c00200a100d9010281825820aa268d154185c9ea06ea73442fd8143c34c1dd543b7142bcb132aac0d1ed6ece5840fc6e2b0750259deedd5a73eeadf481138bf82edc3425614871a0ef09bfcf8cae52a80240fb895a7e6a8ad94d4acb32dffe567ed0d338afcd7878f745737f420df5f6","description":"Ledger Cddl Format","txId":"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce","type":"Witnessed Tx ConwayEra"}}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":11},"record":{"hex":"84a300d90102818258207b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c69700018282581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a00a7d8c082581d605e4e214a6addd337126b3a61faad5dfe1e4f14f637a8969e3a05eefd1a025317c00200a100d9010281825820aa268d154185c9ea06ea73442fd8143c34c1dd543b7142bcb132aac0d1ed6ece5840fc6e2b0750259deedd5a73eeadf481138bf82edc3425614871a0ef09bfcf8cae52a80240fb895a7e6a8ad94d4acb32dffe567ed0d338afcd7878f745737f420df5f6"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":12},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":12,"signatures":{"multiSignature":["aa0673de465f1e7f4ca472b85315243ca2327f15778b3625b8a225563fd4dbb083e2ff9e50bb3a4680a3d1a3da89a839ed841f18c3f85770bf669fe268418608","c682e3bc61e3bf78db64a6bfdd48588e3aafcba62bdb507b8f6b56b364985e575d7185505f33597a45782edff46687d67281e65cf19c7dbbbc68b80b4ed92605","7efc7a1846184214ea2d6748f3db82a34c3be0d9af310d685a47f24e2694223b03611111902512c5674729553440c57755f340694589ccc94e093732b9630908"]},"snapshot":{"confirmedTransactions":["de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":3,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:24:09.825917124Z"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":13},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":13,"tag":"TxValid","timestamp":"2024-10-08T13:24:30.136780836Z","transaction":{"cborHex":"84a300d9010281825820c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d9700018282581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a00c65d4082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a052f83c00200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840ac8f1632d9a636d3627328ffd09cd32e1b654cbf318f0ce499a9870b05530041aa0badf07cd43fec8f1456537ada71227bea8123c1ed641ae3cb22b7313d5f08f5f6","description":"Ledger Cddl Format","txId":"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74","type":"Witnessed Tx ConwayEra"}}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":13},"record":{"hex":"84a300d9010281825820c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d9700018282581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a00c65d4082581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a052f83c00200a100d9010281825820f953b2d6b6f319faa9f8462257eb52ad73e33199c650f0755e279e21882399c05840ac8f1632d9a636d3627328ffd09cd32e1b654cbf318f0ce499a9870b05530041aa0badf07cd43fec8f1456537ada71227bea8123c1ed641ae3cb22b7313d5f08f5f6"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":14},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":14,"signatures":{"multiSignature":["cdd5844d70c2ad9d6e6981f922757cc5aff7785b425ffcbff83347f2ad9545c646bae9c75f6b65d23aad9452e17704d76cbd5e948408e73277cafa2858cb9104","a1551898f0c4b0f2a9b5a94998a18b9ca962dc92f24d4e5308a0dd449eaf1661c1e075fbc9895ad6f0bbbcd141eb251c9e08493d04adff01125a15906f919701","976e8a5fc707c4e048d266344a2af1a43e94dd7ca29f395d1735c70562ff915af22e9b9829f5058eb02d734e625bd30ada7cbb49060098ad27d6c8a747e9740f"]},"snapshot":{"confirmedTransactions":["bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74"],"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","snapshotNumber":4,"utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":13000000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#1":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":87000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}},"utxoToDecommit":null,"version":0},"tag":"SnapshotConfirmed","timestamp":"2024-10-08T13:24:30.186588075Z"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":15},"record":{"contestationDeadline":"2024-10-08T13:24:42.6Z","headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":15,"snapshotNumber":4,"tag":"HeadIsClosed","timestamp":"2024-10-08T13:24:36.81629911Z"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":16},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":16,"tag":"ReadyToFanout","timestamp":"2024-10-08T13:24:42.708785607Z"}} -{"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":17},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","seq":17,"tag":"HeadIsFinalized","timestamp":"2024-10-08T13:25:02.420848196Z","utxo":{"65d64ade1fa9da5099107e3ab9efeea6f305c3c831ca8b9c8f87594289e51617#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":2000000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#0":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":1500000}},"a8117ebbc21da57e580d95bcda7c316eff492c977e61a68fd0aea251348eb4af#1":{"address":"addr_test1vqx5tu4nzz5cuanvac4t9an4djghrx7hkdvjnnhstqm9kegvm6g6c","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":21500000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":13000000}},"bf4ba0d28cc39abee99b7b2bda7d104871e3e979ebfdc531ec34c490f85d1d74#1":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":87000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":11000000}},"de33eeedc890f11fab3c1d827974fbc69e96cfdce2418573b30c9e0844a738ce#1":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":39000000}}}}} From e96758abfc9123b5c6832f03bbd59507da8eea93 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Thu, 7 Nov 2024 15:27:04 +0100 Subject: [PATCH 36/53] factor out `run_daemon` --- src/bin/oura/main.rs | 6 +- src/bin/oura/run_daemon.rs | 85 +++++++++++++++++ src/{bin/oura/daemon.rs => daemon/mod.rs} | 109 +++------------------- src/lib.rs | 1 + tests/hydra.rs | 20 ++-- tests/hydra/logs.txt | 0 6 files changed, 110 insertions(+), 111 deletions(-) create mode 100644 src/bin/oura/run_daemon.rs rename src/{bin/oura/daemon.rs => daemon/mod.rs} (61%) delete mode 100644 tests/hydra/logs.txt diff --git a/src/bin/oura/main.rs b/src/bin/oura/main.rs index 24420043..c253a8cc 100644 --- a/src/bin/oura/main.rs +++ b/src/bin/oura/main.rs @@ -2,21 +2,21 @@ use clap::Parser; use std::process; mod console; -mod daemon; +mod run_daemon; #[derive(Parser)] #[clap(name = "Oura")] #[clap(bin_name = "oura")] #[clap(author, version, about, long_about = None)] enum Oura { - Daemon(daemon::Args), + Daemon(run_daemon::Args), } fn main() { let args = Oura::parse(); let result = match args { - Oura::Daemon(x) => daemon::run(&x), + Oura::Daemon(x) => run_daemon::run(&x), }; if let Err(err) = &result { diff --git a/src/bin/oura/run_daemon.rs b/src/bin/oura/run_daemon.rs new file mode 100644 index 00000000..1febaf32 --- /dev/null +++ b/src/bin/oura/run_daemon.rs @@ -0,0 +1,85 @@ +use gasket::daemon::Daemon; +use oura::framework::*; +use std::net::SocketAddr; +use std::sync::Arc; +use tracing::info; +use oura::daemon::{run_daemon, ConfigRoot, MetricsConfig}; + +use crate::console; + +fn setup_tracing() { + tracing::subscriber::set_global_default( + tracing_subscriber::FmtSubscriber::builder() + .with_max_level(tracing::Level::DEBUG) + .finish(), + ) + .unwrap(); +} + +async fn serve_prometheus( + daemon: Arc, + metrics: Option, +) -> Result<(), Error> { + if let Some(metrics) = metrics { + info!("starting metrics exporter"); + let runtime = daemon.clone(); + + let addr: SocketAddr = metrics + .address + .as_deref() + .unwrap_or("0.0.0.0:9186") + .parse() + .map_err(Error::parse)?; + + gasket_prometheus::serve(addr, runtime).await; + } + + Ok(()) +} + +pub fn run(args: &Args) -> Result<(), Error> { + if !args.tui { + setup_tracing(); + } + + let config = ConfigRoot::new(&args.config).map_err(Error::config)?; + let metrics = config.metrics.clone(); + + let daemon = run_daemon(config)?; + + info!("oura is running"); + + let daemon = Arc::new(daemon); + + let tokio_rt = tokio::runtime::Builder::new_multi_thread() + .enable_io() + .enable_time() + .build() + .unwrap(); + + let prometheus = tokio_rt.spawn(serve_prometheus(daemon.clone(), metrics)); + let tui = tokio_rt.spawn(console::render(daemon.clone(), args.tui)); + + daemon.block(); + + info!("oura is stopping"); + + daemon.teardown(); + prometheus.abort(); + tui.abort(); + + Ok(()) +} + + +#[derive(clap::Args)] +#[clap(author, version, about, long_about = None)] +pub struct Args { + /// config file to load by the daemon + #[clap(long, value_parser)] + config: Option, + + /// display the terminal UI + #[clap(long, action)] + tui: bool, +} diff --git a/src/bin/oura/daemon.rs b/src/daemon/mod.rs similarity index 61% rename from src/bin/oura/daemon.rs rename to src/daemon/mod.rs index 3da8d9db..3634c115 100644 --- a/src/bin/oura/daemon.rs +++ b/src/daemon/mod.rs @@ -1,11 +1,8 @@ + use gasket::daemon::Daemon; -use oura::{cursor, filters, framework::*, sinks, sources}; +use crate::{cursor, filters, framework::*, sinks, sources}; use serde::{Deserialize, Serialize}; -use std::net::SocketAddr; -use std::{sync::Arc, time::Duration}; -use tracing::info; - -use crate::console; +use std::time::Duration; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct MetricsConfig { @@ -13,16 +10,16 @@ pub struct MetricsConfig { } #[derive(Deserialize)] -struct ConfigRoot { - source: sources::Config, - filters: Option>, - sink: sinks::Config, - intersect: IntersectConfig, - finalize: Option, - chain: Option, - retries: Option, - cursor: Option, - metrics: Option, +pub struct ConfigRoot { + pub source: sources::Config, + pub filters: Option>, + pub sink: sinks::Config, + pub intersect: IntersectConfig, + pub finalize: Option, + pub chain: Option, + pub retries: Option, + pub cursor: Option, + pub metrics: Option, } impl ConfigRoot { @@ -94,50 +91,13 @@ fn connect_stages( Ok(runtime) } -fn setup_tracing() { - tracing::subscriber::set_global_default( - tracing_subscriber::FmtSubscriber::builder() - .with_max_level(tracing::Level::DEBUG) - .finish(), - ) - .unwrap(); -} - -async fn serve_prometheus( - daemon: Arc, - metrics: Option, -) -> Result<(), Error> { - if let Some(metrics) = metrics { - info!("starting metrics exporter"); - let runtime = daemon.clone(); - - let addr: SocketAddr = metrics - .address - .as_deref() - .unwrap_or("0.0.0.0:9186") - .parse() - .map_err(Error::parse)?; - - gasket_prometheus::serve(addr, runtime).await; - } - - Ok(()) -} - -pub fn run(args: &Args) -> Result<(), Error> { - if !args.tui { - setup_tracing(); - } - - let config = ConfigRoot::new(&args.config).map_err(Error::config)?; - +pub fn run_daemon(config: ConfigRoot) -> Result { let chain = config.chain.unwrap_or_default(); let intersect = config.intersect; let finalize = config.finalize; let current_dir = std::env::current_dir().unwrap(); let cursor = config.cursor.unwrap_or_default(); let breadcrumbs = cursor.initial_load()?; - let ctx = Context { chain, intersect, @@ -145,56 +105,17 @@ pub fn run(args: &Args) -> Result<(), Error> { current_dir, breadcrumbs, }; - let source = config.source.bootstrapper(&ctx)?; - let filters = config .filters .into_iter() .flatten() .map(|x| x.bootstrapper(&ctx)) .collect::>()?; - let sink = config.sink.bootstrapper(&ctx)?; - let cursor = cursor.bootstrapper(&ctx)?; - let retries = define_gasket_policy(config.retries.as_ref()); - let daemon = connect_stages(source, filters, sink, cursor, retries)?; - - info!("oura is running"); - - let daemon = Arc::new(daemon); - - let tokio_rt = tokio::runtime::Builder::new_multi_thread() - .enable_io() - .enable_time() - .build() - .unwrap(); - - let prometheus = tokio_rt.spawn(serve_prometheus(daemon.clone(), config.metrics)); - let tui = tokio_rt.spawn(console::render(daemon.clone(), args.tui)); - - daemon.block(); - - info!("oura is stopping"); - - daemon.teardown(); - prometheus.abort(); - tui.abort(); - - Ok(()) + Ok(daemon) } -#[derive(clap::Args)] -#[clap(author, version, about, long_about = None)] -pub struct Args { - /// config file to load by the daemon - #[clap(long, value_parser)] - config: Option, - - /// display the terminal UI - #[clap(long, action)] - tui: bool, -} diff --git a/src/lib.rs b/src/lib.rs index 36bfe792..23f77b3d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,3 +3,4 @@ pub mod filters; pub mod framework; pub mod sinks; pub mod sources; +pub mod daemon; diff --git a/tests/hydra.rs b/tests/hydra.rs index 23608614..955bbe91 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -1,4 +1,5 @@ use std::fs; +use std::path::PathBuf; use std::sync::mpsc; use std::time::Duration; @@ -8,6 +9,8 @@ use futures_util::SinkExt; use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; use serde_json::json; use tokio::net::TcpListener; +use oura::daemon::{run_daemon, ConfigRoot}; +use gasket::daemon::Daemon; use tokio::runtime::Runtime; use tokio::time; use tokio_tungstenite::accept_async; @@ -511,23 +514,12 @@ async fn handle_connection( } async fn oura_pipeline() -> Result<()> { - //Clean output file - let _ = std::process::Command::new("truncate") - .arg("-s 0") - .arg("tests/hydra/logs.txt") - .spawn(); - tokio::spawn(invoke_pipeline()); time::sleep(Duration::from_secs(1)).await; - Ok(()) } -async fn invoke_pipeline() -> Result<()> { - let mut cmd = Command::cargo_bin("oura")?; - cmd.args(vec!["daemon", "--config", "tests/daemon.toml"]) - .assert() - .success(); - - Ok(()) +async fn invoke_pipeline() -> Result { + let config = ConfigRoot::new(&Some(PathBuf::from("tests/daemon.toml")))?; + run_daemon(config).map_err(|e| anyhow::anyhow!(e)) } diff --git a/tests/hydra/logs.txt b/tests/hydra/logs.txt deleted file mode 100644 index e69de29b..00000000 From 365210bf352ef5525cb530017df967ae09eb2462 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Thu, 7 Nov 2024 16:22:06 +0100 Subject: [PATCH 37/53] factor out `mock_hydra_node` --- tests/hydra.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index 955bbe91..69588a66 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -4,7 +4,6 @@ use std::sync::mpsc; use std::time::Duration; use anyhow::Result; -use assert_cmd::Command; use futures_util::SinkExt; use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; use serde_json::json; @@ -471,7 +470,6 @@ fn hydra_oura_stdout_scenario_2() -> TestResult { // in order to see println fn hydra_oura_stdout_test(file: String, expected: String) -> TestResult { let rt = Runtime::new().unwrap(); - let (tx, _rx) = mpsc::channel(); let _ = rt.block_on(async move { let addr = "127.0.0.1:4001".to_string(); let server = TcpListener::bind(&addr).await?; @@ -479,11 +477,7 @@ fn hydra_oura_stdout_test(file: String, expected: String) -> TestResult { let _ = tokio::spawn(async move { oura_pipeline().await }); - while let Ok((stream, _)) = server.accept().await { - tokio::spawn(handle_connection(stream, file, tx)); - time::sleep(Duration::from_secs(3)).await; - break; - } + mock_hydra_node(server, file).await; let emitted_jsons = fs::read_to_string("tests/hydra/logs.txt")?; assert_eq!(emitted_jsons, expected); @@ -493,6 +487,15 @@ fn hydra_oura_stdout_test(file: String, expected: String) -> TestResult { Ok(()) } +async fn mock_hydra_node(server: TcpListener, file: String) { + let (tx, _rx) = mpsc::channel(); + while let Ok((stream, _)) = server.accept().await { + tokio::spawn(handle_connection(stream, file, tx)); + time::sleep(Duration::from_secs(3)).await; + break; + } +} + async fn handle_connection( stream: tokio::net::TcpStream, file: String, From f32ddedfe22530e1f51ff8ada3b2793fe3b285a9 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Thu, 7 Nov 2024 16:42:24 +0100 Subject: [PATCH 38/53] Tweak integration tests - Use random TCP ports - Use random output files - Use goldenfile (has the practical UPDATE_GOLDENFILES=1 flag) --- Cargo.lock | 115 +++++++++++-------------- Cargo.toml | 4 +- src/sources/hydra.rs | 2 +- tests/hydra.rs | 100 +++++++++++++-------- tests/hydra/{golden_1.txt => golden_1} | 0 tests/hydra/{golden_2.txt => golden_2} | 0 6 files changed, 116 insertions(+), 105 deletions(-) rename tests/hydra/{golden_1.txt => golden_1} (100%) rename tests/hydra/{golden_2.txt => golden_2} (100%) diff --git a/Cargo.lock b/Cargo.lock index 9681184e..91f73cf8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -174,22 +174,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" -[[package]] -name = "assert_cmd" -version = "2.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" -dependencies = [ - "anstyle", - "bstr", - "doc-comment", - "libc", - "predicates", - "predicates-core", - "predicates-tree", - "wait-timeout", -] - [[package]] name = "async-channel" version = "1.9.0" @@ -1884,12 +1868,6 @@ dependencies = [ "cipher", ] -[[package]] -name = "difflib" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" - [[package]] name = "digest" version = "0.9.0" @@ -2677,6 +2655,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "goldenfile" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "672ff1c2f0537cf3f92065ce8aa77e2fc3f2abae2c805eb67f40ceecfbdee428" +dependencies = [ + "scopeguard", + "similar-asserts", + "tempfile", + "yansi", +] + [[package]] name = "google-cloud-auth" version = "0.11.0" @@ -4139,7 +4129,6 @@ name = "oura" version = "2.0.0-alpha.4" dependencies = [ "anyhow", - "assert_cmd", "async-trait", "aws-config", "aws-sdk-lambda", @@ -4159,6 +4148,7 @@ dependencies = [ "futures-util", "gasket", "gasket-prometheus", + "goldenfile", "google-cloud-default", "google-cloud-googleapis", "google-cloud-pubsub", @@ -4176,6 +4166,7 @@ dependencies = [ "net2", "openssl", "pallas", + "port-selector", "r2d2_redis", "regex", "reqwest 0.11.24", @@ -4184,6 +4175,7 @@ dependencies = [ "sqlx", "strum 0.24.1", "strum_macros 0.25.3", + "tempfile", "thiserror", "tokio", "tokio-tungstenite", @@ -4831,6 +4823,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "port-selector" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd119ef551a50cd8939f0ff93bd062891f7b0dbb771b4a05df8a9c13aebaff68" +dependencies = [ + "rand", +] + [[package]] name = "portable-atomic" version = "1.6.0" @@ -4849,33 +4850,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "predicates" -version = "3.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" -dependencies = [ - "anstyle", - "difflib", - "predicates-core", -] - -[[package]] -name = "predicates-core" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" - -[[package]] -name = "predicates-tree" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" -dependencies = [ - "predicates-core", - "termtree", -] - [[package]] name = "prettyplease" version = "0.2.17" @@ -6052,6 +6026,26 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "similar" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" +dependencies = [ + "bstr", + "unicode-segmentation", +] + +[[package]] +name = "similar-asserts" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe85670573cd6f0fa97940f26e7e6601213c3b0555246c24234131f88c5709e" +dependencies = [ + "console", + "similar", +] + [[package]] name = "simple_asn1" version = "0.6.2" @@ -6611,12 +6605,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "termtree" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" - [[package]] name = "textwrap" version = "0.16.1" @@ -7330,15 +7318,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - [[package]] name = "waker-fn" version = "1.1.1" @@ -8303,6 +8282,12 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + [[package]] name = "yasna" version = "0.5.2" diff --git a/Cargo.toml b/Cargo.toml index 10ea44f3..2eff47b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,4 +85,6 @@ futures-util = "0.3" bytes = "1.7.2" [dev-dependencies] -assert_cmd = "2" +goldenfile = "1.7.3" +tempfile = "3.4" +port-selector = "0.1.6" diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 41e750dd..2bc5cda7 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -254,7 +254,7 @@ impl gasket::framework::Worker for Worker { #[derive(Deserialize)] pub struct Config { - hydra_socket_url: String, + pub hydra_socket_url: String, } impl Config { diff --git a/tests/hydra.rs b/tests/hydra.rs index 69588a66..99c72e1f 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -6,13 +6,19 @@ use std::time::Duration; use anyhow::Result; use futures_util::SinkExt; use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; +use oura::sinks::Config::FileRotate; use serde_json::json; use tokio::net::TcpListener; +use oura::sources::Config::Hydra; use oura::daemon::{run_daemon, ConfigRoot}; use gasket::daemon::Daemon; +use goldenfile::Mint; +use std::io::Write; +use tempfile::NamedTempFile; use tokio::runtime::Runtime; use tokio::time; use tokio_tungstenite::accept_async; +use port_selector::random_free_port; use tokio_tungstenite::tungstenite::protocol::Message; type TestResult = Result<(), Box>; @@ -455,74 +461,92 @@ fn scenario_2() -> TestResult { #[test] fn hydra_oura_stdout_scenario_1() -> TestResult { - let golden_jsons = fs::read_to_string("tests/hydra/golden_1.txt")?; - hydra_oura_stdout_test("tests/hydra/scenario_1.txt".to_string(), golden_jsons) + hydra_oura_stdout_test("tests/hydra/scenario_1.txt".to_string(), "golden_1".to_string()) } #[test] fn hydra_oura_stdout_scenario_2() -> TestResult { - let golden_jsons = fs::read_to_string("tests/hydra/golden_2.txt")?; - hydra_oura_stdout_test("tests/hydra/scenario_2.txt".to_string(), golden_jsons) + hydra_oura_stdout_test("tests/hydra/scenario_2.txt".to_string(), "golden_2".to_string()) } // Run: // cargo test hydra_oura -- --nocapture // in order to see println -fn hydra_oura_stdout_test(file: String, expected: String) -> TestResult { +fn hydra_oura_stdout_test(scenario_file: String, golden_name: String) -> TestResult { + + let mut mint = Mint::new("tests/hydra"); + let mut golden = mint.new_goldenfile(golden_name.clone()).unwrap(); + let rt = Runtime::new().unwrap(); let _ = rt.block_on(async move { - let addr = "127.0.0.1:4001".to_string(); + let port: u16 = random_free_port().unwrap(); + let addr= format!("127.0.0.1:{}", port); let server = TcpListener::bind(&addr).await?; - println!("WebSocket server started on ws://{}", addr); + let output_file = NamedTempFile::new()?; + let config = test_config(&output_file, &addr); - let _ = tokio::spawn(async move { oura_pipeline().await }); + println!("WebSocket server starting on ws://{}", addr); - mock_hydra_node(server, file).await; - - let emitted_jsons = fs::read_to_string("tests/hydra/logs.txt")?; - assert_eq!(emitted_jsons, expected); + let _ = tokio::spawn(async move { run_oura(config) }); + let _ = mock_hydra_node(server, scenario_file).await; + // After the connection is established, give oura time to process + // the chain data and write the output to disk. + time::sleep(Duration::from_secs(3)).await; + let emitted_jsons= fs::read_to_string(output_file)?; + golden.write_all(emitted_jsons.as_bytes()).unwrap(); + println!("test done, will exit"); Ok::<(), std::io::Error>(()) }); Ok(()) } +/// Will await the first connection, and then return while handling it in the +/// background. async fn mock_hydra_node(server: TcpListener, file: String) { - let (tx, _rx) = mpsc::channel(); - while let Ok((stream, _)) = server.accept().await { - tokio::spawn(handle_connection(stream, file, tx)); - time::sleep(Duration::from_secs(3)).await; - break; + async fn handle_connection( + stream: tokio::net::TcpStream, + file: String, + tx: mpsc::Sender, + ) -> Result<()> { + let mut ws_stream = accept_async(stream).await?; + println!("WebSocket server oura connection established"); + + let to_send = fs::read_to_string(file)?; + + let mut lines = 0; + for line in to_send.lines() { + ws_stream.send(Message::Text(line.to_string())).await?; + lines += 1; + } + tx.send(lines).unwrap(); + Ok(()) } + + let (tx, _rx) = mpsc::channel(); + let (stream, _) = server.accept().await.unwrap(); + let _ = tokio::spawn(handle_connection(stream, file, tx)); } -async fn handle_connection( - stream: tokio::net::TcpStream, - file: String, - tx: mpsc::Sender, -) -> Result<()> { - let mut ws_stream = accept_async(stream).await?; - println!("WebSocket server oura connection established"); - let to_send = fs::read_to_string(file)?; +fn test_config(tmp_output_file: &NamedTempFile, socket_path: &String) -> ConfigRoot { + let mut config = ConfigRoot::new(&Some(PathBuf::from("tests/daemon.toml"))).unwrap(); - let mut lines = 0; - for line in to_send.lines() { - ws_stream.send(Message::Text(line.to_string())).await?; - lines += 1; + if let FileRotate(ref mut file_rotate) = config.sink { + file_rotate.output_path = Some(tmp_output_file.path().to_string_lossy().to_string()); + } else { + panic!("assumed config template to use file_rotate sink"); } - tx.send(lines).unwrap(); - Ok(()) -} + if let Hydra(ref mut hydra_config) = config.source { + hydra_config.hydra_socket_url = "ws://".to_string() + socket_path; + } else { + panic!("assumed config template to use hydra source"); + } -async fn oura_pipeline() -> Result<()> { - tokio::spawn(invoke_pipeline()); - time::sleep(Duration::from_secs(1)).await; - Ok(()) + config } -async fn invoke_pipeline() -> Result { - let config = ConfigRoot::new(&Some(PathBuf::from("tests/daemon.toml")))?; +fn run_oura(config: ConfigRoot) -> Result { run_daemon(config).map_err(|e| anyhow::anyhow!(e)) } diff --git a/tests/hydra/golden_1.txt b/tests/hydra/golden_1 similarity index 100% rename from tests/hydra/golden_1.txt rename to tests/hydra/golden_1 diff --git a/tests/hydra/golden_2.txt b/tests/hydra/golden_2 similarity index 100% rename from tests/hydra/golden_2.txt rename to tests/hydra/golden_2 From f53c10cfbf016f9427a0c35ea61b5d17688d78ad Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Wed, 30 Oct 2024 15:16:28 +0100 Subject: [PATCH 39/53] Make intersection logic more robust --- src/sources/hydra.rs | 61 +++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 2bc5cda7..a6287195 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -4,7 +4,7 @@ use tokio_tungstenite::MaybeTlsStream; use pallas::network::miniprotocols::Point; use gasket::framework::*; -use tracing::{debug, error, info}; +use tracing::{debug, error, info, warn}; use futures_util::StreamExt; use tokio_tungstenite::WebSocketStream; @@ -143,7 +143,41 @@ pub struct Stage { pub struct Worker { socket: HydraConnection, - intersect: Point, + intersect: WorkerIntersect, +} +#[derive(Debug, Clone)] +/// Worker state for finding the right intersection point +pub enum WorkerIntersect { + SkipUntil(u64, Vec), // Possibility of Point::Origin is excluded + ProcessMessages, +} + +impl WorkerIntersect { + /// When passed the point of the next hydra message, this function will return whether or not + /// that message should be processed. The `WorkerIntersect` will be mutated to reflect the + /// state where the next message has been processed. + fn should_process(&mut self, next: Point) -> bool { + match self { + WorkerIntersect::SkipUntil(slot, hash) => { + let p = Point::Specific(slot.clone(), hash.clone()); + debug!( + "Skipping message {} before or at intersection {}", + next.slot_or_default(), p.slot_or_default() + ); + if p == next { + *self = WorkerIntersect::ProcessMessages; + } else if next.slot_or_default() >= p.slot_or_default() { + warn!( + "Skipping message from wrong hydra chain (intersection point hash mismatch) {:?} {:?}", + p, next + + ); + } + false + } + WorkerIntersect::ProcessMessages => true, + } + } } impl Worker { @@ -176,11 +210,11 @@ impl Worker { } } -fn intersect_from_config(intersect: &IntersectConfig) -> Point { +fn intersect_from_config(intersect: &IntersectConfig) -> WorkerIntersect { match intersect { IntersectConfig::Origin => { - info!("intersecting origin"); - Point::Origin + info!("starting from Origin"); + WorkerIntersect::ProcessMessages } IntersectConfig::Tip => { panic!("intersecting tip not currently supported with hydra as source") @@ -188,7 +222,7 @@ fn intersect_from_config(intersect: &IntersectConfig) -> Point { IntersectConfig::Point(slot, hash_str) => { info!("intersecting specific point"); let hash = hex::decode(hash_str).expect("valid hex hash"); - Point::Specific(slot.clone(), hash) + WorkerIntersect::SkipUntil(slot.clone(), hash) } IntersectConfig::Breadcrumbs(_) => { panic!("intersecting breadcrumbs not currently supported with hydra as source") @@ -226,19 +260,10 @@ impl gasket::framework::Worker for Worker { debug!("Hydra message: {}", text); match serde_json::from_str::(text) { Ok(hydra_message) => { - // TODO: search for the intersection point to ensure - // we're on the same chain. - match &self.intersect { - Point::Specific(slot, _hash) if &hydra_message.seq <= slot => { - debug!( - "Skipping message {} before or at intersection {}", - hydra_message.seq, slot - ); - Ok(()) - } - Point::Origin | Point::Specific(_, _) => { + if self.intersect.should_process(hydra_message.pseudo_point()) { self.process_next(stage, hydra_message).await - } + } else { + Ok(()) } } Err(err) => { From bf14271e0a269c8e4a190738448b1b664486ab00 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Tue, 12 Nov 2024 19:24:56 +0100 Subject: [PATCH 40/53] let `mock_hydra_node` take contents instead of file --- tests/hydra.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index 99c72e1f..62a7ac8e 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -461,18 +461,20 @@ fn scenario_2() -> TestResult { #[test] fn hydra_oura_stdout_scenario_1() -> TestResult { - hydra_oura_stdout_test("tests/hydra/scenario_1.txt".to_string(), "golden_1".to_string()) + let scenario = fs::read_to_string("tests/hydra/scenario_1.txt")?; + hydra_oura_stdout_test(scenario, "golden_1".to_string()) } #[test] fn hydra_oura_stdout_scenario_2() -> TestResult { - hydra_oura_stdout_test("tests/hydra/scenario_2.txt".to_string(), "golden_2".to_string()) + let scenario = fs::read_to_string("tests/hydra/scenario_2.txt")?; + hydra_oura_stdout_test(scenario, "golden_2".to_string()) } // Run: // cargo test hydra_oura -- --nocapture // in order to see println -fn hydra_oura_stdout_test(scenario_file: String, golden_name: String) -> TestResult { +fn hydra_oura_stdout_test(mock_data: String, golden_name: String) -> TestResult { let mut mint = Mint::new("tests/hydra"); let mut golden = mint.new_goldenfile(golden_name.clone()).unwrap(); @@ -488,7 +490,7 @@ fn hydra_oura_stdout_test(scenario_file: String, golden_name: String) -> TestRes println!("WebSocket server starting on ws://{}", addr); let _ = tokio::spawn(async move { run_oura(config) }); - let _ = mock_hydra_node(server, scenario_file).await; + let _ = mock_hydra_node(server, mock_data).await; // After the connection is established, give oura time to process // the chain data and write the output to disk. @@ -503,19 +505,17 @@ fn hydra_oura_stdout_test(scenario_file: String, golden_name: String) -> TestRes /// Will await the first connection, and then return while handling it in the /// background. -async fn mock_hydra_node(server: TcpListener, file: String) { +async fn mock_hydra_node(server: TcpListener, mock_data: String) { async fn handle_connection( stream: tokio::net::TcpStream, - file: String, + mock_data: String, tx: mpsc::Sender, ) -> Result<()> { let mut ws_stream = accept_async(stream).await?; println!("WebSocket server oura connection established"); - let to_send = fs::read_to_string(file)?; - let mut lines = 0; - for line in to_send.lines() { + for line in mock_data.lines() { ws_stream.send(Message::Text(line.to_string())).await?; lines += 1; } @@ -525,7 +525,7 @@ async fn mock_hydra_node(server: TcpListener, file: String) { let (tx, _rx) = mpsc::channel(); let (stream, _) = server.accept().await.unwrap(); - let _ = tokio::spawn(handle_connection(stream, file, tx)); + let _ = tokio::spawn(handle_connection(stream, mock_data , tx)); } From a0dbc4d3cfd54c4d34167e6633af354389a3dba0 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Wed, 13 Nov 2024 13:51:19 +0100 Subject: [PATCH 41/53] Add basic tests for hydra source intersection --- tests/hydra.rs | 72 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index 62a7ac8e..038d095d 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -1,3 +1,5 @@ +use serde::Deserialize; +use oura::framework::IntersectConfig; use std::fs; use std::path::PathBuf; use std::sync::mpsc; @@ -7,7 +9,7 @@ use anyhow::Result; use futures_util::SinkExt; use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; use oura::sinks::Config::FileRotate; -use serde_json::json; +use serde_json::{json, Value}; use tokio::net::TcpListener; use oura::sources::Config::Hydra; use oura::daemon::{run_daemon, ConfigRoot}; @@ -471,6 +473,74 @@ fn hydra_oura_stdout_scenario_2() -> TestResult { hydra_oura_stdout_test(scenario, "golden_2".to_string()) } +#[test] +fn hydra_restore_from_intersection_success() { + let scenario= fs::read_to_string("tests/hydra/scenario_1.txt").unwrap(); + let intersect = IntersectConfig::Point( + 6, + "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab".to_string() + ); + let events = events(scenario, intersect); + + assert_ne!(events.len(), 0); + assert_eq!(events[0].point, json!({"slot": 7, "hash": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab"})); + for e in events { + if e.point == json!({"slot": 6, "hash": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab"}) { + panic!("only events /after/ the intersection should be emitted"); + } + } +} + +#[test] +fn hydra_restore_from_intersection_failure() { + let scenario= fs::read_to_string("tests/hydra/scenario_1.txt").unwrap(); + let bad_intersect= IntersectConfig::Point( + 6, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff".to_string() + ); + let events = events(scenario, bad_intersect); + assert_eq!(events, vec![]); +} + + +/// Wraps the json format of oura::framework::ChainEvent::Apply with just enough +/// structure to test point equality without having to implement the full json +/// deserializers. +#[derive(Debug, Deserialize, PartialEq)] +struct JsonApplyChainEvent { + point: Value, + record: Value, +} + +fn events(scenario: String, intersect: IntersectConfig) -> Vec { + let rt = Runtime::new().unwrap(); + rt.block_on(async move { + let port: u16 = random_free_port().unwrap(); + let addr = format!("127.0.0.1:{}", port); + let server = TcpListener::bind(&addr).await?; + let output_file = NamedTempFile::new()?; + let mut config = test_config(&output_file, &addr); + config.intersect = intersect; + + println!("WebSocket server starting on ws://{}", addr); + + let _ = tokio::spawn(async move { run_oura(config) }); + let _ = mock_hydra_node(server, scenario).await; + + // After the connection is established, give oura time to process + // the chain data and write the output to disk. + time::sleep(Duration::from_secs(3)).await; + + let emitted_jsons: Vec = fs::read_to_string(&output_file)? + .lines() + .map(|line| serde_json::from_str(line).expect("Invalid JSON line")) + .collect(); + + Ok::, anyhow::Error>(emitted_jsons) + }) + .unwrap() +} + // Run: // cargo test hydra_oura -- --nocapture // in order to see println From a9ac87c259c34238f3b762552e18d16479ad0e24 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Wed, 13 Nov 2024 22:14:35 +0100 Subject: [PATCH 42/53] Factor out `oura_output_from_mock_chain` --- tests/hydra.rs | 64 +++++++++++++++++--------------------------------- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index 038d095d..a8de418e 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -462,14 +462,14 @@ fn scenario_2() -> TestResult { } #[test] -fn hydra_oura_stdout_scenario_1() -> TestResult { - let scenario = fs::read_to_string("tests/hydra/scenario_1.txt")?; +fn hydra_oura_stdout_scenario_1() { + let scenario = fs::read_to_string("tests/hydra/scenario_1.txt").unwrap(); hydra_oura_stdout_test(scenario, "golden_1".to_string()) } #[test] -fn hydra_oura_stdout_scenario_2() -> TestResult { - let scenario = fs::read_to_string("tests/hydra/scenario_2.txt")?; +fn hydra_oura_stdout_scenario_2() { + let scenario = fs::read_to_string("tests/hydra/scenario_2.txt").unwrap(); hydra_oura_stdout_test(scenario, "golden_2".to_string()) } @@ -480,7 +480,7 @@ fn hydra_restore_from_intersection_success() { 6, "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab".to_string() ); - let events = events(scenario, intersect); + let events = oura_events_from_mock_chain(scenario, intersect); assert_ne!(events.len(), 0); assert_eq!(events[0].point, json!({"slot": 7, "hash": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab"})); @@ -490,7 +490,6 @@ fn hydra_restore_from_intersection_success() { } } } - #[test] fn hydra_restore_from_intersection_failure() { let scenario= fs::read_to_string("tests/hydra/scenario_1.txt").unwrap(); @@ -498,11 +497,10 @@ fn hydra_restore_from_intersection_failure() { 6, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff".to_string() ); - let events = events(scenario, bad_intersect); + let events = oura_events_from_mock_chain(scenario, bad_intersect); assert_eq!(events, vec![]); } - /// Wraps the json format of oura::framework::ChainEvent::Apply with just enough /// structure to test point equality without having to implement the full json /// deserializers. @@ -512,13 +510,13 @@ struct JsonApplyChainEvent { record: Value, } -fn events(scenario: String, intersect: IntersectConfig) -> Vec { +fn oura_output_from_mock_chain(scenario: String, intersect: IntersectConfig) -> String { let rt = Runtime::new().unwrap(); rt.block_on(async move { let port: u16 = random_free_port().unwrap(); let addr = format!("127.0.0.1:{}", port); - let server = TcpListener::bind(&addr).await?; - let output_file = NamedTempFile::new()?; + let server = TcpListener::bind(&addr).await.unwrap(); + let output_file = NamedTempFile::new().unwrap(); let mut config = test_config(&output_file, &addr); config.intersect = intersect; @@ -528,49 +526,29 @@ fn events(scenario: String, intersect: IntersectConfig) -> Vec = fs::read_to_string(&output_file)? - .lines() - .map(|line| serde_json::from_str(line).expect("Invalid JSON line")) - .collect(); - - Ok::, anyhow::Error>(emitted_jsons) + fs::read_to_string(&output_file).unwrap() }) - .unwrap() +} + +fn oura_events_from_mock_chain(scenario: String, intersect: IntersectConfig) -> Vec { + oura_output_from_mock_chain(scenario, intersect) + .lines() + .map(|line| serde_json::from_str(line).expect("Invalid JSON line")) + .collect() } // Run: // cargo test hydra_oura -- --nocapture // in order to see println -fn hydra_oura_stdout_test(mock_data: String, golden_name: String) -> TestResult { - +fn hydra_oura_stdout_test(mock_data: String, golden_name: String) { let mut mint = Mint::new("tests/hydra"); let mut golden = mint.new_goldenfile(golden_name.clone()).unwrap(); - let rt = Runtime::new().unwrap(); - let _ = rt.block_on(async move { - let port: u16 = random_free_port().unwrap(); - let addr= format!("127.0.0.1:{}", port); - let server = TcpListener::bind(&addr).await?; - let output_file = NamedTempFile::new()?; - let config = test_config(&output_file, &addr); - - println!("WebSocket server starting on ws://{}", addr); - - let _ = tokio::spawn(async move { run_oura(config) }); - let _ = mock_hydra_node(server, mock_data).await; + let output = oura_output_from_mock_chain(mock_data, IntersectConfig::Origin); - // After the connection is established, give oura time to process - // the chain data and write the output to disk. - time::sleep(Duration::from_secs(3)).await; - let emitted_jsons= fs::read_to_string(output_file)?; - golden.write_all(emitted_jsons.as_bytes()).unwrap(); - println!("test done, will exit"); - Ok::<(), std::io::Error>(()) - }); - Ok(()) + golden.write_all(output.as_bytes()).unwrap(); } /// Will await the first connection, and then return while handling it in the From d1ddde31882ae76ee05c2e30e499a7e0eca0933d Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Wed, 13 Nov 2024 22:29:54 +0100 Subject: [PATCH 43/53] Move `read_to_string` inside `hydra_stdout_test` again --- tests/hydra.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index a8de418e..0b54a2d4 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -463,14 +463,12 @@ fn scenario_2() -> TestResult { #[test] fn hydra_oura_stdout_scenario_1() { - let scenario = fs::read_to_string("tests/hydra/scenario_1.txt").unwrap(); - hydra_oura_stdout_test(scenario, "golden_1".to_string()) + hydra_oura_stdout_test("scenario_1.txt".to_string(), "golden_1".to_string()) } #[test] fn hydra_oura_stdout_scenario_2() { - let scenario = fs::read_to_string("tests/hydra/scenario_2.txt").unwrap(); - hydra_oura_stdout_test(scenario, "golden_2".to_string()) + hydra_oura_stdout_test("scenario_2.txt".to_string(), "golden_2".to_string()) } #[test] @@ -542,11 +540,12 @@ fn oura_events_from_mock_chain(scenario: String, intersect: IntersectConfig) -> // Run: // cargo test hydra_oura -- --nocapture // in order to see println -fn hydra_oura_stdout_test(mock_data: String, golden_name: String) { +fn hydra_oura_stdout_test(scenario_name: String, golden_name: String) { let mut mint = Mint::new("tests/hydra"); let mut golden = mint.new_goldenfile(golden_name.clone()).unwrap(); - let output = oura_output_from_mock_chain(mock_data, IntersectConfig::Origin); + let scenario = fs::read_to_string(format!("tests/hydra/{}", scenario_name)).unwrap(); + let output = oura_output_from_mock_chain(scenario, IntersectConfig::Origin); golden.write_all(output.as_bytes()).unwrap(); } From 3633457a69798c1092647b4686c1ec56b3b58906 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Thu, 14 Nov 2024 13:58:00 +0100 Subject: [PATCH 44/53] Refactor `should_process` into a wrapping `process` --- src/sources/hydra.rs | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index a6287195..fb526163 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -152,36 +152,33 @@ pub enum WorkerIntersect { ProcessMessages, } -impl WorkerIntersect { - /// When passed the point of the next hydra message, this function will return whether or not - /// that message should be processed. The `WorkerIntersect` will be mutated to reflect the - /// state where the next message has been processed. - fn should_process(&mut self, next: Point) -> bool { - match self { +impl Worker { + async fn process(&mut self, stage: &mut Stage, msg: HydraMessage) -> Result<(), WorkerError> { + let point = msg.pseudo_point(); + match &self.intersect { WorkerIntersect::SkipUntil(slot, hash) => { - let p = Point::Specific(slot.clone(), hash.clone()); + let target = Point::Specific(slot.clone(), hash.clone()); debug!( "Skipping message {} before or at intersection {}", - next.slot_or_default(), p.slot_or_default() + point.slot_or_default(), target.slot_or_default() ); - if p == next { - *self = WorkerIntersect::ProcessMessages; - } else if next.slot_or_default() >= p.slot_or_default() { + + if target == point { + self.intersect = WorkerIntersect::ProcessMessages; + } else if point.slot_or_default() >= target.slot_or_default() { warn!( "Skipping message from wrong hydra chain (intersection point hash mismatch) {:?} {:?}", - p, next - + target, point ); } - false + Ok(()) } - WorkerIntersect::ProcessMessages => true, + WorkerIntersect::ProcessMessages => self.process_message(stage, msg).await, } } -} -impl Worker { - async fn process_next( + /// Helper only to be called by `process` + async fn process_message( &mut self, stage: &mut Stage, next: HydraMessage, @@ -260,11 +257,7 @@ impl gasket::framework::Worker for Worker { debug!("Hydra message: {}", text); match serde_json::from_str::(text) { Ok(hydra_message) => { - if self.intersect.should_process(hydra_message.pseudo_point()) { - self.process_next(stage, hydra_message).await - } else { - Ok(()) - } + self.process(stage, hydra_message).await } Err(err) => { error!("Failed to parse Hydra message: {}", err); From 414f9183fb2a4db336f554095f0d2905e31bf1a7 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Thu, 14 Nov 2024 16:34:16 +0100 Subject: [PATCH 45/53] Minor style changes --- src/sources/hydra.rs | 3 ++- tests/hydra.rs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index fb526163..b99f567e 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -145,8 +145,9 @@ pub struct Worker { socket: HydraConnection, intersect: WorkerIntersect, } -#[derive(Debug, Clone)] + /// Worker state for finding the right intersection point +#[derive(Debug, Clone)] pub enum WorkerIntersect { SkipUntil(u64, Vec), // Possibility of Point::Origin is excluded ProcessMessages, diff --git a/tests/hydra.rs b/tests/hydra.rs index 0b54a2d4..3900b968 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -1,10 +1,10 @@ -use serde::Deserialize; -use oura::framework::IntersectConfig; use std::fs; use std::path::PathBuf; use std::sync::mpsc; use std::time::Duration; +use serde::Deserialize; +use oura::framework::IntersectConfig; use anyhow::Result; use futures_util::SinkExt; use oura::sources::hydra::{HydraMessage, HydraMessagePayload}; From 3340f8aacd362522f6cf7503369977f44bb15ddc Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Mon, 18 Nov 2024 12:19:06 +0100 Subject: [PATCH 46/53] Add additional intersection tests --- tests/hydra.rs | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/tests/hydra.rs b/tests/hydra.rs index 3900b968..5f07b22f 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -488,9 +488,44 @@ fn hydra_restore_from_intersection_success() { } } } + +#[test] +fn hydra_restore_from_intersection_tip() { + let scenario = fs::read_to_string("tests/hydra/scenario_1.txt").unwrap(); + let intersect = IntersectConfig::Point( + 11, + "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab".to_string() + ); + let events = oura_events_from_mock_chain(scenario, intersect); + assert_eq!(events, vec![]); +} + +#[test] +fn hydra_restore_from_intersection_point_with_dummy_hash_and_shared_slot_1() { + let scenario = fs::read_to_string("tests/hydra/scenario_1.txt").unwrap(); + let intersect = IntersectConfig::Point( + 2, + "0000000000000000000000000000000000000000000000000000000000000000".to_string() + ); + let events = oura_events_from_mock_chain(scenario, intersect); + // It appears the Greetings and HeadIsInitializing messages share the same seq / slot. + assert_eq!(events[0].point, json!({"slot": 2, "hash": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab"})) +} + +#[test] +fn hydra_restore_from_intersection_point_with_shared_slot_2() { + let scenario = fs::read_to_string("tests/hydra/scenario_1.txt").unwrap(); + let intersect = IntersectConfig::Point( + 2, + "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab".to_string() + ); + let events = oura_events_from_mock_chain(scenario, intersect); + assert_eq!(events[0].point, json!({"slot": 3, "hash": "84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab"})) +} + #[test] fn hydra_restore_from_intersection_failure() { - let scenario= fs::read_to_string("tests/hydra/scenario_1.txt").unwrap(); + let scenario = fs::read_to_string("tests/hydra/scenario_1.txt").unwrap(); let bad_intersect= IntersectConfig::Point( 6, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff".to_string() From dd047a4787f55484d0db5bf77188c20a33dc2492 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Mon, 18 Nov 2024 12:46:18 +0100 Subject: [PATCH 47/53] Add parenthesis to clarify debug log message --- src/sources/hydra.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index b99f567e..1c565d6c 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -160,7 +160,7 @@ impl Worker { WorkerIntersect::SkipUntil(slot, hash) => { let target = Point::Specific(slot.clone(), hash.clone()); debug!( - "Skipping message {} before or at intersection {}", + "Skipping message {} before (or at) requested intersection {}", point.slot_or_default(), target.slot_or_default() ); From e2466afe5449bf65e9cbb3893d4bf113cce5b2fe Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Thu, 14 Nov 2024 17:01:03 +0100 Subject: [PATCH 48/53] Drop unused hydra `rollback_count` --- src/sources/hydra.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 1c565d6c..0faedb13 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -136,9 +136,6 @@ pub struct Stage { #[metric] current_slot: gasket::metrics::Gauge, - - #[metric] - rollback_count: gasket::metrics::Counter, } pub struct Worker { @@ -285,7 +282,6 @@ impl Config { ops_count: Default::default(), chain_tip: Default::default(), current_slot: Default::default(), - rollback_count: Default::default(), }; Ok(stage) From de834ace09bab64ff5e7c742fc5bc29c954e0068 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Thu, 14 Nov 2024 17:01:56 +0100 Subject: [PATCH 49/53] Drop hydra `chain_tip` with questionable implementation We can't know of the chain tip before we actually reach it when processing. --- src/sources/hydra.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 0faedb13..7cf4f1b0 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -131,9 +131,6 @@ pub struct Stage { #[metric] ops_count: gasket::metrics::Counter, - #[metric] - chain_tip: gasket::metrics::Gauge, - #[metric] current_slot: gasket::metrics::Gauge, } @@ -195,7 +192,6 @@ impl Worker { stage.output.send(evt.into()).await.or_panic()?; stage.ops_count.inc(1); - stage.chain_tip.set(point.slot_or_default() as i64); stage.current_slot.set(point.slot_or_default() as i64); stage.ops_count.inc(1); } @@ -280,7 +276,6 @@ impl Config { intersect: ctx.intersect.clone(), output: Default::default(), ops_count: Default::default(), - chain_tip: Default::default(), current_slot: Default::default(), }; From ad53357f0d08dad92aa0a2237e1cabb111b053a4 Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Mon, 18 Nov 2024 14:55:35 +0100 Subject: [PATCH 50/53] Correct dummy hash length from 32 to 28 bytes --- src/sources/hydra.rs | 2 +- tests/hydra.rs | 2 +- tests/hydra/golden_1 | 6 +++--- tests/hydra/golden_2 | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 7cf4f1b0..4fdd2996 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -26,7 +26,7 @@ pub struct HydraMessage { impl HydraMessage { fn head_id_or_default(&self) -> Vec { - let dummy_hash = vec![0u8; 32]; + let dummy_hash = vec![0u8; 28]; self.head_id.clone().unwrap_or(dummy_hash) } diff --git a/tests/hydra.rs b/tests/hydra.rs index 5f07b22f..5c272935 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -505,7 +505,7 @@ fn hydra_restore_from_intersection_point_with_dummy_hash_and_shared_slot_1() { let scenario = fs::read_to_string("tests/hydra/scenario_1.txt").unwrap(); let intersect = IntersectConfig::Point( 2, - "0000000000000000000000000000000000000000000000000000000000000000".to_string() + "00000000000000000000000000000000000000000000000000000000".to_string() ); let events = oura_events_from_mock_chain(scenario, intersect); // It appears the Greetings and HeadIsInitializing messages share the same seq / slot. diff --git a/tests/hydra/golden_1 b/tests/hydra/golden_1 index c7fe2453..91a4c334 100644 --- a/tests/hydra/golden_1 +++ b/tests/hydra/golden_1 @@ -1,6 +1,6 @@ -{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":0},"record":{"peer":"3","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.556003751Z"}} -{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":1},"record":{"peer":"2","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.559653645Z"}} -{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":2},"record":{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:04:56.445761285Z"}} +{"event":"apply","point":{"hash":"00000000000000000000000000000000000000000000000000000000","slot":0},"record":{"peer":"3","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.556003751Z"}} +{"event":"apply","point":{"hash":"00000000000000000000000000000000000000000000000000000000","slot":1},"record":{"peer":"2","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:01:20.559653645Z"}} +{"event":"apply","point":{"hash":"00000000000000000000000000000000000000000000000000000000","slot":2},"record":{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:04:56.445761285Z"}} {"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":2},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","parties":[{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"}],"seq":2,"tag":"HeadIsInitializing","timestamp":"2024-10-08T13:05:47.330461177Z"}} {"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":3},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":3,"tag":"Committed","timestamp":"2024-10-08T13:05:56.918549005Z","utxo":{"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}}}} {"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":4},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},"seq":4,"tag":"Committed","timestamp":"2024-10-08T13:06:05.615623261Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}}}}} diff --git a/tests/hydra/golden_2 b/tests/hydra/golden_2 index e0eff470..5895f165 100644 --- a/tests/hydra/golden_2 +++ b/tests/hydra/golden_2 @@ -1,6 +1,6 @@ -{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":0},"record":{"peer":"2","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.954897681Z"}} -{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":1},"record":{"peer":"3","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.98647342Z"}} -{"event":"apply","point":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","slot":2},"record":{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:21:28.141876427Z"}} +{"event":"apply","point":{"hash":"00000000000000000000000000000000000000000000000000000000","slot":0},"record":{"peer":"2","seq":0,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.954897681Z"}} +{"event":"apply","point":{"hash":"00000000000000000000000000000000000000000000000000000000","slot":1},"record":{"peer":"3","seq":1,"tag":"PeerConnected","timestamp":"2024-10-08T13:19:06.98647342Z"}} +{"event":"apply","point":{"hash":"00000000000000000000000000000000000000000000000000000000","slot":2},"record":{"headStatus":"Idle","hydraNodeVersion":"0.19.0-1ffe7c6b505e3f38b5546ae5e5b97de26bc70425","me":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":2,"tag":"Greetings","timestamp":"2024-10-08T13:21:28.141876427Z"}} {"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":2},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","parties":[{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},{"vkey":"7abcda7de6d883e7570118c1ccc8ee2e911f2e628a41ab0685ffee15f39bba96"}],"seq":2,"tag":"HeadIsInitializing","timestamp":"2024-10-08T13:22:05.725778923Z"}} {"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":3},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"b37aabd81024c043f53a069c91e51a5b52e4ea399ae17ee1fe3cb9c44db707eb"},"seq":3,"tag":"Committed","timestamp":"2024-10-08T13:22:11.016254447Z","utxo":{"c9a5fb7ca6f55f07facefccb7c5d824eed00ce18719d28ec4c4a2e4041e85d97#0":{"address":"addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":100000000}}}}} {"event":"apply","point":{"hash":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","slot":4},"record":{"headId":"84e657e3dd5241caac75b749195f78684023583736cc08b2896290ab","party":{"vkey":"f68e5624f885d521d2f43c3959a0de70496d5464bd3171aba8248f50d5d72b41"},"seq":4,"tag":"Committed","timestamp":"2024-10-08T13:22:18.915120931Z","utxo":{"7b27f432e04984dc21ee61e8b1539775cd72cc8669f72cf39aebf6d87e35c697#0":{"address":"addr_test1vp0yug22dtwaxdcjdvaxr74dthlpunc57cm639578gz7algset3fh","datum":null,"datumhash":null,"inlineDatum":null,"referenceScript":null,"value":{"lovelace":50000000}}}}} From 5f6950bbe89bd54a4d1dccbde2756ab4b790edcf Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Mon, 18 Nov 2024 16:36:10 +0100 Subject: [PATCH 51/53] Drop unneeded addition to .gitignore --- examples/.gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/.gitignore b/examples/.gitignore index 30e06623..162ee335 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,2 +1 @@ -scratchpad -tests/hydra/logs.txt \ No newline at end of file +scratchpad \ No newline at end of file From f5b87dcef09821977bd6dd30c0ffae3dbd7636ac Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Mon, 18 Nov 2024 16:36:31 +0100 Subject: [PATCH 52/53] Rename `hydra_socket_url` -> `hydra_socket_path` --- examples/hydra/daemon.toml | 2 +- src/sources/hydra.rs | 4 ++-- tests/daemon.toml | 2 +- tests/hydra.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/hydra/daemon.toml b/examples/hydra/daemon.toml index f58b38bd..e860fa89 100644 --- a/examples/hydra/daemon.toml +++ b/examples/hydra/daemon.toml @@ -1,6 +1,6 @@ [source] type = "Hydra" -hydra_socket_url = "ws://127.0.0.1:4001" +hydra_socket_path = "ws://127.0.0.1:4001" magic = 42 [intersect] diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 4fdd2996..2a7bf9be 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -226,7 +226,7 @@ impl gasket::framework::Worker for Worker { async fn bootstrap(stage: &Stage) -> Result { debug!("connecting to hydra WebSocket"); - let url = &stage.config.hydra_socket_url; + let url = &stage.config.hydra_socket_path; let (socket, _) = connect_async(url).await.expect("Can't connect"); let worker = Self { socket, @@ -266,7 +266,7 @@ impl gasket::framework::Worker for Worker { #[derive(Deserialize)] pub struct Config { - pub hydra_socket_url: String, + pub hydra_socket_path: String, } impl Config { diff --git a/tests/daemon.toml b/tests/daemon.toml index bbf93f1b..97706a13 100644 --- a/tests/daemon.toml +++ b/tests/daemon.toml @@ -1,6 +1,6 @@ [source] type = "Hydra" -hydra_socket_url = "ws://127.0.0.1:4001" +hydra_socket_path = "ws://127.0.0.1:4001" magic = 42 [intersect] diff --git a/tests/hydra.rs b/tests/hydra.rs index 5c272935..764da318 100644 --- a/tests/hydra.rs +++ b/tests/hydra.rs @@ -621,7 +621,7 @@ fn test_config(tmp_output_file: &NamedTempFile, socket_path: &String) -> ConfigR } if let Hydra(ref mut hydra_config) = config.source { - hydra_config.hydra_socket_url = "ws://".to_string() + socket_path; + hydra_config.hydra_socket_path = "ws://".to_string() + socket_path; } else { panic!("assumed config template to use hydra source"); } From 371ed765cb35e11944392e1e5de477cea85bd76f Mon Sep 17 00:00:00 2001 From: Johannes Lund Date: Mon, 18 Nov 2024 16:37:10 +0100 Subject: [PATCH 53/53] Drop unused `Snapshot` struct --- src/sources/hydra.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/sources/hydra.rs b/src/sources/hydra.rs index 2a7bf9be..e9753377 100644 --- a/src/sources/hydra.rs +++ b/src/sources/hydra.rs @@ -112,11 +112,6 @@ where Ok(cbor) } -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct Snapshot { - number: u64, - confirmed_transaction_ids: Vec, -} type HydraConnection = WebSocketStream>; #[derive(Stage)]