From bb16c3cc85a778678c41877af945a791335d322b Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Wed, 23 Feb 2022 19:52:49 -0300 Subject: [PATCH] feat: Allow chainsync to start from origin (#56) --- pallas-miniprotocols/examples/blockfetch.rs | 4 +-- .../examples/chainsync-blocks.rs | 4 +-- .../examples/chainsync-headers.rs | 34 +++---------------- pallas-miniprotocols/src/chainsync/clients.rs | 19 ++++++++--- pallas-miniprotocols/src/codec.rs | 20 ++++++++--- pallas-miniprotocols/src/common.rs | 15 ++++---- 6 files changed, 47 insertions(+), 49 deletions(-) diff --git a/pallas-miniprotocols/examples/blockfetch.rs b/pallas-miniprotocols/examples/blockfetch.rs index 230d757..2abbe5e 100644 --- a/pallas-miniprotocols/examples/blockfetch.rs +++ b/pallas-miniprotocols/examples/blockfetch.rs @@ -23,12 +23,12 @@ fn main() { println!("{:?}", last); let range = ( - Point( + Point::Specific( 43847831u64, hex::decode("15b9eeee849dd6386d3770b0745e0450190f7560e5159b1b3ab13b14b2684a45") .unwrap(), ), - Point( + Point::Specific( 43847831u64, hex::decode("15b9eeee849dd6386d3770b0745e0450190f7560e5159b1b3ab13b14b2684a45") .unwrap(), diff --git a/pallas-miniprotocols/examples/chainsync-blocks.rs b/pallas-miniprotocols/examples/chainsync-blocks.rs index 9e344da..79ec5a5 100644 --- a/pallas-miniprotocols/examples/chainsync-blocks.rs +++ b/pallas-miniprotocols/examples/chainsync-blocks.rs @@ -40,13 +40,13 @@ fn main() { println!("last hanshake state: {:?}", last); // some random known-point in the chain to use as starting point for the sync - let known_points = vec![Point( + let known_points = vec![Point::Specific( 45147459, hex::decode("bee16ef28ac02abb50c340a7deff085a77f3a7b84c66250b3318dcb125c19a10").unwrap(), )]; let mut cs_channel = muxer.use_channel(5); - let cs = Consumer::::initial(known_points, NoopObserver {}); + let cs = Consumer::::initial(Some(known_points), NoopObserver {}); let cs = run_agent(cs, &mut cs_channel).unwrap(); println!("{:?}", cs); } diff --git a/pallas-miniprotocols/examples/chainsync-headers.rs b/pallas-miniprotocols/examples/chainsync-headers.rs index 3e97346..3282b9f 100644 --- a/pallas-miniprotocols/examples/chainsync-headers.rs +++ b/pallas-miniprotocols/examples/chainsync-headers.rs @@ -1,43 +1,17 @@ -use minicbor::data::Tag; use net2::TcpStreamExt; use pallas_primitives::alonzo::Header; -use pallas_primitives::Fragment; use pallas_miniprotocols::Point; use std::net::TcpStream; -use pallas_miniprotocols::chainsync::{Consumer, NoopObserver}; +use pallas_miniprotocols::chainsync::{Consumer, HeaderContent, NoopObserver}; use pallas_miniprotocols::handshake::n2n::{Client, VersionTable}; -use pallas_miniprotocols::{ - run_agent, DecodePayload, EncodePayload, PayloadDecoder, PayloadEncoder, MAINNET_MAGIC, -}; +use pallas_miniprotocols::{run_agent, MAINNET_MAGIC}; use pallas_multiplexer::Multiplexer; #[derive(Debug)] pub struct Content(u32, Header); -impl EncodePayload for Content { - fn encode_payload(&self, e: &mut PayloadEncoder) -> Result<(), Box> { - e.array(2)?; - e.u32(self.0)?; - e.tag(Tag::Cbor)?; - e.bytes(&self.1.encode_fragment()?)?; - - Ok(()) - } -} - -impl DecodePayload for Content { - fn decode_payload(d: &mut PayloadDecoder) -> Result> { - d.array()?; - let unknown = d.u32()?; // WTF is this value? - d.tag()?; - let bytes = d.bytes()?; - let header = Header::decode_fragment(bytes)?; - Ok(Content(unknown, header)) - } -} - fn main() { env_logger::init(); @@ -52,14 +26,14 @@ fn main() { let last = run_agent(Client::initial(versions), &mut hs_channel).unwrap(); println!("{:?}", last); - let known_points = vec![Point( + let known_points = vec![Point::Specific( 43847831u64, hex::decode("15b9eeee849dd6386d3770b0745e0450190f7560e5159b1b3ab13b14b2684a45").unwrap(), )]; let mut cs_channel = muxer.use_channel(2); - let cs = Consumer::::initial(known_points, NoopObserver {}); + let cs = Consumer::::initial(Some(known_points), NoopObserver {}); let cs = run_agent(cs, &mut cs_channel).unwrap(); println!("{:?}", cs); diff --git a/pallas-miniprotocols/src/chainsync/clients.rs b/pallas-miniprotocols/src/chainsync/clients.rs index bbbe538..602239b 100644 --- a/pallas-miniprotocols/src/chainsync/clients.rs +++ b/pallas-miniprotocols/src/chainsync/clients.rs @@ -52,7 +52,7 @@ where O: Observer, { pub state: State, - pub known_points: Vec, + pub known_points: Option>, pub intersect: Option, pub tip: Option, @@ -66,7 +66,7 @@ where O: Observer, C: DecodePayload + EncodePayload, { - pub fn initial(known_points: Vec, observer: O) -> Self { + pub fn initial(known_points: Option>, observer: O) -> Self { Self { state: State::Idle, intersect: None, @@ -80,7 +80,12 @@ where fn send_find_intersect(self, tx: &impl MachineOutput) -> Transition { debug!("requesting find intersect"); - let msg = Message::::FindIntersect(self.known_points.clone()); + let points = match &self.known_points { + Some(x) => x.clone(), + None => return Err("can't find intersect without known points".into()), + }; + + let msg = Message::::FindIntersect(points); tx.send_msg(&msg)?; @@ -189,8 +194,14 @@ where fn send_next(self, tx: &impl MachineOutput) -> Transition { match self.state { State::Idle => match self.intersect { + // keep going from pointer Some(_) => self.send_request_next(tx), - None => self.send_find_intersect(tx), + _ => match self.known_points { + // need to find instersection first + Some(_) => self.send_find_intersect(tx), + // start from genesis + None => self.send_request_next(tx), + }, }, _ => panic!("I don't have agency, don't know what to do"), } diff --git a/pallas-miniprotocols/src/codec.rs b/pallas-miniprotocols/src/codec.rs index 6db35e3..3c15347 100644 --- a/pallas-miniprotocols/src/codec.rs +++ b/pallas-miniprotocols/src/codec.rs @@ -3,17 +3,27 @@ use super::payloads::*; impl EncodePayload for Point { fn encode_payload(&self, e: &mut PayloadEncoder) -> Result<(), Box> { - e.array(2)?.u64(self.0)?.bytes(&self.1)?; + match self { + Point::Origin => e.array(0)?, + Point::Specific(slot, hash) => e.array(2)?.u64(*slot)?.bytes(hash)?, + }; + Ok(()) } } impl DecodePayload for Point { fn decode_payload(d: &mut PayloadDecoder) -> Result> { - d.array()?; - let slot = d.u64()?; - let hash = d.bytes()?; + let size = d.array()?; - Ok(Point(slot, Vec::from(hash))) + match size { + Some(0) => Ok(Point::Origin), + Some(2) => { + let slot = d.u64()?; + let hash = d.bytes()?; + Ok(Point::Specific(slot, Vec::from(hash))) + } + _ => Err("can't decode Point from array of size".into()), + } } } diff --git a/pallas-miniprotocols/src/common.rs b/pallas-miniprotocols/src/common.rs index 70ad4e9..382e8af 100644 --- a/pallas-miniprotocols/src/common.rs +++ b/pallas-miniprotocols/src/common.rs @@ -8,19 +8,22 @@ pub const MAINNET_MAGIC: u64 = 764824073; /// A point within a chain #[derive(Clone, Eq, PartialEq, Hash)] -pub struct Point(pub u64, pub Vec); +pub enum Point { + Origin, + Specific(u64, Vec), +} impl Debug for Point { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("Point") - .field(&self.0) - .field(&hex::encode(&self.1)) - .finish() + match self { + Self::Origin => write!(f, "Origin"), + Self::Specific(arg0, arg1) => write!(f, "({}, {})", arg0, hex::encode(arg1)), + } } } impl Point { pub fn new(slot: u64, hash: Vec) -> Self { - Point(slot, hash) + Point::Specific(slot, hash) } }