diff --git a/src/fiber/gen/gossip.rs b/src/fiber/gen/gossip.rs index 26a503603..b4d849c66 100644 --- a/src/fiber/gen/gossip.rs +++ b/src/fiber/gen/gossip.rs @@ -7500,3 +7500,1438 @@ impl From for GossipMessage { Self::new_builder().set(value).build() } } +#[derive(Clone)] +pub struct ChannelUpdateOpt(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for ChannelUpdateOpt { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for ChannelUpdateOpt { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for ChannelUpdateOpt { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(v) = self.to_opt() { + write!(f, "{}(Some({}))", Self::NAME, v) + } else { + write!(f, "{}(None)", Self::NAME) + } + } +} +impl ::core::default::Default for ChannelUpdateOpt { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + ChannelUpdateOpt::new_unchecked(v) + } +} +impl ChannelUpdateOpt { + const DEFAULT_VALUE: [u8; 0] = []; + pub fn is_none(&self) -> bool { + self.0.is_empty() + } + pub fn is_some(&self) -> bool { + !self.0.is_empty() + } + pub fn to_opt(&self) -> Option { + if self.is_none() { + None + } else { + Some(ChannelUpdate::new_unchecked(self.0.clone())) + } + } + pub fn as_reader<'r>(&'r self) -> ChannelUpdateOptReader<'r> { + ChannelUpdateOptReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for ChannelUpdateOpt { + type Builder = ChannelUpdateOptBuilder; + const NAME: &'static str = "ChannelUpdateOpt"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + ChannelUpdateOpt(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ChannelUpdateOptReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ChannelUpdateOptReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set(self.to_opt()) + } +} +#[derive(Clone, Copy)] +pub struct ChannelUpdateOptReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ChannelUpdateOptReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ChannelUpdateOptReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ChannelUpdateOptReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(v) = self.to_opt() { + write!(f, "{}(Some({}))", Self::NAME, v) + } else { + write!(f, "{}(None)", Self::NAME) + } + } +} +impl<'r> ChannelUpdateOptReader<'r> { + pub fn is_none(&self) -> bool { + self.0.is_empty() + } + pub fn is_some(&self) -> bool { + !self.0.is_empty() + } + pub fn to_opt(&self) -> Option> { + if self.is_none() { + None + } else { + Some(ChannelUpdateReader::new_unchecked(self.as_slice())) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ChannelUpdateOptReader<'r> { + type Entity = ChannelUpdateOpt; + const NAME: &'static str = "ChannelUpdateOptReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ChannelUpdateOptReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + if !slice.is_empty() { + ChannelUpdateReader::verify(&slice[..], compatible)?; + } + Ok(()) + } +} +#[derive(Clone, Debug, Default)] +pub struct ChannelUpdateOptBuilder(pub(crate) Option); +impl ChannelUpdateOptBuilder { + pub fn set(mut self, v: Option) -> Self { + self.0 = v; + self + } +} +impl molecule::prelude::Builder for ChannelUpdateOptBuilder { + type Entity = ChannelUpdateOpt; + const NAME: &'static str = "ChannelUpdateOptBuilder"; + fn expected_length(&self) -> usize { + self.0 + .as_ref() + .map(|ref inner| inner.as_slice().len()) + .unwrap_or(0) + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + self.0 + .as_ref() + .map(|ref inner| writer.write_all(inner.as_slice())) + .unwrap_or(Ok(())) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + ChannelUpdateOpt::new_unchecked(inner.into()) + } +} +impl From for ChannelUpdateOpt { + fn from(value: ChannelUpdate) -> Self { + Self::new_builder().set(Some(value)).build() + } +} +#[derive(Clone)] +pub struct ChannelFailed(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for ChannelFailed { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for ChannelFailed { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for ChannelFailed { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "channel_outpoint", self.channel_outpoint())?; + write!(f, ", {}: {}", "channel_update", self.channel_update())?; + write!(f, ", {}: {}", "node_id", self.node_id())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for ChannelFailed { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + ChannelFailed::new_unchecked(v) + } +} +impl ChannelFailed { + const DEFAULT_VALUE: [u8; 85] = [ + 85, 0, 0, 0, 16, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn channel_outpoint(&self) -> OutPoint { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + OutPoint::new_unchecked(self.0.slice(start..end)) + } + pub fn channel_update(&self) -> ChannelUpdateOpt { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + ChannelUpdateOpt::new_unchecked(self.0.slice(start..end)) + } + pub fn node_id(&self) -> Pubkey { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + Pubkey::new_unchecked(self.0.slice(start..end)) + } else { + Pubkey::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> ChannelFailedReader<'r> { + ChannelFailedReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for ChannelFailed { + type Builder = ChannelFailedBuilder; + const NAME: &'static str = "ChannelFailed"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + ChannelFailed(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ChannelFailedReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ChannelFailedReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .channel_outpoint(self.channel_outpoint()) + .channel_update(self.channel_update()) + .node_id(self.node_id()) + } +} +#[derive(Clone, Copy)] +pub struct ChannelFailedReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ChannelFailedReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ChannelFailedReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ChannelFailedReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "channel_outpoint", self.channel_outpoint())?; + write!(f, ", {}: {}", "channel_update", self.channel_update())?; + write!(f, ", {}: {}", "node_id", self.node_id())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> ChannelFailedReader<'r> { + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn channel_outpoint(&self) -> OutPointReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + OutPointReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn channel_update(&self) -> ChannelUpdateOptReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + ChannelUpdateOptReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn node_id(&self) -> PubkeyReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + PubkeyReader::new_unchecked(&self.as_slice()[start..end]) + } else { + PubkeyReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ChannelFailedReader<'r> { + type Entity = ChannelFailed; + const NAME: &'static str = "ChannelFailedReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ChannelFailedReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + OutPointReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + ChannelUpdateOptReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + PubkeyReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Ok(()) + } +} +#[derive(Clone, Debug, Default)] +pub struct ChannelFailedBuilder { + pub(crate) channel_outpoint: OutPoint, + pub(crate) channel_update: ChannelUpdateOpt, + pub(crate) node_id: Pubkey, +} +impl ChannelFailedBuilder { + pub const FIELD_COUNT: usize = 3; + pub fn channel_outpoint(mut self, v: OutPoint) -> Self { + self.channel_outpoint = v; + self + } + pub fn channel_update(mut self, v: ChannelUpdateOpt) -> Self { + self.channel_update = v; + self + } + pub fn node_id(mut self, v: Pubkey) -> Self { + self.node_id = v; + self + } +} +impl molecule::prelude::Builder for ChannelFailedBuilder { + type Entity = ChannelFailed; + const NAME: &'static str = "ChannelFailedBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.channel_outpoint.as_slice().len() + + self.channel_update.as_slice().len() + + self.node_id.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.channel_outpoint.as_slice().len(); + offsets.push(total_size); + total_size += self.channel_update.as_slice().len(); + offsets.push(total_size); + total_size += self.node_id.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.channel_outpoint.as_slice())?; + writer.write_all(self.channel_update.as_slice())?; + writer.write_all(self.node_id.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + ChannelFailed::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct NodeFailed(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for NodeFailed { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for NodeFailed { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for NodeFailed { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "node_id", self.node_id())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for NodeFailed { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + NodeFailed::new_unchecked(v) + } +} +impl NodeFailed { + const DEFAULT_VALUE: [u8; 41] = [ + 41, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 1; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn node_id(&self) -> Pubkey { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[8..]) as usize; + Pubkey::new_unchecked(self.0.slice(start..end)) + } else { + Pubkey::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> NodeFailedReader<'r> { + NodeFailedReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for NodeFailed { + type Builder = NodeFailedBuilder; + const NAME: &'static str = "NodeFailed"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + NodeFailed(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + NodeFailedReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + NodeFailedReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().node_id(self.node_id()) + } +} +#[derive(Clone, Copy)] +pub struct NodeFailedReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for NodeFailedReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for NodeFailedReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for NodeFailedReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "node_id", self.node_id())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> NodeFailedReader<'r> { + pub const FIELD_COUNT: usize = 1; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn node_id(&self) -> PubkeyReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[8..]) as usize; + PubkeyReader::new_unchecked(&self.as_slice()[start..end]) + } else { + PubkeyReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for NodeFailedReader<'r> { + type Entity = NodeFailed; + const NAME: &'static str = "NodeFailedReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + NodeFailedReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + PubkeyReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + Ok(()) + } +} +#[derive(Clone, Debug, Default)] +pub struct NodeFailedBuilder { + pub(crate) node_id: Pubkey, +} +impl NodeFailedBuilder { + pub const FIELD_COUNT: usize = 1; + pub fn node_id(mut self, v: Pubkey) -> Self { + self.node_id = v; + self + } +} +impl molecule::prelude::Builder for NodeFailedBuilder { + type Entity = NodeFailed; + const NAME: &'static str = "NodeFailedBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.node_id.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.node_id.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.node_id.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + NodeFailed::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct TlcErrData(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for TlcErrData { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for TlcErrData { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for TlcErrData { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}(", Self::NAME)?; + self.to_enum().display_inner(f)?; + write!(f, ")") + } +} +impl ::core::default::Default for TlcErrData { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + TlcErrData::new_unchecked(v) + } +} +impl TlcErrData { + const DEFAULT_VALUE: [u8; 89] = [ + 0, 0, 0, 0, 85, 0, 0, 0, 16, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + pub const ITEMS_COUNT: usize = 2; + pub fn item_id(&self) -> molecule::Number { + molecule::unpack_number(self.as_slice()) + } + pub fn to_enum(&self) -> TlcErrDataUnion { + let inner = self.0.slice(molecule::NUMBER_SIZE..); + match self.item_id() { + 0 => ChannelFailed::new_unchecked(inner).into(), + 1 => NodeFailed::new_unchecked(inner).into(), + _ => panic!("{}: invalid data", Self::NAME), + } + } + pub fn as_reader<'r>(&'r self) -> TlcErrDataReader<'r> { + TlcErrDataReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for TlcErrData { + type Builder = TlcErrDataBuilder; + const NAME: &'static str = "TlcErrData"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + TlcErrData(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + TlcErrDataReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + TlcErrDataReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set(self.to_enum()) + } +} +#[derive(Clone, Copy)] +pub struct TlcErrDataReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for TlcErrDataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for TlcErrDataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for TlcErrDataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}(", Self::NAME)?; + self.to_enum().display_inner(f)?; + write!(f, ")") + } +} +impl<'r> TlcErrDataReader<'r> { + pub const ITEMS_COUNT: usize = 2; + pub fn item_id(&self) -> molecule::Number { + molecule::unpack_number(self.as_slice()) + } + pub fn to_enum(&self) -> TlcErrDataUnionReader<'r> { + let inner = &self.as_slice()[molecule::NUMBER_SIZE..]; + match self.item_id() { + 0 => ChannelFailedReader::new_unchecked(inner).into(), + 1 => NodeFailedReader::new_unchecked(inner).into(), + _ => panic!("{}: invalid data", Self::NAME), + } + } +} +impl<'r> molecule::prelude::Reader<'r> for TlcErrDataReader<'r> { + type Entity = TlcErrData; + const NAME: &'static str = "TlcErrDataReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + TlcErrDataReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let item_id = molecule::unpack_number(slice); + let inner_slice = &slice[molecule::NUMBER_SIZE..]; + match item_id { + 0 => ChannelFailedReader::verify(inner_slice, compatible), + 1 => NodeFailedReader::verify(inner_slice, compatible), + _ => ve!(Self, UnknownItem, Self::ITEMS_COUNT, item_id), + }?; + Ok(()) + } +} +#[derive(Clone, Debug, Default)] +pub struct TlcErrDataBuilder(pub(crate) TlcErrDataUnion); +impl TlcErrDataBuilder { + pub const ITEMS_COUNT: usize = 2; + pub fn set(mut self, v: I) -> Self + where + I: ::core::convert::Into, + { + self.0 = v.into(); + self + } +} +impl molecule::prelude::Builder for TlcErrDataBuilder { + type Entity = TlcErrData; + const NAME: &'static str = "TlcErrDataBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE + self.0.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + writer.write_all(&molecule::pack_number(self.0.item_id()))?; + writer.write_all(self.0.as_slice()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + TlcErrData::new_unchecked(inner.into()) + } +} +#[derive(Debug, Clone)] +pub enum TlcErrDataUnion { + ChannelFailed(ChannelFailed), + NodeFailed(NodeFailed), +} +#[derive(Debug, Clone, Copy)] +pub enum TlcErrDataUnionReader<'r> { + ChannelFailed(ChannelFailedReader<'r>), + NodeFailed(NodeFailedReader<'r>), +} +impl ::core::default::Default for TlcErrDataUnion { + fn default() -> Self { + TlcErrDataUnion::ChannelFailed(::core::default::Default::default()) + } +} +impl ::core::fmt::Display for TlcErrDataUnion { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + TlcErrDataUnion::ChannelFailed(ref item) => { + write!(f, "{}::{}({})", Self::NAME, ChannelFailed::NAME, item) + } + TlcErrDataUnion::NodeFailed(ref item) => { + write!(f, "{}::{}({})", Self::NAME, NodeFailed::NAME, item) + } + } + } +} +impl<'r> ::core::fmt::Display for TlcErrDataUnionReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + TlcErrDataUnionReader::ChannelFailed(ref item) => { + write!(f, "{}::{}({})", Self::NAME, ChannelFailed::NAME, item) + } + TlcErrDataUnionReader::NodeFailed(ref item) => { + write!(f, "{}::{}({})", Self::NAME, NodeFailed::NAME, item) + } + } + } +} +impl TlcErrDataUnion { + pub(crate) fn display_inner(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + TlcErrDataUnion::ChannelFailed(ref item) => write!(f, "{}", item), + TlcErrDataUnion::NodeFailed(ref item) => write!(f, "{}", item), + } + } +} +impl<'r> TlcErrDataUnionReader<'r> { + pub(crate) fn display_inner(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + TlcErrDataUnionReader::ChannelFailed(ref item) => write!(f, "{}", item), + TlcErrDataUnionReader::NodeFailed(ref item) => write!(f, "{}", item), + } + } +} +impl ::core::convert::From for TlcErrDataUnion { + fn from(item: ChannelFailed) -> Self { + TlcErrDataUnion::ChannelFailed(item) + } +} +impl ::core::convert::From for TlcErrDataUnion { + fn from(item: NodeFailed) -> Self { + TlcErrDataUnion::NodeFailed(item) + } +} +impl<'r> ::core::convert::From> for TlcErrDataUnionReader<'r> { + fn from(item: ChannelFailedReader<'r>) -> Self { + TlcErrDataUnionReader::ChannelFailed(item) + } +} +impl<'r> ::core::convert::From> for TlcErrDataUnionReader<'r> { + fn from(item: NodeFailedReader<'r>) -> Self { + TlcErrDataUnionReader::NodeFailed(item) + } +} +impl TlcErrDataUnion { + pub const NAME: &'static str = "TlcErrDataUnion"; + pub fn as_bytes(&self) -> molecule::bytes::Bytes { + match self { + TlcErrDataUnion::ChannelFailed(item) => item.as_bytes(), + TlcErrDataUnion::NodeFailed(item) => item.as_bytes(), + } + } + pub fn as_slice(&self) -> &[u8] { + match self { + TlcErrDataUnion::ChannelFailed(item) => item.as_slice(), + TlcErrDataUnion::NodeFailed(item) => item.as_slice(), + } + } + pub fn item_id(&self) -> molecule::Number { + match self { + TlcErrDataUnion::ChannelFailed(_) => 0, + TlcErrDataUnion::NodeFailed(_) => 1, + } + } + pub fn item_name(&self) -> &str { + match self { + TlcErrDataUnion::ChannelFailed(_) => "ChannelFailed", + TlcErrDataUnion::NodeFailed(_) => "NodeFailed", + } + } + pub fn as_reader<'r>(&'r self) -> TlcErrDataUnionReader<'r> { + match self { + TlcErrDataUnion::ChannelFailed(item) => item.as_reader().into(), + TlcErrDataUnion::NodeFailed(item) => item.as_reader().into(), + } + } +} +impl<'r> TlcErrDataUnionReader<'r> { + pub const NAME: &'r str = "TlcErrDataUnionReader"; + pub fn as_slice(&self) -> &'r [u8] { + match self { + TlcErrDataUnionReader::ChannelFailed(item) => item.as_slice(), + TlcErrDataUnionReader::NodeFailed(item) => item.as_slice(), + } + } + pub fn item_id(&self) -> molecule::Number { + match self { + TlcErrDataUnionReader::ChannelFailed(_) => 0, + TlcErrDataUnionReader::NodeFailed(_) => 1, + } + } + pub fn item_name(&self) -> &str { + match self { + TlcErrDataUnionReader::ChannelFailed(_) => "ChannelFailed", + TlcErrDataUnionReader::NodeFailed(_) => "NodeFailed", + } + } +} +impl From for TlcErrData { + fn from(value: ChannelFailed) -> Self { + Self::new_builder().set(value).build() + } +} +impl From for TlcErrData { + fn from(value: NodeFailed) -> Self { + Self::new_builder().set(value).build() + } +} +#[derive(Clone)] +pub struct TlcErrDataOpt(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for TlcErrDataOpt { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for TlcErrDataOpt { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for TlcErrDataOpt { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(v) = self.to_opt() { + write!(f, "{}(Some({}))", Self::NAME, v) + } else { + write!(f, "{}(None)", Self::NAME) + } + } +} +impl ::core::default::Default for TlcErrDataOpt { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + TlcErrDataOpt::new_unchecked(v) + } +} +impl TlcErrDataOpt { + const DEFAULT_VALUE: [u8; 0] = []; + pub fn is_none(&self) -> bool { + self.0.is_empty() + } + pub fn is_some(&self) -> bool { + !self.0.is_empty() + } + pub fn to_opt(&self) -> Option { + if self.is_none() { + None + } else { + Some(TlcErrData::new_unchecked(self.0.clone())) + } + } + pub fn as_reader<'r>(&'r self) -> TlcErrDataOptReader<'r> { + TlcErrDataOptReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for TlcErrDataOpt { + type Builder = TlcErrDataOptBuilder; + const NAME: &'static str = "TlcErrDataOpt"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + TlcErrDataOpt(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + TlcErrDataOptReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + TlcErrDataOptReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set(self.to_opt()) + } +} +#[derive(Clone, Copy)] +pub struct TlcErrDataOptReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for TlcErrDataOptReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for TlcErrDataOptReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for TlcErrDataOptReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(v) = self.to_opt() { + write!(f, "{}(Some({}))", Self::NAME, v) + } else { + write!(f, "{}(None)", Self::NAME) + } + } +} +impl<'r> TlcErrDataOptReader<'r> { + pub fn is_none(&self) -> bool { + self.0.is_empty() + } + pub fn is_some(&self) -> bool { + !self.0.is_empty() + } + pub fn to_opt(&self) -> Option> { + if self.is_none() { + None + } else { + Some(TlcErrDataReader::new_unchecked(self.as_slice())) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for TlcErrDataOptReader<'r> { + type Entity = TlcErrDataOpt; + const NAME: &'static str = "TlcErrDataOptReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + TlcErrDataOptReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + if !slice.is_empty() { + TlcErrDataReader::verify(&slice[..], compatible)?; + } + Ok(()) + } +} +#[derive(Clone, Debug, Default)] +pub struct TlcErrDataOptBuilder(pub(crate) Option); +impl TlcErrDataOptBuilder { + pub fn set(mut self, v: Option) -> Self { + self.0 = v; + self + } +} +impl molecule::prelude::Builder for TlcErrDataOptBuilder { + type Entity = TlcErrDataOpt; + const NAME: &'static str = "TlcErrDataOptBuilder"; + fn expected_length(&self) -> usize { + self.0 + .as_ref() + .map(|ref inner| inner.as_slice().len()) + .unwrap_or(0) + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + self.0 + .as_ref() + .map(|ref inner| writer.write_all(inner.as_slice())) + .unwrap_or(Ok(())) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + TlcErrDataOpt::new_unchecked(inner.into()) + } +} +impl From for TlcErrDataOpt { + fn from(value: TlcErrData) -> Self { + Self::new_builder().set(Some(value)).build() + } +} +#[derive(Clone)] +pub struct TlcErr(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for TlcErr { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for TlcErr { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for TlcErr { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "error_code", self.error_code())?; + write!(f, ", {}: {}", "extra_data", self.extra_data())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for TlcErr { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + TlcErr::new_unchecked(v) + } +} +impl TlcErr { + const DEFAULT_VALUE: [u8; 44] = [ + 44, 0, 0, 0, 12, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn error_code(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn extra_data(&self) -> TlcErrDataOpt { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + TlcErrDataOpt::new_unchecked(self.0.slice(start..end)) + } else { + TlcErrDataOpt::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> TlcErrReader<'r> { + TlcErrReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for TlcErr { + type Builder = TlcErrBuilder; + const NAME: &'static str = "TlcErr"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + TlcErr(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + TlcErrReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + TlcErrReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .error_code(self.error_code()) + .extra_data(self.extra_data()) + } +} +#[derive(Clone, Copy)] +pub struct TlcErrReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for TlcErrReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for TlcErrReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for TlcErrReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "error_code", self.error_code())?; + write!(f, ", {}: {}", "extra_data", self.extra_data())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> TlcErrReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn error_code(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn extra_data(&self) -> TlcErrDataOptReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + TlcErrDataOptReader::new_unchecked(&self.as_slice()[start..end]) + } else { + TlcErrDataOptReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for TlcErrReader<'r> { + type Entity = TlcErr; + const NAME: &'static str = "TlcErrReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + TlcErrReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Byte32Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + TlcErrDataOptReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Clone, Debug, Default)] +pub struct TlcErrBuilder { + pub(crate) error_code: Byte32, + pub(crate) extra_data: TlcErrDataOpt, +} +impl TlcErrBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn error_code(mut self, v: Byte32) -> Self { + self.error_code = v; + self + } + pub fn extra_data(mut self, v: TlcErrDataOpt) -> Self { + self.extra_data = v; + self + } +} +impl molecule::prelude::Builder for TlcErrBuilder { + type Entity = TlcErr; + const NAME: &'static str = "TlcErrBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.error_code.as_slice().len() + + self.extra_data.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.error_code.as_slice().len(); + offsets.push(total_size); + total_size += self.extra_data.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.error_code.as_slice())?; + writer.write_all(self.extra_data.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + TlcErr::new_unchecked(inner.into()) + } +} diff --git a/src/fiber/schema/gossip.mol b/src/fiber/schema/gossip.mol index 5a4a23328..7f1ea634c 100644 --- a/src/fiber/schema/gossip.mol +++ b/src/fiber/schema/gossip.mol @@ -34,7 +34,7 @@ struct BroadcastMessageQuery { vector BroadcastMessageQueries ; // A NodeAnnouncement is a broadcast message to the network for the node information. -// An update to the node information can be broadcasted with a NodeAnnouncement with larger timestamp. +// An update to the node information can be broadcasted with a NodeAnnouncement with larger timestamp. table NodeAnnouncement { // Signature to this message. signature: EcdsaSignature, @@ -166,3 +166,25 @@ union GossipMessage { QueryBroadcastMessages, QueryBroadcastMessagesResult, } + +option ChannelUpdateOpt (ChannelUpdate); +table ChannelFailed { + channel_outpoint: OutPoint, + channel_update: ChannelUpdateOpt, + node_id: Pubkey, +} + +table NodeFailed { + node_id: Pubkey, +} + +union TlcErrData { + ChannelFailed, + NodeFailed, +} + +option TlcErrDataOpt (TlcErrData); +table TlcErr { + error_code: Byte32, + extra_data: TlcErrDataOpt, +} \ No newline at end of file diff --git a/src/fiber/types.rs b/src/fiber/types.rs index 66c292781..6e69de18a 100644 --- a/src/fiber/types.rs +++ b/src/fiber/types.rs @@ -1107,6 +1107,70 @@ impl TryFrom for RemoveTlcFulfill { } } +// impl From for molecule_gossip::TlcErr { +// fn from(tlc_err: TlcErr) -> Self { +// molecule_gossip::TlcErr::new_builder() +// .error_code(ckb_types::packed::Byte32::new(tlc_err.error_code as u32)) +// .extra_data( +// tlc_err +// .extra_data +// .map(|data| match data { +// TlcErrData::ChannelFailed { +// channel_outpoint, +// channel_update, +// node_id, +// } => molecule_gossip::TlcErrDataBuilder::set( +// molecule_gossip::ChannelFailed::new_builder() +// .channel_outpoint(channel_outpoint.into()) +// .channel_update(channel_update.into()) +// .node_id(node_id.into()) +// .build(), +// ) +// .build() +// .to_opt(), +// TlcErrData::NodeFailed { node_id } => { +// molecule_gossip::TlcErrDataBuilder::set( +// molecule_gossip::NodeFailed::new_builder() +// .node_id(node_id.into()) +// .build(), +// ) +// .build() +// .to_opt() +// } +// }) +// .pack(), +// ) +// .build() +// } +// } + +// impl TryFrom for TlcErr { +// type Error = Error; + +// fn try_from(tlc_err: molecule_gossip::TlcErr) -> Result { +// Ok(TlcErr { +// error_code: tlc_err.error_code().into(), +// extra_data: tlc_err +// .extra_data() +// .to_opt() +// .map(|data| match data.unpack() { +// TlcErrData::ChannelFailed { +// channel_outpoint, +// channel_update, +// node_id, +// } => TlcErrData::ChannelFailed { +// channel_outpoint: channel_outpoint.into(), +// channel_update: channel_update.to_opt(), +// node_id: node_id.into(), +// }, +// TlcErrData::NodeFailed { node_id } => TlcErrData::NodeFailed { +// node_id: node_id.into(), +// }, +// }), +// }) +// } +// } + #[serde_as] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum TlcErrData {