From 4c86e0b6cff7dec3e891afb7a70d7ca5fe882812 Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Mon, 13 Jun 2022 17:40:07 -0300 Subject: [PATCH 1/4] (WIP) feat: Use pallas traverse library --- Cargo.lock | 69 +++++++++++++--- Cargo.toml | 5 +- src/crosscut/mod.rs | 2 +- src/enrich/mod.rs | 44 ++++++++++ src/enrich/sled.rs | 117 +++++++++++++++++++++++++++ src/lib.rs | 8 ++ src/model.rs | 72 ++--------------- src/reducers/balance_by_address.temp | 108 +++++++++++++++++++++++++ src/reducers/point_by_tx.rs | 33 ++------ src/reducers/pool_by_stake.rs | 24 +++--- src/reducers/utxo_by_address.rs | 63 ++++----------- src/storage/mod.rs | 4 +- src/storage/redis.rs | 8 +- 13 files changed, 384 insertions(+), 173 deletions(-) create mode 100644 src/enrich/mod.rs create mode 100644 src/enrich/sled.rs create mode 100644 src/reducers/balance_by_address.temp diff --git a/Cargo.lock b/Cargo.lock index eda84987..cbc1f57c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -132,6 +132,15 @@ dependencies = [ "toml", ] +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "crossbeam" version = "0.8.1" @@ -273,6 +282,25 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "gasket" version = "0.1.0" @@ -567,21 +595,18 @@ dependencies = [ [[package]] name = "pallas" version = "0.11.0-alpha.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8821516a5f4e5fffe404363d2b5dca5790b75beeb817aa7268e7c17108cea96" dependencies = [ "pallas-codec", "pallas-crypto", "pallas-miniprotocols", "pallas-multiplexer", "pallas-primitives", + "pallas-traverse", ] [[package]] name = "pallas-codec" version = "0.11.0-alpha.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871883de93ab0c9d5ae158eab015a23ed37ec5959bfac5a1880fec384035f6f9" dependencies = [ "minicbor 0.17.1", ] @@ -589,8 +614,6 @@ dependencies = [ [[package]] name = "pallas-crypto" version = "0.11.0-alpha.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4f0a2c1d09049da3ea92f4aca7455dc139a08d737093205054c1b823795215" dependencies = [ "cryptoxide", "hex", @@ -602,8 +625,6 @@ dependencies = [ [[package]] name = "pallas-miniprotocols" version = "0.11.0-alpha.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d173f767dcb3ed5f768121842fdfd845189526d86f048bdf0fcbfe8b887e6913" dependencies = [ "hex", "itertools", @@ -616,8 +637,6 @@ dependencies = [ [[package]] name = "pallas-multiplexer" version = "0.11.0-alpha.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b8cc8839fb441a8741cbca1a68d0f260ef5ce40b80b26beb2e1ed9f3d7d498" dependencies = [ "byteorder", "hex", @@ -630,8 +649,6 @@ dependencies = [ [[package]] name = "pallas-primitives" version = "0.11.0-alpha.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cae85c601244903dc90c5aec9602f771e87b7fa4903d8dc7736c6b4d9285811" dependencies = [ "base58", "bech32", @@ -643,6 +660,17 @@ dependencies = [ "serde_json", ] +[[package]] +name = "pallas-traverse" +version = "0.11.0-alpha.0" +dependencies = [ + "hex", + "pallas-codec", + "pallas-crypto", + "pallas-primitives", + "thiserror", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -880,6 +908,7 @@ dependencies = [ "redis", "serde", "serde_json", + "sled", "thiserror", ] @@ -959,6 +988,22 @@ dependencies = [ "libc", ] +[[package]] +name = "sled" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot 0.11.2", +] + [[package]] name = "smallvec" version = "1.8.0" diff --git a/Cargo.toml b/Cargo.toml index dc672d3a..f9f5bf4c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,8 @@ authors = ["Santiago Carmuega "] [dependencies] -pallas = "0.11.0-alpha.0" -# pallas = { path = "../pallas/pallas" } +# pallas = "0.11.0-alpha.0" +pallas = { path = "../pallas/pallas" } hex = "0.4.3" net2 = "0.2.37" bech32 = "0.8.1" @@ -31,6 +31,7 @@ prometheus_exporter = { version = "0.8.4", default-features = false } gasket = { git = "https://github.com/construkts/gasket-rs.git" } thiserror = "1.0.30" redis = "0.21.5" +sled = "0.34.7" [features] unstable = [] diff --git a/src/crosscut/mod.rs b/src/crosscut/mod.rs index 1189eb6d..b4641886 100644 --- a/src/crosscut/mod.rs +++ b/src/crosscut/mod.rs @@ -2,4 +2,4 @@ mod args; mod epoch_calculator; pub use args::*; -pub use epoch_calculator::*; \ No newline at end of file +pub use epoch_calculator::*; diff --git a/src/enrich/mod.rs b/src/enrich/mod.rs new file mode 100644 index 00000000..b56d24b4 --- /dev/null +++ b/src/enrich/mod.rs @@ -0,0 +1,44 @@ +pub mod sled; + +use gasket::messaging::{InputPort, OutputPort}; +use serde::Deserialize; + +use crate::{bootstrap, crosscut, model}; + +#[derive(Deserialize)] +#[serde(tag = "type")] +pub enum Config { + Sled(sled::Config), +} + +impl Config { + pub fn Bootstrapper(self) -> Bootstrapper { + match self { + Config::Sled(c) => Bootstrapper::Sled(c.boostrapper()), + } + } +} + +pub enum Bootstrapper { + Sled(sled::Bootstrapper), +} + +impl Bootstrapper { + pub fn borrow_input_port(&mut self) -> &'_ mut InputPort { + match self { + Bootstrapper::Sled(x) => x.borrow_input_port(), + } + } + + pub fn borrow_output_port(&mut self) -> &'_ mut OutputPort { + match self { + Bootstrapper::Sled(x) => x.borrow_output_port(), + } + } + + pub fn spawn_stages(self, pipeline: &mut bootstrap::Pipeline) { + match self { + Bootstrapper::Sled(x) => x.spawn_stages(pipeline), + } + } +} diff --git a/src/enrich/sled.rs b/src/enrich/sled.rs new file mode 100644 index 00000000..e644565f --- /dev/null +++ b/src/enrich/sled.rs @@ -0,0 +1,117 @@ +use gasket::{ + error::AsWorkError, + runtime::{spawn_stage, WorkOutcome}, +}; + +use pallas::ledger::traverse::MultiEraBlock; +use serde::Deserialize; + +use crate::{bootstrap, model}; + +type InputPort = gasket::messaging::InputPort; +type OutputPort = gasket::messaging::OutputPort; + +#[derive(Deserialize, Clone)] +pub struct Config { + pub db_path: String, +} + +impl Config { + pub fn boostrapper(self) -> Bootstrapper { + Bootstrapper { + config: self, + input: Default::default(), + output: Default::default(), + } + } +} + +pub struct Bootstrapper { + config: Config, + input: InputPort, + output: OutputPort, +} + +impl Bootstrapper { + pub fn borrow_input_port(&mut self) -> &'_ mut InputPort { + &mut self.input + } + + pub fn borrow_output_port(&mut self) -> &'_ mut OutputPort { + &mut self.output + } + + pub fn spawn_stages(self, pipeline: &mut bootstrap::Pipeline) { + let worker = Worker { + config: self.config.clone(), + db: None, + input: self.input, + output: self.output, + }; + + pipeline.register_stage("enrich-sled", spawn_stage(worker, Default::default())); + } +} + +pub struct Worker { + config: Config, + db: Option, + input: InputPort, + output: OutputPort, +} + +impl Worker { + fn track_block_txs(&self, cbor: &[u8]) -> Result<(), crate::Error> { + let block = MultiEraBlock::decode(cbor).map_err(crate::Error::cbor)?; + + for tx in block.tx_iter() { + let hash = tx.hash(); + + let cbor = tx.encode().map_err(crate::Error::cbor)?; + + self.db + .unwrap() + .insert(hash, cbor) + .map_err(crate::Error::storage)?; + } + + Ok(()) + } +} + +impl gasket::runtime::Worker for Worker { + fn metrics(&self) -> gasket::metrics::Registry { + gasket::metrics::Builder::new().build() + } + + fn work(&mut self) -> gasket::runtime::WorkResult { + let msg = self.input.recv()?; + + match &msg.payload { + model::ChainSyncCommandEx::RollForward(cbor) => { + self.track_block_txs(cbor).or_work_err()?; + self.output.send(msg) + } + model::ChainSyncCommandEx::RollBack(_) => self.output.send(msg), + }; + + Ok(WorkOutcome::Partial) + } + + fn bootstrap(&mut self) -> Result<(), gasket::error::Error> { + let db = sled::open(self.config.db_path).or_work_err()?; + self.db = Some(db); + + Ok(()) + } + + fn teardown(&mut self) -> Result<(), gasket::error::Error> { + match self.db { + Some(db) => { + db.flush().or_work_err()?; + Ok(()) + } + None => Ok(()), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 6429153a..2becc5fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ pub mod bootstrap; pub mod crosscut; +pub mod enrich; pub mod model; pub mod reducers; pub mod sources; @@ -20,6 +21,9 @@ pub enum Error { #[error("ouroboros error: {0}")] OuroborosError(String), + #[error("cbor error: {0}")] + CborError(String), + #[error("ledger error: {0}")] LedgerError(String), @@ -49,6 +53,10 @@ impl Error { Error::NetworkError(format!("network error: {}", error)) } + pub fn cbor(error: impl Display) -> Error { + Error::CborError(format!("cbor error: {}", error)) + } + pub fn ouroboros(error: impl Display) -> Error { Error::OuroborosError(format!("ouroboros error: {}", error)) } diff --git a/src/model.rs b/src/model.rs index 37430ed8..745383e9 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1,9 +1,6 @@ -use std::{collections::HashSet, ops::Deref}; +use std::collections::HashSet; -use pallas::{ - ledger::primitives::{alonzo, byron, probing, Era, Fragment, ToHash}, - network::miniprotocols::Point, -}; +use pallas::{ledger::traverse::MultiEraBlock, network::miniprotocols::Point}; use crate::Error; @@ -47,63 +44,6 @@ impl ChainSyncCommandEx { } } -#[derive(Debug)] -pub enum MultiEraBlock<'b> { - AlonzoCompatible(alonzo::BlockWrapper<'b>), - Byron(byron::Block), -} - -pub fn parse_block_content(body: &[u8]) -> Result { - match probing::probe_block_cbor_era(&body) { - probing::Outcome::Matched(era) => match era { - Era::Byron => { - let primitive = byron::Block::decode_fragment(&body)?; - let block = MultiEraBlock::Byron(primitive); - Ok(block) - } - _ => { - let primitive = alonzo::BlockWrapper::decode_fragment(&body)?; - let block = MultiEraBlock::AlonzoCompatible(primitive); - Ok(block) - } - }, - // TODO: we're assuming that the genesis block is Byron-compatible. Is this a safe - // assumption? - probing::Outcome::GenesisBlock => { - let primitive = byron::Block::decode_fragment(&body)?; - let block = MultiEraBlock::Byron(primitive); - Ok(block) - } - probing::Outcome::Inconclusive => { - let msg = format!("can't infer primitive block from cbor, inconclusive probing. CBOR hex for debugging: {}", hex::encode(body)); - return Err(Error::Message(msg)); - } - } -} - -impl<'b> MultiEraBlock<'b> { - pub fn point(&self) -> Result { - match self { - MultiEraBlock::Byron(x) => match x.deref() { - byron::Block::EbBlock(x) => { - let hash = x.header.to_hash(); - let slot = x.header.to_abs_slot(); - Ok(Point::Specific(slot, hash.to_vec())) - } - byron::Block::MainBlock(x) => { - let hash = x.header.to_hash(); - let slot = x.header.consensus_data.0.to_abs_slot(); - Ok(Point::Specific(slot, hash.to_vec())) - } - }, - MultiEraBlock::AlonzoCompatible(x) => { - let hash = &x.1.header.to_hash(); - Ok(Point::Specific(x.1.header.header_body.slot, hash.to_vec())) - } - } - } -} - pub type Set = String; pub type Member = String; pub type Key = String; @@ -127,12 +67,16 @@ pub enum CRDTCommand { impl CRDTCommand { pub fn block_starting(block: &MultiEraBlock) -> CRDTCommand { - let point = block.point().expect("block has defined point"); + let hash = block.hash(); + let slot = block.slot(); + let point = Point::Specific(slot, hash.to_vec()); CRDTCommand::BlockStarting(point) } pub fn block_finished(block: &MultiEraBlock) -> CRDTCommand { - let point = block.point().expect("block has defined point"); + let hash = block.hash(); + let slot = block.slot(); + let point = Point::Specific(slot, hash.to_vec()); CRDTCommand::BlockFinished(point) } } diff --git a/src/reducers/balance_by_address.temp b/src/reducers/balance_by_address.temp new file mode 100644 index 00000000..cbcb1995 --- /dev/null +++ b/src/reducers/balance_by_address.temp @@ -0,0 +1,108 @@ +use gasket::error::AsWorkError; +use pallas::crypto::hash::Hash; +use pallas::ledger::primitives::{alonzo, byron}; +use serde::Deserialize; + +use crate::{crosscut, model, storage}; + +#[derive(Deserialize)] +pub struct Config { + pub key_prefix: Option, + pub filter: Option>, +} + +pub struct Reducer { + config: Config, + address_hrp: String, +} + +impl Reducer { + fn send_increment( + &mut self, + slot: u64, + address: &str, + value: i64, + output: &mut super::OutputPort, + ) -> Result<(), gasket::error::Error> { + let key = match &self.config.key_prefix { + Some(prefix) => format!("{}.{}", prefix, address), + None => format!("{}", address), + }; + + let crdt = model::CRDTCommand::LastWriteWins(key, address.to_string(), slot); + + output.send(gasket::messaging::Message::from(crdt))?; + + Ok(()) + } + + fn reduce_alonzo_compatible_tx( + &mut self, + slot: u64, + tx: &alonzo::TransactionBody, + state: &mut storage::ReadPlugin, + output: &mut super::OutputPort, + ) -> Result<(), gasket::error::Error> { + let tx_hash = tx.to_hash(); + + tx.iter() + .filter_map(|b| match b { + alonzo::TransactionBodyComponent::Outputs(o) => Some(o), + _ => None, + }) + .flat_map(|o| o.iter()) + .enumerate() + .map(move |(tx_idx, tx_output)| { + let address = tx_output + .to_bech32_address(&self.address_hrp) + .or_work_err()?; + self.send_increment(slot, &address, 1, output) + }) + .collect(); + + tx.iter() + .filter_map(|b| match b { + alonzo::TransactionBodyComponent::Inputs(i) => Some(i), + _ => None, + }) + .flat_map(|i| i.iter()) + .map(move |tx_input| { + let txo = format!("{}#{}", tx_input.transaction_id, tx_input.index); + let address = state.read_state(model::StateQuery::KeyValue(txo))?; + self.send_increment(slot, &address, -1, output) + }) + .collect(); + + Ok(()) + } + + pub fn reduce_block( + &mut self, + block: &model::MultiEraBlock, + state: &mut storage::ReadPlugin, + output: &mut super::OutputPort, + ) -> Result<(), gasket::error::Error> { + match block { + model::MultiEraBlock::AlonzoCompatible(x) => x + .1 + .transaction_bodies + .iter() + .map(|tx| { + self.reduce_alonzo_compatible_tx(x.1.header.header_body.slot, tx, state, output) + }) + .collect(), + _ => Ok(()), + } + } +} + +impl Config { + pub fn plugin(self, chain: &crosscut::ChainWellKnownInfo) -> super::Reducer { + let reducer = Reducer { + config: self, + address_hrp: chain.address_hrp.clone(), + }; + + super::Reducer::BalanceByAddress(reducer) + } +} diff --git a/src/reducers/point_by_tx.rs b/src/reducers/point_by_tx.rs index 8375cde4..2fa96944 100644 --- a/src/reducers/point_by_tx.rs +++ b/src/reducers/point_by_tx.rs @@ -1,5 +1,5 @@ use pallas::crypto::hash::Hash; -use pallas::ledger::primitives::{byron, ToHash}; +use pallas::ledger::traverse::MultiEraBlock; use serde::Deserialize; use crate::model; @@ -36,33 +36,16 @@ impl Reducer { pub fn reduce_block( &mut self, - block: &model::MultiEraBlock, + block: &MultiEraBlock, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - match block { - model::MultiEraBlock::Byron(byron::Block::MainBlock(x)) => { - let hash = x.header.to_hash(); - let slot = x.header.consensus_data.0.to_abs_slot(); + let block_hash = block.hash(); + let block_slot = block.slot(); - x.body - .tx_payload - .iter() - .map(|tx| tx.transaction.to_hash()) - .map(|tx| self.send_set_add(tx, slot, hash, output)) - .collect() - } - model::MultiEraBlock::Byron(_) => Ok(()), - model::MultiEraBlock::AlonzoCompatible(x) => { - let slot = x.1.header.header_body.slot; - let hash = x.1.header.header_body.block_body_hash; - - x.1.transaction_bodies - .iter() - .map(|tx| tx.to_hash()) - .map(|tx| self.send_set_add(tx, slot, hash, output)) - .collect() - } - } + block + .tx_iter() + .map(|tx| self.send_set_add(tx.hash(), block_slot, block_hash, output)) + .collect() } } diff --git a/src/reducers/pool_by_stake.rs b/src/reducers/pool_by_stake.rs index 226e077e..b11755ce 100644 --- a/src/reducers/pool_by_stake.rs +++ b/src/reducers/pool_by_stake.rs @@ -1,5 +1,6 @@ use pallas::ledger::primitives::alonzo; use pallas::ledger::primitives::alonzo::{PoolKeyhash, StakeCredential}; +use pallas::ledger::traverse::{MultiEraBlock, MultiEraTx}; use serde::Deserialize; use crate::model; @@ -40,10 +41,10 @@ impl Reducer { Ok(()) } - fn reduce_alonzo_compatible_tx( + fn reduce_tx( &mut self, slot: u64, - tx: &alonzo::TransactionBody, + tx: &MultiEraTx, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { tx.iter() @@ -62,20 +63,15 @@ impl Reducer { pub fn reduce_block( &mut self, - block: &model::MultiEraBlock, + block: &MultiEraBlock, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - match block { - model::MultiEraBlock::Byron(_) => Ok(()), - model::MultiEraBlock::AlonzoCompatible(block) => block - .1 - .transaction_bodies - .iter() - .map(|tx| { - self.reduce_alonzo_compatible_tx(block.1.header.header_body.slot, tx, output) - }) - .collect(), - } + let slot = block.slot(); + + block + .tx_iter() + .map(|tx| self.reduce_tx(slot, tx, output)) + .collect() } } diff --git a/src/reducers/utxo_by_address.rs b/src/reducers/utxo_by_address.rs index fcf235e0..e3b96c7e 100644 --- a/src/reducers/utxo_by_address.rs +++ b/src/reducers/utxo_by_address.rs @@ -1,6 +1,7 @@ use gasket::error::AsWorkError; use pallas::crypto::hash::Hash; use pallas::ledger::primitives::{alonzo, byron, ToHash}; +use pallas::ledger::traverse::{MultiEraBlock, MultiEraTx}; use serde::Deserialize; use crate::{crosscut, model}; @@ -21,7 +22,7 @@ impl Reducer { &mut self, address: &str, tx_hash: Hash<32>, - tx_idx: usize, + output_idx: usize, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { if let Some(addresses) = &self.config.filter { @@ -35,7 +36,7 @@ impl Reducer { None => address.to_string(), }; - let member = format!("{}:{}", tx_hash, tx_idx); + let member = format!("{}#{}", tx_hash, output_idx); let crdt = model::CRDTCommand::TwoPhaseSetAdd(key, member); output.send(gasket::messaging::Message::from(crdt))?; @@ -43,42 +44,17 @@ impl Reducer { Ok(()) } - fn reduce_byron_tx( + fn reduce_tx( &mut self, - tx: &byron::TxPayload, + tx: &MultiEraTx, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - let tx_hash = tx.transaction.to_hash(); + let tx_hash = tx.hash(); - tx.transaction - .outputs - .iter() + tx.output_iter() .enumerate() - .map(move |(tx_idx, tx)| { - let address = tx.address.to_addr_string().or_work_err()?; - self.send_set_add(&address, tx_hash, tx_idx, output) - }) - .collect() - } - - fn reduce_alonzo_compatible_tx( - &mut self, - tx: &alonzo::TransactionBody, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - let tx_hash = tx.to_hash(); - - tx.iter() - .filter_map(|b| match b { - alonzo::TransactionBodyComponent::Outputs(o) => Some(o), - _ => None, - }) - .flat_map(|o| o.iter()) - .enumerate() - .map(move |(tx_idx, tx_output)| { - let address = tx_output - .to_bech32_address(&self.address_hrp) - .or_work_err()?; + .map(|(tx_idx, tx_output)| { + let address = tx_output.address(&self.address_hrp); self.send_set_add(&address, tx_hash, tx_idx, output) }) .collect() @@ -86,24 +62,13 @@ impl Reducer { pub fn reduce_block( &mut self, - block: &model::MultiEraBlock, + block: &MultiEraBlock, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - match block { - model::MultiEraBlock::Byron(byron::Block::MainBlock(x)) => x - .body - .tx_payload - .iter() - .map(|tx| self.reduce_byron_tx(tx, output)) - .collect(), - model::MultiEraBlock::Byron(_) => Ok(()), - model::MultiEraBlock::AlonzoCompatible(x) => { - x.1.transaction_bodies - .iter() - .map(|tx| self.reduce_alonzo_compatible_tx(tx, output)) - .collect() - } - } + block + .tx_iter() + .map(|tx| self.reduce_tx(&tx, output)) + .collect() } } diff --git a/src/storage/mod.rs b/src/storage/mod.rs index 1eba9713..4e25d4dc 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -1,6 +1,6 @@ pub mod redis; -use gasket::messaging::FunnelPort; +use gasket::messaging::InputPort; use serde::Deserialize; use crate::{bootstrap, crosscut, model}; @@ -28,7 +28,7 @@ pub enum Bootstrapper { } impl Bootstrapper { - pub fn borrow_input_port(&mut self) -> &'_ mut FunnelPort { + pub fn borrow_input_port(&mut self) -> &'_ mut InputPort { match self { Bootstrapper::Redis(x) => x.borrow_input_port(), } diff --git a/src/storage/redis.rs b/src/storage/redis.rs index 635b4b3e..dc819ff7 100644 --- a/src/storage/redis.rs +++ b/src/storage/redis.rs @@ -13,7 +13,7 @@ use crate::{ model::{self, StateData}, }; -type FunnelPort = gasket::messaging::FunnelPort; +type InputPort = gasket::messaging::InputPort; #[derive(Deserialize, Clone)] pub struct Config { @@ -35,11 +35,11 @@ impl Config { pub struct Bootstrapper { config: Config, - input: FunnelPort, + input: InputPort, } impl Bootstrapper { - pub fn borrow_input_port(&mut self) -> &'_ mut FunnelPort { + pub fn borrow_input_port(&mut self) -> &'_ mut InputPort { &mut self.input } @@ -64,7 +64,7 @@ impl Bootstrapper { pub struct Worker { config: Config, connection: Option, - input: FunnelPort, + input: InputPort, } impl gasket::runtime::Worker for Worker { From 190f19a950105b9a5e991c70135842d34235216a Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Tue, 14 Jun 2022 17:25:03 -0300 Subject: [PATCH 2/4] Keep working on traverse implementation --- src/crosscut/addresses.rs | 13 +++ src/crosscut/mod.rs | 1 + src/reducers/address_by_txo.rs | 76 +++---------- src/reducers/mod.rs | 5 +- src/reducers/point_by_tx.rs | 13 +-- src/reducers/pool_by_stake.rs | 41 +++---- src/reducers/total_transactions_count.rs | 23 ++-- ...ransactions_count_by_contract_addresses.rs | 57 ++-------- ...ions_count_by_contract_address_by_epoch.rs | 101 +++++------------- src/reducers/utxo_by_address.rs | 32 ++---- src/reducers/worker.rs | 5 +- src/sources/n2c/chainsync.rs | 6 +- 12 files changed, 115 insertions(+), 258 deletions(-) create mode 100644 src/crosscut/addresses.rs diff --git a/src/crosscut/addresses.rs b/src/crosscut/addresses.rs new file mode 100644 index 00000000..acd79295 --- /dev/null +++ b/src/crosscut/addresses.rs @@ -0,0 +1,13 @@ +fn get_bit_at(input: u8, n: u8) -> bool { + if n < 32 { + input & (1 << n) != 0 + } else { + false + } +} + +// https://github.com/input-output-hk/cardano-ledger/blob/master/eras/alonzo/test-suite/cddl-files/alonzo.cddl#L135 +pub fn is_smart_contract(address: &[u8]) -> bool { + let byte_1 = address[0]; + return get_bit_at(byte_1, 4); +} diff --git a/src/crosscut/mod.rs b/src/crosscut/mod.rs index b4641886..3420a009 100644 --- a/src/crosscut/mod.rs +++ b/src/crosscut/mod.rs @@ -1,3 +1,4 @@ +pub mod addresses; mod args; mod epoch_calculator; diff --git a/src/reducers/address_by_txo.rs b/src/reducers/address_by_txo.rs index e08660f4..566f4a8f 100644 --- a/src/reducers/address_by_txo.rs +++ b/src/reducers/address_by_txo.rs @@ -1,6 +1,7 @@ use gasket::error::AsWorkError; use pallas::crypto::hash::Hash; use pallas::ledger::primitives::{alonzo, byron, ToHash}; +use pallas::ledger::traverse::MultiEraBlock; use serde::Deserialize; use crate::{crosscut, model, storage}; @@ -22,7 +23,7 @@ impl Reducer { slot: u64, address: &str, tx_hash: Hash<32>, - tx_idx: usize, + output_idx: usize, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { if let Some(addresses) = &self.config.filter { @@ -32,8 +33,8 @@ impl Reducer { } let key = match &self.config.key_prefix { - Some(prefix) => format!("{}.{}#{}", prefix, tx_hash, tx_idx), - None => format!("{}#{}", tx_hash, tx_idx), + Some(prefix) => format!("{}.{}#{}", prefix, tx_hash, output_idx), + None => format!("{}#{}", tx_hash, output_idx), }; let crdt = model::CRDTCommand::LastWriteWins(key, address.to_string(), slot); @@ -43,70 +44,25 @@ impl Reducer { Ok(()) } - fn reduce_byron_tx( + pub fn reduce_block( &mut self, - slot: u64, - tx: &byron::TxPayload, + block: &MultiEraBlock, + _state: &mut storage::ReadPlugin, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - let tx_hash = tx.transaction.to_hash(); - - tx.transaction - .outputs - .iter() - .enumerate() - .map(move |(tx_idx, tx)| { - let address = tx.address.to_addr_string().or_work_err()?; - self.send_set_add(slot, &address, tx_hash, tx_idx, output) - }) - .collect() - } + let slot = block.slot(); - fn reduce_alonzo_compatible_tx( - &mut self, - slot: u64, - tx: &alonzo::TransactionBody, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - let tx_hash = tx.to_hash(); + for tx in block.txs() { + let tx_hash = tx.hash(); - tx.iter() - .filter_map(|b| match b { - alonzo::TransactionBodyComponent::Outputs(o) => Some(o), - _ => None, - }) - .flat_map(|o| o.iter()) - .enumerate() - .map(move |(tx_idx, tx_output)| { - let address = tx_output - .to_bech32_address(&self.address_hrp) - .or_work_err()?; - self.send_set_add(slot, &address, tx_hash, tx_idx, output) - }) - .collect() - } + for (output_idx, tx_out) in tx.outputs().iter().enumerate() { + let address = tx_out.address(&self.address_hrp); - pub fn reduce_block( - &mut self, - block: &model::MultiEraBlock, - _state: &mut storage::ReadPlugin, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - match block { - model::MultiEraBlock::Byron(byron::Block::MainBlock(x)) => x - .body - .tx_payload - .iter() - .map(|tx| self.reduce_byron_tx(x.header.consensus_data.0.to_abs_slot(), tx, output)) - .collect(), - model::MultiEraBlock::Byron(_) => Ok(()), - model::MultiEraBlock::AlonzoCompatible(x) => x - .1 - .transaction_bodies - .iter() - .map(|tx| self.reduce_alonzo_compatible_tx(x.1.header.header_body.slot, tx, output)) - .collect(), + self.send_set_add(slot, &address, tx_hash, output_idx, output)?; + } } + + Ok(()) } } diff --git a/src/reducers/mod.rs b/src/reducers/mod.rs index 6694c292..6a68678c 100644 --- a/src/reducers/mod.rs +++ b/src/reducers/mod.rs @@ -1,4 +1,5 @@ use gasket::runtime::spawn_stage; +use pallas::ledger::traverse::MultiEraBlock; use serde::Deserialize; use crate::{bootstrap, crosscut, model, storage}; @@ -125,9 +126,9 @@ pub enum Reducer { } impl Reducer { - pub fn reduce_block( + pub fn reduce_block<'b>( &mut self, - block: &model::MultiEraBlock, + block: &'b MultiEraBlock<'b>, state: &mut storage::ReadPlugin, output: &mut OutputPort, ) -> Result<(), gasket::error::Error> { diff --git a/src/reducers/point_by_tx.rs b/src/reducers/point_by_tx.rs index 2fa96944..79a2b4e4 100644 --- a/src/reducers/point_by_tx.rs +++ b/src/reducers/point_by_tx.rs @@ -34,18 +34,19 @@ impl Reducer { Ok(()) } - pub fn reduce_block( + pub fn reduce_block<'b>( &mut self, - block: &MultiEraBlock, + block: &'b MultiEraBlock<'b>, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { let block_hash = block.hash(); let block_slot = block.slot(); - block - .tx_iter() - .map(|tx| self.send_set_add(tx.hash(), block_slot, block_hash, output)) - .collect() + for tx in &block.txs() { + self.send_set_add(tx.hash(), block_slot, block_hash, output)?; + } + + Ok(()) } } diff --git a/src/reducers/pool_by_stake.rs b/src/reducers/pool_by_stake.rs index b11755ce..2231d1ca 100644 --- a/src/reducers/pool_by_stake.rs +++ b/src/reducers/pool_by_stake.rs @@ -1,6 +1,6 @@ use pallas::ledger::primitives::alonzo; use pallas::ledger::primitives::alonzo::{PoolKeyhash, StakeCredential}; -use pallas::ledger::traverse::{MultiEraBlock, MultiEraTx}; +use pallas::ledger::traverse::MultiEraBlock; use serde::Deserialize; use crate::model; @@ -41,37 +41,24 @@ impl Reducer { Ok(()) } - fn reduce_tx( + pub fn reduce_block<'b>( &mut self, - slot: u64, - tx: &MultiEraTx, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - tx.iter() - .filter_map(|b| match b { - alonzo::TransactionBodyComponent::Certificates(c) => Some(c), - _ => None, - }) - .flat_map(|c| c.iter()) - .filter_map(|c| match c { - alonzo::Certificate::StakeDelegation(cred, pool) => Some((cred, pool)), - _ => None, - }) - .map(|(cred, pool)| self.send_key_write(cred, pool, slot, output)) - .collect() - } - - pub fn reduce_block( - &mut self, - block: &MultiEraBlock, + block: &'b MultiEraBlock<'b>, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { let slot = block.slot(); - block - .tx_iter() - .map(|tx| self.reduce_tx(slot, tx, output)) - .collect() + for tx in block.txs() { + for cert in tx.certs() { + if let Some(cert) = cert.as_alonzo() { + if let alonzo::Certificate::StakeDelegation(cred, pool) = cert { + self.send_key_write(cred, pool, slot, output)?; + } + } + } + } + + Ok(()) } } diff --git a/src/reducers/total_transactions_count.rs b/src/reducers/total_transactions_count.rs index ac2c638f..cc136742 100644 --- a/src/reducers/total_transactions_count.rs +++ b/src/reducers/total_transactions_count.rs @@ -1,4 +1,4 @@ -use pallas::ledger::primitives::byron; +use pallas::ledger::traverse::MultiEraBlock; use serde::Deserialize; use crate::model; @@ -31,25 +31,14 @@ impl Reducer { pub fn reduce_block( &mut self, - block: &model::MultiEraBlock, + block: &MultiEraBlock, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - match block { - model::MultiEraBlock::Byron(byron::Block::MainBlock(x)) => x - .body - .tx_payload - .iter() - .map(|_tx| self.increment_key(output)) - .collect(), - - model::MultiEraBlock::Byron(_) => Ok(()), - model::MultiEraBlock::AlonzoCompatible(block) => block - .1 - .transaction_bodies - .iter() - .map(|_tx| self.increment_key(output)) - .collect(), + for tx in block.txs() { + self.increment_key(output)?; } + + Ok(()) } } diff --git a/src/reducers/total_transactions_count_by_contract_addresses.rs b/src/reducers/total_transactions_count_by_contract_addresses.rs index c801eb17..9727b8b8 100644 --- a/src/reducers/total_transactions_count_by_contract_addresses.rs +++ b/src/reducers/total_transactions_count_by_contract_addresses.rs @@ -1,7 +1,7 @@ -use pallas::ledger::primitives::alonzo; +use pallas::ledger::traverse::{Feature, MultiEraBlock}; use serde::Deserialize; -use crate::model; +use crate::{crosscut, model}; #[derive(Deserialize)] pub struct Config { @@ -28,57 +28,22 @@ impl Reducer { Ok(()) } - fn reduce_alonzo_compatible_tx( + pub fn reduce_block( &mut self, - tx: &alonzo::TransactionBody, + block: &MultiEraBlock, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - let is_smart_contract_transaction = tx - .iter() - .filter_map(|b| match b { - alonzo::TransactionBodyComponent::Outputs(o) => Some(o), - _ => None, - }) - .flat_map(|o| o.iter()) - .enumerate() - .any(move |(_tx_idx, output)| { - fn get_bit_at(input: u8, n: u8) -> bool { - if n < 32 { - input & (1 << n) != 0 - } else { - false + if block.era().has_feature(Feature::SmartContracts) { + for tx in block.txs() { + for tx_out in tx.outputs().iter().filter_map(|x| x.as_alonzo()) { + if crosscut::addresses::is_smart_contract(tx_out.address.as_slice()) { + self.increment_for_contract_address(output)?; } } - - // first byte of address is header - let first_byte_of_address = output.address.as_slice()[0]; - // https://github.com/input-output-hk/cardano-ledger/blob/master/eras/alonzo/test-suite/cddl-files/alonzo.cddl#L135 - let is_smart_contract_address = get_bit_at(first_byte_of_address, 4); - - return is_smart_contract_address; - }); - - if is_smart_contract_transaction { - return self.increment_for_contract_address(output); - } - - return Ok(()); - } - - pub fn reduce_block( - &mut self, - block: &model::MultiEraBlock, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - match block { - model::MultiEraBlock::Byron(_) => Ok(()), - model::MultiEraBlock::AlonzoCompatible(x) => { - x.1.transaction_bodies - .iter() - .map(|tx| self.reduce_alonzo_compatible_tx(tx, output)) - .collect() } } + + Ok(()) } } diff --git a/src/reducers/transactions_count_by_contract_address_by_epoch.rs b/src/reducers/transactions_count_by_contract_address_by_epoch.rs index a4ecb043..f11248a5 100644 --- a/src/reducers/transactions_count_by_contract_address_by_epoch.rs +++ b/src/reducers/transactions_count_by_contract_address_by_epoch.rs @@ -1,4 +1,7 @@ -use pallas::ledger::primitives::alonzo; +use pallas::ledger::{ + primitives::alonzo, + traverse::{Feature, MultiEraBlock}, +}; use serde::Deserialize; use crate::{ @@ -6,6 +9,7 @@ use crate::{ model, }; +use core::slice::SlicePattern; use std::collections::HashSet; #[derive(Deserialize)] @@ -23,7 +27,7 @@ pub struct Reducer { impl Reducer { fn increment_for_addresses( &mut self, - contract_addresses: &std::collections::HashSet, + address: &str, slot: u64, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { @@ -33,90 +37,41 @@ impl Reducer { slot, ); - for contract_address in contract_addresses { - let key = match &self.config.key_prefix { - Some(prefix) => format!("{}.{}.{}", prefix, contract_address.to_string(), epoch_no), - None => format!("{}.{}", contract_address.to_string(), epoch_no), - }; + let key = match &self.config.key_prefix { + Some(prefix) => format!("{}.{}.{}", prefix, address.to_string(), epoch_no), + None => format!("{}.{}", address.to_string(), epoch_no), + }; - let crdt = model::CRDTCommand::PNCounter(key, 1); - output.send(gasket::messaging::Message::from(crdt))?; - } + let crdt = model::CRDTCommand::PNCounter(key, 1); + output.send(gasket::messaging::Message::from(crdt))?; Ok(()) } - fn reduce_alonzo_compatible_tx( - &mut self, - tx: &alonzo::TransactionBody, - slot: u64, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - let hrp_addr = &self.address_hrp.clone(); - - let addresses: Vec> = tx - .iter() - .filter_map(|b| match b { - alonzo::TransactionBodyComponent::Outputs(o) => Some(o), - _ => None, - }) - .flat_map(|o| o.iter()) - .enumerate() - .map(move |(_tx_idx, output)| { - let address = output.to_bech32_address(hrp_addr).unwrap(); - - fn get_bit_at(input: u8, n: u8) -> bool { - if n < 32 { - input & (1 << n) != 0 - } else { - false - } - } - - // first byte of address is header - let first_byte_of_address = output.address.as_slice()[0]; - // https://github.com/input-output-hk/cardano-ledger/blob/master/eras/alonzo/test-suite/cddl-files/alonzo.cddl#L135 - let is_smart_contract_address = get_bit_at(first_byte_of_address, 4); - - if is_smart_contract_address { - return Some(address); - } - - return None::; - }) - .collect(); - - if addresses.len() == 0 { - return Result::Ok(()); - } - - let currated_addresses: Vec = addresses - .into_iter() - .filter(|x| x.is_some()) - .map(|x| x.unwrap()) - .collect(); - - let deduped_addresses: HashSet = HashSet::from_iter(currated_addresses); - - return self.increment_for_addresses(&deduped_addresses, slot, output); - } - pub fn reduce_block( &mut self, - block: &model::MultiEraBlock, + block: &MultiEraBlock, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - match block { - model::MultiEraBlock::Byron(_) => Ok(()), - model::MultiEraBlock::AlonzoCompatible(x) => { - let slot = x.1.header.header_body.slot; + if block.era().has_feature(Feature::SmartContracts) { + let slot = block.slot(); - x.1.transaction_bodies + for tx in block.txs() { + let addresses: HashSet<_> = tx + .outputs() .iter() - .map(|tx| self.reduce_alonzo_compatible_tx(tx, slot, output)) - .collect() + .filter_map(|tx| tx.as_alonzo()) + .filter(|x| crosscut::addresses::is_smart_contract(x.address.as_slice())) + .filter_map(|x| x.to_bech32_address(&self.address_hrp).ok()) + .collect(); + + for address in addresses { + self.increment_for_addresses(address, slot, output)?; + } } } + + Ok(()) } } diff --git a/src/reducers/utxo_by_address.rs b/src/reducers/utxo_by_address.rs index e3b96c7e..49879b92 100644 --- a/src/reducers/utxo_by_address.rs +++ b/src/reducers/utxo_by_address.rs @@ -1,7 +1,5 @@ -use gasket::error::AsWorkError; use pallas::crypto::hash::Hash; -use pallas::ledger::primitives::{alonzo, byron, ToHash}; -use pallas::ledger::traverse::{MultiEraBlock, MultiEraTx}; +use pallas::ledger::traverse::MultiEraBlock; use serde::Deserialize; use crate::{crosscut, model}; @@ -44,31 +42,21 @@ impl Reducer { Ok(()) } - fn reduce_tx( + pub fn reduce_block<'b>( &mut self, - tx: &MultiEraTx, + block: &'b MultiEraBlock<'b>, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - let tx_hash = tx.hash(); + for tx in block.txs().into_iter() { + let tx_hash = tx.hash(); - tx.output_iter() - .enumerate() - .map(|(tx_idx, tx_output)| { + for tx_output in tx.outputs() { let address = tx_output.address(&self.address_hrp); - self.send_set_add(&address, tx_hash, tx_idx, output) - }) - .collect() - } + self.send_set_add(&address, tx_hash, 0, output)?; + } + } - pub fn reduce_block( - &mut self, - block: &MultiEraBlock, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - block - .tx_iter() - .map(|tx| self.reduce_tx(&tx, output)) - .collect() + Ok(()) } } diff --git a/src/reducers/worker.rs b/src/reducers/worker.rs index 87103dad..009cdfdc 100644 --- a/src/reducers/worker.rs +++ b/src/reducers/worker.rs @@ -1,4 +1,5 @@ use gasket::{error::AsWorkError, runtime::WorkOutcome}; +use pallas::ledger::traverse::MultiEraBlock; use crate::{model, storage}; @@ -31,8 +32,8 @@ impl Worker { } } - fn reduce_block(&mut self, block: &[u8]) -> Result<(), gasket::error::Error> { - let block = model::parse_block_content(block).or_work_err()?; + fn reduce_block<'b>(&mut self, block: &'b [u8]) -> Result<(), gasket::error::Error> { + let block = MultiEraBlock::decode(block).or_work_err()?; self.output.send(gasket::messaging::Message::from( model::CRDTCommand::block_starting(&block), diff --git a/src/sources/n2c/chainsync.rs b/src/sources/n2c/chainsync.rs index 2dcfb960..4be61fd9 100644 --- a/src/sources/n2c/chainsync.rs +++ b/src/sources/n2c/chainsync.rs @@ -1,5 +1,6 @@ use std::{collections::HashMap, ops::Deref}; +use pallas::ledger::traverse::MultiEraBlock; use pallas::network::miniprotocols::{self, chainsync, Agent, Point}; use pallas::network::multiplexer; @@ -8,7 +9,6 @@ use gasket::{ metrics::{Counter, Gauge}, }; -use crate::model; use crate::{crosscut, model::ChainSyncCommandEx, sources::utils, storage}; struct ChainObserver { @@ -41,8 +41,8 @@ impl chainsync::Observer for ChainObserver { ) -> Result> { // parse the block and extract the point of the chain let cbor = Vec::from(content.deref()); - let block = model::parse_block_content(&cbor)?; - let point = block.point()?; + let block = MultiEraBlock::decode(&cbor)?; + let point = Point::Specific(block.slot(), block.hash().to_vec()); // store the block for later retrieval self.blocks.insert(point.clone(), cbor); From 4ca3e1e88292cf47bfe3c245514a221065622bcf Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Wed, 15 Jun 2022 10:44:09 -0300 Subject: [PATCH 3/4] Finish migration to new api --- Cargo.lock | 45 ------- Cargo.toml | 1 - src/crosscut/epoch_calculator.rs | 33 ----- src/crosscut/epochs.rs | 33 +++++ src/crosscut/mod.rs | 3 +- src/enrich/mod.rs | 44 ------- src/enrich/sled.rs | 117 ------------------ src/lib.rs | 1 - src/model.rs | 2 - src/reducers/address_by_txo.rs | 2 - src/reducers/balance_by_address.temp | 108 ---------------- src/reducers/total_transactions_count.rs | 3 +- .../transactions_count_by_contract_address.rs | 96 ++++---------- ...ions_count_by_contract_address_by_epoch.rs | 37 ++---- src/reducers/transactions_count_by_epoch.rs | 73 ++--------- 15 files changed, 84 insertions(+), 514 deletions(-) delete mode 100644 src/crosscut/epoch_calculator.rs create mode 100644 src/crosscut/epochs.rs delete mode 100644 src/enrich/mod.rs delete mode 100644 src/enrich/sled.rs delete mode 100644 src/reducers/balance_by_address.temp diff --git a/Cargo.lock b/Cargo.lock index cbc1f57c..205898de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -132,15 +132,6 @@ dependencies = [ "toml", ] -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "crossbeam" version = "0.8.1" @@ -282,25 +273,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "gasket" version = "0.1.0" @@ -908,7 +880,6 @@ dependencies = [ "redis", "serde", "serde_json", - "sled", "thiserror", ] @@ -988,22 +959,6 @@ dependencies = [ "libc", ] -[[package]] -name = "sled" -version = "0.34.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" -dependencies = [ - "crc32fast", - "crossbeam-epoch", - "crossbeam-utils", - "fs2", - "fxhash", - "libc", - "log", - "parking_lot 0.11.2", -] - [[package]] name = "smallvec" version = "1.8.0" diff --git a/Cargo.toml b/Cargo.toml index f9f5bf4c..42eadffb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,6 @@ prometheus_exporter = { version = "0.8.4", default-features = false } gasket = { git = "https://github.com/construkts/gasket-rs.git" } thiserror = "1.0.30" redis = "0.21.5" -sled = "0.34.7" [features] unstable = [] diff --git a/src/crosscut/epoch_calculator.rs b/src/crosscut/epoch_calculator.rs deleted file mode 100644 index e5b624c9..00000000 --- a/src/crosscut/epoch_calculator.rs +++ /dev/null @@ -1,33 +0,0 @@ -// TODO this is temporary, we should actually use this code from Pallas as this is very generic code -pub struct EpochCalculator { -} - -impl EpochCalculator { - - pub fn get_shelley_epoch_no_for_absolute_slot( - shelley_known_slot: u64, - shelley_epoch_length: u64, - slot: u64 - ) -> u64 { - let last_byron_epoch_no = 208; - - let shelley_known_slot = shelley_known_slot as u64; - let shelley_epoch_length = shelley_epoch_length as u64; - - let shelley_epoch_no = (slot - shelley_known_slot) / shelley_epoch_length; - - return last_byron_epoch_no + shelley_epoch_no; - } - - pub fn get_byron_epoch_no_for_absolute_slot( - byron_epoch_length: u64, - byron_slot_length: u64, - slot: u64, - ) -> u64 { - let byron_epoch_length = byron_epoch_length as u64; - let byron_slot_length = byron_slot_length as u64; - - return slot / (byron_epoch_length / byron_slot_length) - } - -} diff --git a/src/crosscut/epochs.rs b/src/crosscut/epochs.rs new file mode 100644 index 00000000..b69b1108 --- /dev/null +++ b/src/crosscut/epochs.rs @@ -0,0 +1,33 @@ +// TODO this is temporary, we should actually use this code from Pallas as this +// is very generic code + +use pallas::ledger::traverse::MultiEraBlock; + +fn post_byron_epoch_for_slot(shelley_known_slot: u64, shelley_epoch_length: u32, slot: u64) -> u64 { + let last_byron_epoch_no = 208; + + let shelley_known_slot = shelley_known_slot as u64; + let shelley_epoch_length = shelley_epoch_length as u64; + + let shelley_epoch_no = (slot - shelley_known_slot) / shelley_epoch_length; + + return last_byron_epoch_no + shelley_epoch_no; +} + +fn byron_epoch_for_slot(byron_epoch_length: u32, byron_slot_length: u32, slot: u64) -> u64 { + let byron_epoch_length = byron_epoch_length as u64; + let byron_slot_length = byron_slot_length as u64; + + return slot / (byron_epoch_length / byron_slot_length); +} + +pub fn block_epoch(chain: &super::ChainWellKnownInfo, block: &MultiEraBlock) -> u64 { + let slot = block.slot(); + + match block.era() { + pallas::ledger::traverse::Era::Byron => { + byron_epoch_for_slot(chain.byron_epoch_length, chain.byron_slot_length, slot) + } + _ => post_byron_epoch_for_slot(chain.shelley_known_slot, chain.shelley_epoch_length, slot), + } +} diff --git a/src/crosscut/mod.rs b/src/crosscut/mod.rs index 3420a009..3e1ee2ab 100644 --- a/src/crosscut/mod.rs +++ b/src/crosscut/mod.rs @@ -1,6 +1,5 @@ pub mod addresses; mod args; -mod epoch_calculator; +pub mod epochs; pub use args::*; -pub use epoch_calculator::*; diff --git a/src/enrich/mod.rs b/src/enrich/mod.rs deleted file mode 100644 index b56d24b4..00000000 --- a/src/enrich/mod.rs +++ /dev/null @@ -1,44 +0,0 @@ -pub mod sled; - -use gasket::messaging::{InputPort, OutputPort}; -use serde::Deserialize; - -use crate::{bootstrap, crosscut, model}; - -#[derive(Deserialize)] -#[serde(tag = "type")] -pub enum Config { - Sled(sled::Config), -} - -impl Config { - pub fn Bootstrapper(self) -> Bootstrapper { - match self { - Config::Sled(c) => Bootstrapper::Sled(c.boostrapper()), - } - } -} - -pub enum Bootstrapper { - Sled(sled::Bootstrapper), -} - -impl Bootstrapper { - pub fn borrow_input_port(&mut self) -> &'_ mut InputPort { - match self { - Bootstrapper::Sled(x) => x.borrow_input_port(), - } - } - - pub fn borrow_output_port(&mut self) -> &'_ mut OutputPort { - match self { - Bootstrapper::Sled(x) => x.borrow_output_port(), - } - } - - pub fn spawn_stages(self, pipeline: &mut bootstrap::Pipeline) { - match self { - Bootstrapper::Sled(x) => x.spawn_stages(pipeline), - } - } -} diff --git a/src/enrich/sled.rs b/src/enrich/sled.rs deleted file mode 100644 index e644565f..00000000 --- a/src/enrich/sled.rs +++ /dev/null @@ -1,117 +0,0 @@ -use gasket::{ - error::AsWorkError, - runtime::{spawn_stage, WorkOutcome}, -}; - -use pallas::ledger::traverse::MultiEraBlock; -use serde::Deserialize; - -use crate::{bootstrap, model}; - -type InputPort = gasket::messaging::InputPort; -type OutputPort = gasket::messaging::OutputPort; - -#[derive(Deserialize, Clone)] -pub struct Config { - pub db_path: String, -} - -impl Config { - pub fn boostrapper(self) -> Bootstrapper { - Bootstrapper { - config: self, - input: Default::default(), - output: Default::default(), - } - } -} - -pub struct Bootstrapper { - config: Config, - input: InputPort, - output: OutputPort, -} - -impl Bootstrapper { - pub fn borrow_input_port(&mut self) -> &'_ mut InputPort { - &mut self.input - } - - pub fn borrow_output_port(&mut self) -> &'_ mut OutputPort { - &mut self.output - } - - pub fn spawn_stages(self, pipeline: &mut bootstrap::Pipeline) { - let worker = Worker { - config: self.config.clone(), - db: None, - input: self.input, - output: self.output, - }; - - pipeline.register_stage("enrich-sled", spawn_stage(worker, Default::default())); - } -} - -pub struct Worker { - config: Config, - db: Option, - input: InputPort, - output: OutputPort, -} - -impl Worker { - fn track_block_txs(&self, cbor: &[u8]) -> Result<(), crate::Error> { - let block = MultiEraBlock::decode(cbor).map_err(crate::Error::cbor)?; - - for tx in block.tx_iter() { - let hash = tx.hash(); - - let cbor = tx.encode().map_err(crate::Error::cbor)?; - - self.db - .unwrap() - .insert(hash, cbor) - .map_err(crate::Error::storage)?; - } - - Ok(()) - } -} - -impl gasket::runtime::Worker for Worker { - fn metrics(&self) -> gasket::metrics::Registry { - gasket::metrics::Builder::new().build() - } - - fn work(&mut self) -> gasket::runtime::WorkResult { - let msg = self.input.recv()?; - - match &msg.payload { - model::ChainSyncCommandEx::RollForward(cbor) => { - self.track_block_txs(cbor).or_work_err()?; - self.output.send(msg) - } - model::ChainSyncCommandEx::RollBack(_) => self.output.send(msg), - }; - - Ok(WorkOutcome::Partial) - } - - fn bootstrap(&mut self) -> Result<(), gasket::error::Error> { - let db = sled::open(self.config.db_path).or_work_err()?; - self.db = Some(db); - - Ok(()) - } - - fn teardown(&mut self) -> Result<(), gasket::error::Error> { - match self.db { - Some(db) => { - db.flush().or_work_err()?; - Ok(()) - } - None => Ok(()), - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 2becc5fc..53af8a43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ pub mod bootstrap; pub mod crosscut; -pub mod enrich; pub mod model; pub mod reducers; pub mod sources; diff --git a/src/model.rs b/src/model.rs index 745383e9..bb761924 100644 --- a/src/model.rs +++ b/src/model.rs @@ -2,8 +2,6 @@ use std::collections::HashSet; use pallas::{ledger::traverse::MultiEraBlock, network::miniprotocols::Point}; -use crate::Error; - #[derive(Debug)] pub enum ChainSyncCommand { RollForward(Point), diff --git a/src/reducers/address_by_txo.rs b/src/reducers/address_by_txo.rs index 566f4a8f..a59babef 100644 --- a/src/reducers/address_by_txo.rs +++ b/src/reducers/address_by_txo.rs @@ -1,6 +1,4 @@ -use gasket::error::AsWorkError; use pallas::crypto::hash::Hash; -use pallas::ledger::primitives::{alonzo, byron, ToHash}; use pallas::ledger::traverse::MultiEraBlock; use serde::Deserialize; diff --git a/src/reducers/balance_by_address.temp b/src/reducers/balance_by_address.temp deleted file mode 100644 index cbcb1995..00000000 --- a/src/reducers/balance_by_address.temp +++ /dev/null @@ -1,108 +0,0 @@ -use gasket::error::AsWorkError; -use pallas::crypto::hash::Hash; -use pallas::ledger::primitives::{alonzo, byron}; -use serde::Deserialize; - -use crate::{crosscut, model, storage}; - -#[derive(Deserialize)] -pub struct Config { - pub key_prefix: Option, - pub filter: Option>, -} - -pub struct Reducer { - config: Config, - address_hrp: String, -} - -impl Reducer { - fn send_increment( - &mut self, - slot: u64, - address: &str, - value: i64, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - let key = match &self.config.key_prefix { - Some(prefix) => format!("{}.{}", prefix, address), - None => format!("{}", address), - }; - - let crdt = model::CRDTCommand::LastWriteWins(key, address.to_string(), slot); - - output.send(gasket::messaging::Message::from(crdt))?; - - Ok(()) - } - - fn reduce_alonzo_compatible_tx( - &mut self, - slot: u64, - tx: &alonzo::TransactionBody, - state: &mut storage::ReadPlugin, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - let tx_hash = tx.to_hash(); - - tx.iter() - .filter_map(|b| match b { - alonzo::TransactionBodyComponent::Outputs(o) => Some(o), - _ => None, - }) - .flat_map(|o| o.iter()) - .enumerate() - .map(move |(tx_idx, tx_output)| { - let address = tx_output - .to_bech32_address(&self.address_hrp) - .or_work_err()?; - self.send_increment(slot, &address, 1, output) - }) - .collect(); - - tx.iter() - .filter_map(|b| match b { - alonzo::TransactionBodyComponent::Inputs(i) => Some(i), - _ => None, - }) - .flat_map(|i| i.iter()) - .map(move |tx_input| { - let txo = format!("{}#{}", tx_input.transaction_id, tx_input.index); - let address = state.read_state(model::StateQuery::KeyValue(txo))?; - self.send_increment(slot, &address, -1, output) - }) - .collect(); - - Ok(()) - } - - pub fn reduce_block( - &mut self, - block: &model::MultiEraBlock, - state: &mut storage::ReadPlugin, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - match block { - model::MultiEraBlock::AlonzoCompatible(x) => x - .1 - .transaction_bodies - .iter() - .map(|tx| { - self.reduce_alonzo_compatible_tx(x.1.header.header_body.slot, tx, state, output) - }) - .collect(), - _ => Ok(()), - } - } -} - -impl Config { - pub fn plugin(self, chain: &crosscut::ChainWellKnownInfo) -> super::Reducer { - let reducer = Reducer { - config: self, - address_hrp: chain.address_hrp.clone(), - }; - - super::Reducer::BalanceByAddress(reducer) - } -} diff --git a/src/reducers/total_transactions_count.rs b/src/reducers/total_transactions_count.rs index cc136742..91664e3b 100644 --- a/src/reducers/total_transactions_count.rs +++ b/src/reducers/total_transactions_count.rs @@ -34,7 +34,8 @@ impl Reducer { block: &MultiEraBlock, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - for tx in block.txs() { + for _tx in block.txs() { + // TODO apply filters using tx data self.increment_key(output)?; } diff --git a/src/reducers/transactions_count_by_contract_address.rs b/src/reducers/transactions_count_by_contract_address.rs index 63d298dc..66253921 100644 --- a/src/reducers/transactions_count_by_contract_address.rs +++ b/src/reducers/transactions_count_by_contract_address.rs @@ -1,4 +1,4 @@ -use pallas::ledger::primitives::alonzo; +use pallas::ledger::traverse::{Feature, MultiEraBlock}; use serde::Deserialize; use crate::{crosscut, model}; @@ -16,92 +16,44 @@ pub struct Reducer { } impl Reducer { - fn increment_for_addresses( + fn increment_for_address( &mut self, - contract_addresses: &std::collections::HashSet, + address: &str, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - for contract_address in contract_addresses { - let key = match &self.config.key_prefix { - Some(prefix) => format!("{}.{}", prefix, contract_address.to_string()), - None => format!("{}", contract_address.to_string()), - }; + let key = match &self.config.key_prefix { + Some(prefix) => format!("{}.{}", prefix, address.to_string()), + None => format!("{}", address.to_string()), + }; - let crdt = model::CRDTCommand::PNCounter(key, 1); - output.send(gasket::messaging::Message::from(crdt))?; - } + let crdt = model::CRDTCommand::PNCounter(key, 1); + output.send(gasket::messaging::Message::from(crdt))?; Ok(()) } - fn reduce_alonzo_compatible_tx( - &mut self, - tx: &alonzo::TransactionBody, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - let hrp_addr = &self.address_hrp.clone(); - - let addresses: Vec> = tx - .iter() - .filter_map(|b| match b { - alonzo::TransactionBodyComponent::Outputs(o) => Some(o), - _ => None, - }) - .flat_map(|o| o.iter()) - .enumerate() - .map(move |(_tx_idx, output)| { - let address = output.to_bech32_address(hrp_addr).unwrap(); - - fn get_bit_at(input: u8, n: u8) -> bool { - if n < 32 { - input & (1 << n) != 0 - } else { - false - } - } - - // first byte of address is header - let first_byte_of_address = output.address.as_slice()[0]; - // https://github.com/input-output-hk/cardano-ledger/blob/master/eras/alonzo/test-suite/cddl-files/alonzo.cddl#L135 - let is_smart_contract_address = get_bit_at(first_byte_of_address, 4); - - if is_smart_contract_address { - return Some(address); - } - - return None::; - }) - .collect(); - - if addresses.len() == 0 { - return Result::Ok(()); - } - - let currated_addresses: Vec = addresses - .into_iter() - .filter(|x| x.is_some()) - .map(|x| x.unwrap()) - .collect(); - - let deduped_addresses: HashSet = HashSet::from_iter(currated_addresses); - - return self.increment_for_addresses(&deduped_addresses, output); - } - pub fn reduce_block( &mut self, - block: &model::MultiEraBlock, + block: &MultiEraBlock, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - match block { - model::MultiEraBlock::Byron(_) => Ok(()), - model::MultiEraBlock::AlonzoCompatible(x) => { - x.1.transaction_bodies + if block.era().has_feature(Feature::SmartContracts) { + for tx in block.txs() { + let addresses: HashSet<_> = tx + .outputs() .iter() - .map(|tx| self.reduce_alonzo_compatible_tx(tx, output)) - .collect() + .filter_map(|tx| tx.as_alonzo()) + .filter(|x| crosscut::addresses::is_smart_contract(x.address.as_slice())) + .filter_map(|x| x.to_bech32_address(&self.address_hrp).ok()) + .collect(); + + for address in addresses.iter() { + self.increment_for_address(address, output)?; + } } } + + Ok(()) } } diff --git a/src/reducers/transactions_count_by_contract_address_by_epoch.rs b/src/reducers/transactions_count_by_contract_address_by_epoch.rs index f11248a5..9415137e 100644 --- a/src/reducers/transactions_count_by_contract_address_by_epoch.rs +++ b/src/reducers/transactions_count_by_contract_address_by_epoch.rs @@ -1,15 +1,8 @@ -use pallas::ledger::{ - primitives::alonzo, - traverse::{Feature, MultiEraBlock}, -}; +use pallas::ledger::traverse::{Feature, MultiEraBlock}; use serde::Deserialize; -use crate::{ - crosscut::{self, EpochCalculator}, - model, -}; +use crate::{crosscut, model}; -use core::slice::SlicePattern; use std::collections::HashSet; #[derive(Deserialize)] @@ -20,26 +13,19 @@ pub struct Config { pub struct Reducer { config: Config, address_hrp: String, - shelley_known_slot: u64, - shelley_epoch_length: u64, + chain: crosscut::ChainWellKnownInfo, } impl Reducer { - fn increment_for_addresses( + fn increment_for_address( &mut self, address: &str, - slot: u64, + epoch: u64, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - let epoch_no = EpochCalculator::get_shelley_epoch_no_for_absolute_slot( - self.shelley_known_slot, - self.shelley_epoch_length, - slot, - ); - let key = match &self.config.key_prefix { - Some(prefix) => format!("{}.{}.{}", prefix, address.to_string(), epoch_no), - None => format!("{}.{}", address.to_string(), epoch_no), + Some(prefix) => format!("{}.{}.{}", prefix, address.to_string(), epoch), + None => format!("{}.{}", address.to_string(), epoch), }; let crdt = model::CRDTCommand::PNCounter(key, 1); @@ -54,7 +40,7 @@ impl Reducer { output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { if block.era().has_feature(Feature::SmartContracts) { - let slot = block.slot(); + let epoch = crosscut::epochs::block_epoch(&self.chain, block); for tx in block.txs() { let addresses: HashSet<_> = tx @@ -65,8 +51,8 @@ impl Reducer { .filter_map(|x| x.to_bech32_address(&self.address_hrp).ok()) .collect(); - for address in addresses { - self.increment_for_addresses(address, slot, output)?; + for address in addresses.iter() { + self.increment_for_address(address, epoch, output)?; } } } @@ -80,8 +66,7 @@ impl Config { let reducer = Reducer { config: self, address_hrp: chain.address_hrp.clone(), - shelley_known_slot: chain.shelley_known_slot.clone() as u64, - shelley_epoch_length: chain.shelley_epoch_length.clone() as u64, + chain: chain.clone(), }; super::Reducer::TransactionsCountByContractAddressByEpoch(reducer) diff --git a/src/reducers/transactions_count_by_epoch.rs b/src/reducers/transactions_count_by_epoch.rs index a6f10eb3..488585a1 100644 --- a/src/reducers/transactions_count_by_epoch.rs +++ b/src/reducers/transactions_count_by_epoch.rs @@ -1,10 +1,7 @@ use serde::Deserialize; -use crate::{ - crosscut::{self, EpochCalculator}, - model, -}; -use pallas::ledger::primitives::byron; +use crate::{crosscut, model}; +use pallas::ledger::traverse::MultiEraBlock; #[derive(Deserialize)] pub struct Config { @@ -13,44 +10,13 @@ pub struct Config { pub struct Reducer { config: Config, - shelley_known_slot: u64, - shelley_epoch_length: u64, - byron_epoch_length: u64, - byron_slot_length: u64, + chain: crosscut::ChainWellKnownInfo, } impl Reducer { - fn reduce_alonzo_compatible_tx( - &mut self, - slot: u64, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - let epoch_no = EpochCalculator::get_shelley_epoch_no_for_absolute_slot( - self.shelley_known_slot, - self.shelley_epoch_length, - slot, - ); - - return self.increment_key(epoch_no, output); - } - - fn reduce_byron_compatible_tx( - &mut self, - slot: u64, - output: &mut super::OutputPort, - ) -> Result<(), gasket::error::Error> { - let epoch_no = EpochCalculator::get_byron_epoch_no_for_absolute_slot( - self.byron_epoch_length, - self.byron_slot_length, - slot, - ); - - return self.increment_key(epoch_no, output); - } - fn increment_key( &mut self, - epoch_no: u64, + epoch: u64, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { let prefix = match &self.config.key_prefix { @@ -58,7 +24,7 @@ impl Reducer { None => "transactions_by_epoch", }; - let key = format!("{}.{}", prefix, epoch_no.to_string()); + let key = format!("{}.{}", prefix, epoch); let crdt = model::CRDTCommand::PNCounter(key, 1); @@ -69,27 +35,17 @@ impl Reducer { pub fn reduce_block( &mut self, - block: &model::MultiEraBlock, + block: &MultiEraBlock, output: &mut super::OutputPort, ) -> Result<(), gasket::error::Error> { - match block { - model::MultiEraBlock::Byron(byron::Block::MainBlock(x)) => x - .body - .tx_payload - .iter() - .map(|_tx| { - self.reduce_byron_compatible_tx(x.header.consensus_data.0.to_abs_slot(), output) - }) - .collect(), + let epoch = crosscut::epochs::block_epoch(&self.chain, block); - model::MultiEraBlock::Byron(_) => Ok(()), - model::MultiEraBlock::AlonzoCompatible(x) => x - .1 - .transaction_bodies - .iter() - .map(|_tx| self.reduce_alonzo_compatible_tx(x.1.header.header_body.slot, output)) - .collect(), + for _tx in block.txs() { + // TODO apply filters using tx data + self.increment_key(epoch, output)?; } + + Ok(()) } } @@ -97,10 +53,7 @@ impl Config { pub fn plugin(self, chain: &crosscut::ChainWellKnownInfo) -> super::Reducer { let reducer = Reducer { config: self, - shelley_known_slot: chain.shelley_known_slot.clone() as u64, - shelley_epoch_length: chain.shelley_epoch_length.clone() as u64, - byron_epoch_length: chain.byron_epoch_length.clone() as u64, - byron_slot_length: chain.byron_slot_length.clone() as u64, + chain: chain.clone(), }; super::Reducer::TransactionsCountByEpoch(reducer) From b168e97ed4b28edc28fee66fd70da6290cdca28c Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Wed, 15 Jun 2022 11:11:45 -0300 Subject: [PATCH 4/4] Use published pallas crate --- Cargo.lock | 28 +++++++++++++++++++++------- Cargo.toml | 4 ++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 205898de..1407420f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -566,7 +566,9 @@ dependencies = [ [[package]] name = "pallas" -version = "0.11.0-alpha.0" +version = "0.11.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4a6821aa417b88472c3bed38278c968a7ebc600be4ea14cc907971ca2fb790" dependencies = [ "pallas-codec", "pallas-crypto", @@ -578,14 +580,18 @@ dependencies = [ [[package]] name = "pallas-codec" -version = "0.11.0-alpha.0" +version = "0.11.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a966504180da5ac67f704e3c2d95596c2065a63c24b8ede3462b617e1a3e274b" dependencies = [ "minicbor 0.17.1", ] [[package]] name = "pallas-crypto" -version = "0.11.0-alpha.0" +version = "0.11.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e23744565e070603ab0dcc9137e1f76256e8511371077c61b36985635b2c52" dependencies = [ "cryptoxide", "hex", @@ -596,7 +602,9 @@ dependencies = [ [[package]] name = "pallas-miniprotocols" -version = "0.11.0-alpha.0" +version = "0.11.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e846e444d341cf495f1d97ec596ae18df5b1ca76d13293308f7dc64dc385c66c" dependencies = [ "hex", "itertools", @@ -608,7 +616,9 @@ dependencies = [ [[package]] name = "pallas-multiplexer" -version = "0.11.0-alpha.0" +version = "0.11.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc514bc4d63c88c77b9aaadf0b2ab47133dd856c3afd318939606a2c26a8346f" dependencies = [ "byteorder", "hex", @@ -620,7 +630,9 @@ dependencies = [ [[package]] name = "pallas-primitives" -version = "0.11.0-alpha.0" +version = "0.11.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fb1461122763788158153379039499c94ba6263ae62276e125974dac049bfce" dependencies = [ "base58", "bech32", @@ -634,7 +646,9 @@ dependencies = [ [[package]] name = "pallas-traverse" -version = "0.11.0-alpha.0" +version = "0.11.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88c650c07d43ef16b002812e138f7a44045566704db4e039fc765228a6c46455" dependencies = [ "hex", "pallas-codec", diff --git a/Cargo.toml b/Cargo.toml index 42eadffb..7b8ff02e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,8 @@ authors = ["Santiago Carmuega "] [dependencies] -# pallas = "0.11.0-alpha.0" -pallas = { path = "../pallas/pallas" } +pallas = "0.11.0-alpha.1" +# pallas = { path = "../pallas/pallas" } hex = "0.4.3" net2 = "0.2.37" bech32 = "0.8.1"