From 0672c10eabec82d12d6a04612438de63477aba2c Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Tue, 25 Jul 2023 10:13:54 -0400 Subject: [PATCH 01/57] Add parents to block --- sdk/src/types/block/core.rs | 96 ++++++++++++++++++++++++++--------- sdk/src/types/block/error.rs | 4 ++ sdk/src/types/block/parent.rs | 17 ++++++- 3 files changed, 93 insertions(+), 24 deletions(-) diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index abcd373cde..678a710d99 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 use alloc::vec::Vec; -use core::ops::Deref; use crypto::hashes::{blake2b::Blake2b256, Digest}; use packable::{ @@ -12,6 +11,7 @@ use packable::{ Packable, PackableExt, }; +use super::parent::{ShallowLikeParents, WeakParents}; use crate::types::block::{ parent::StrongParents, payload::{OptionalPayload, Payload}, @@ -25,6 +25,8 @@ use crate::types::block::{ pub struct BlockBuilder { protocol_version: Option, strong_parents: StrongParents, + weak_parents: WeakParents, + shallow_like_parents: ShallowLikeParents, payload: OptionalPayload, nonce: Option, } @@ -38,6 +40,8 @@ impl BlockBuilder { Self { protocol_version: None, strong_parents, + weak_parents: Default::default(), + shallow_like_parents: Default::default(), payload: OptionalPayload::default(), nonce: None, } @@ -50,6 +54,20 @@ impl BlockBuilder { self } + /// Adds weak parents to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { + self.weak_parents = weak_parents.into(); + self + } + + /// Adds shallow like parents to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { + self.shallow_like_parents = shallow_like_parents.into(); + self + } + /// Adds a payload to a [`BlockBuilder`]. #[inline(always)] pub fn with_payload(mut self, payload: impl Into) -> Self { @@ -65,11 +83,13 @@ impl BlockBuilder { } fn _finish(self) -> Result<(Block, Vec), Error> { - verify_payload(self.payload.as_ref())?; + verify_parents(&self.strong_parents, &self.weak_parents, &self.shallow_like_parents)?; let block = Block { protocol_version: self.protocol_version.unwrap_or(PROTOCOL_VERSION), strong_parents: self.strong_parents, + weak_parents: self.weak_parents, + shallow_like_parents: self.shallow_like_parents, payload: self.payload, nonce: self.nonce.unwrap_or(Self::DEFAULT_NONCE), }; @@ -106,6 +126,10 @@ pub struct Block { protocol_version: u8, /// Blocks that are strongly directly approved. strong_parents: StrongParents, + /// Blocks that are weakly directly approved. + weak_parents: WeakParents, + /// Blocks that are directly referenced to adjust opinion. + shallow_like_parents: ShallowLikeParents, /// The optional [Payload] of the block. payload: OptionalPayload, /// The result of the Proof of Work in order for the block to be accepted into the tangle. @@ -136,6 +160,18 @@ impl Block { &self.strong_parents } + /// Returns the weak parents of a [`Block`]. + #[inline(always)] + pub fn weak_parents(&self) -> &WeakParents { + &self.weak_parents + } + + /// Returns the shallow like parents of a [`Block`]. + #[inline(always)] + pub fn shallow_like_parents(&self) -> &ShallowLikeParents { + &self.shallow_like_parents + } + /// Returns the optional payload of a [`Block`]. #[inline(always)] pub fn payload(&self) -> Option<&Payload> { @@ -185,6 +221,8 @@ impl Packable for Block { fn pack(&self, packer: &mut P) -> Result<(), P::Error> { self.protocol_version.pack(packer)?; self.strong_parents.pack(packer)?; + self.weak_parents.pack(packer)?; + self.shallow_like_parents.pack(packer)?; self.payload.pack(packer)?; self.nonce.pack(packer)?; @@ -207,17 +245,22 @@ impl Packable for Block { } let strong_parents = StrongParents::unpack::<_, VERIFY>(unpacker, &())?; - let payload = OptionalPayload::unpack::<_, VERIFY>(unpacker, visitor)?; + let weak_parents = WeakParents::unpack::<_, VERIFY>(unpacker, &())?; + let shallow_like_parents = ShallowLikeParents::unpack::<_, VERIFY>(unpacker, &())?; if VERIFY { - verify_payload(payload.deref().as_ref()).map_err(UnpackError::Packable)?; + verify_parents(&strong_parents, &weak_parents, &shallow_like_parents).map_err(UnpackError::Packable)?; } + let payload = OptionalPayload::unpack::<_, VERIFY>(unpacker, visitor)?; + let nonce = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; let block = Self { protocol_version, strong_parents, + weak_parents, + shallow_like_parents, payload, nonce, }; @@ -238,21 +281,27 @@ impl Packable for Block { } } -// TODO not needed anymore? -fn verify_payload(payload: Option<&Payload>) -> Result<(), Error> { - if !matches!( - payload, - None | Some(Payload::Transaction(_)) | Some(Payload::TaggedData(_)) - ) { - // Safe to unwrap since it's known not to be None. - Err(Error::InvalidPayloadKind(payload.unwrap().kind())) - } else { - Ok(()) +fn verify_parents( + strong_parents: &StrongParents, + weak_parents: &WeakParents, + shallow_like_parents: &ShallowLikeParents, +) -> Result<(), Error> { + let (strong_parents, weak_parents, shallow_like_parents) = ( + strong_parents.to_set(), + weak_parents.to_set(), + shallow_like_parents.to_set(), + ); + if !weak_parents.is_disjoint(&strong_parents) || !weak_parents.is_disjoint(&shallow_like_parents) { + return Err(Error::NonDisjointParents); } + Ok(()) } pub(crate) mod dto { - use alloc::string::{String, ToString}; + use alloc::{ + collections::BTreeSet, + string::{String, ToString}, + }; use serde::{Deserialize, Serialize}; @@ -269,7 +318,9 @@ pub(crate) mod dto { /// pub protocol_version: u8, /// - pub strong_parents: Vec, + pub strong_parents: BTreeSet, + pub weak_parents: BTreeSet, + pub shallow_like_parents: BTreeSet, /// #[serde(default, skip_serializing_if = "Option::is_none")] pub payload: Option, @@ -281,7 +332,9 @@ pub(crate) mod dto { fn from(value: &Block) -> Self { Self { protocol_version: value.protocol_version(), - strong_parents: value.strong_parents().iter().map(BlockId::to_string).collect(), + strong_parents: value.strong_parents().to_set(), + weak_parents: value.weak_parents().to_set(), + shallow_like_parents: value.shallow_like_parents().to_set(), payload: value.payload().map(Into::into), nonce: value.nonce().to_string(), } @@ -293,14 +346,11 @@ pub(crate) mod dto { type Error = Error; fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { - let strong_parents = StrongParents::from_vec( - dto.strong_parents - .into_iter() - .map(|m| m.parse::().map_err(|_| Error::InvalidField("parents"))) - .collect::, Error>>()?, - )?; + let strong_parents = StrongParents::from_set(dto.strong_parents)?; let mut builder = BlockBuilder::new(strong_parents) + .with_weak_parents(WeakParents::from_set(dto.weak_parents)?) + .with_shallow_like_parents(ShallowLikeParents::from_set(dto.shallow_like_parents)?) .with_protocol_version(dto.protocol_version) .with_nonce(dto.nonce.parse::().map_err(|_| Error::InvalidField("nonce"))?); diff --git a/sdk/src/types/block/error.rs b/sdk/src/types/block/error.rs index a301424dbe..53f24077f6 100644 --- a/sdk/src/types/block/error.rs +++ b/sdk/src/types/block/error.rs @@ -91,6 +91,7 @@ pub enum Error { NativeTokensNullAmount, NativeTokensOverflow, NetworkIdMismatch { expected: u64, actual: u64 }, + NonDisjointParents, NonZeroStateIndexOrFoundryCounter, ParentsNotUniqueSorted, ProtocolVersionMismatch { expected: u8, actual: u8 }, @@ -234,6 +235,9 @@ impl fmt::Display for Error { Self::NetworkIdMismatch { expected, actual } => { write!(f, "network ID mismatch: expected {expected} but got {actual}") } + Self::NonDisjointParents => { + write!(f, "weak parents are not disjoint to strong or shallow like parents") + } Self::NonZeroStateIndexOrFoundryCounter => { write!( f, diff --git a/sdk/src/types/block/parent.rs b/sdk/src/types/block/parent.rs index c95080dd7e..7c2116f319 100644 --- a/sdk/src/types/block/parent.rs +++ b/sdk/src/types/block/parent.rs @@ -26,7 +26,6 @@ pub struct Parents( #[packable(verify_with = verify_parents)] BoxedSlicePrefix>, ); -#[allow(clippy::len_without_is_empty)] impl Parents { /// The range representing the valid number of parents. pub const COUNT_RANGE: RangeInclusive = MIN..=MAX; @@ -55,11 +54,21 @@ impl Parents { )) } + /// Returns the unique, ordered set of parents. + pub fn to_set(&self) -> BTreeSet { + self.0.iter().copied().collect() + } + /// Returns the number of parents. pub fn len(&self) -> usize { self.0.len() } + /// Returns whether the parents list is empty. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Returns an iterator over the parents. pub fn iter(&self) -> impl ExactSizeIterator + '_ { self.0.iter() @@ -74,6 +83,12 @@ fn verify_parents(parents: &[BlockId], _: &()) -> Result<(), } } +impl Default for Parents<0, MAX> { + fn default() -> Self { + Self(Default::default()) + } +} + pub type StrongParents = Parents<1, 8>; pub type WeakParents = Parents<0, 8>; pub type ShallowLikeParents = Parents<0, 8>; From 93559d5728f0f8bc10114113eba8bae27d69919d Mon Sep 17 00:00:00 2001 From: Alexandcoats Date: Tue, 25 Jul 2023 11:23:18 -0400 Subject: [PATCH 02/57] Add burned mana to rust block (#926) --- sdk/src/types/block/core.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 678a710d99..69f90df405 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -29,6 +29,7 @@ pub struct BlockBuilder { shallow_like_parents: ShallowLikeParents, payload: OptionalPayload, nonce: Option, + burned_mana: u64, } impl BlockBuilder { @@ -44,6 +45,7 @@ impl BlockBuilder { shallow_like_parents: Default::default(), payload: OptionalPayload::default(), nonce: None, + burned_mana: Default::default(), } } @@ -82,6 +84,13 @@ impl BlockBuilder { self } + /// Adds burned mana to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_burned_mana(mut self, burned_mana: u64) -> Self { + self.burned_mana = burned_mana; + self + } + fn _finish(self) -> Result<(Block, Vec), Error> { verify_parents(&self.strong_parents, &self.weak_parents, &self.shallow_like_parents)?; @@ -91,6 +100,7 @@ impl BlockBuilder { weak_parents: self.weak_parents, shallow_like_parents: self.shallow_like_parents, payload: self.payload, + burned_mana: self.burned_mana, nonce: self.nonce.unwrap_or(Self::DEFAULT_NONCE), }; @@ -132,6 +142,9 @@ pub struct Block { shallow_like_parents: ShallowLikeParents, /// The optional [Payload] of the block. payload: OptionalPayload, + /// The amount of mana the Account identified by [`IssuerId`](super::IssuerId) is at most + /// willing to burn for this block. + burned_mana: u64, /// The result of the Proof of Work in order for the block to be accepted into the tangle. nonce: u64, } @@ -184,6 +197,12 @@ impl Block { self.nonce } + /// Returns the burned mana of a [`Block`]. + #[inline(always)] + pub fn burned_mana(&self) -> u64 { + self.burned_mana + } + /// Computes the identifier of the block. #[inline(always)] pub fn id(&self) -> BlockId { @@ -224,6 +243,7 @@ impl Packable for Block { self.weak_parents.pack(packer)?; self.shallow_like_parents.pack(packer)?; self.payload.pack(packer)?; + self.burned_mana.pack(packer)?; self.nonce.pack(packer)?; Ok(()) @@ -254,6 +274,8 @@ impl Packable for Block { let payload = OptionalPayload::unpack::<_, VERIFY>(unpacker, visitor)?; + let burned_mana = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + let nonce = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; let block = Self { @@ -262,6 +284,7 @@ impl Packable for Block { weak_parents, shallow_like_parents, payload, + burned_mana, nonce, }; @@ -324,6 +347,8 @@ pub(crate) mod dto { /// #[serde(default, skip_serializing_if = "Option::is_none")] pub payload: Option, + #[serde(with = "crate::utils::serde::string")] + pub burned_mana: u64, /// pub nonce: String, } @@ -336,6 +361,7 @@ pub(crate) mod dto { weak_parents: value.weak_parents().to_set(), shallow_like_parents: value.shallow_like_parents().to_set(), payload: value.payload().map(Into::into), + burned_mana: value.burned_mana(), nonce: value.nonce().to_string(), } } @@ -352,6 +378,7 @@ pub(crate) mod dto { .with_weak_parents(WeakParents::from_set(dto.weak_parents)?) .with_shallow_like_parents(ShallowLikeParents::from_set(dto.shallow_like_parents)?) .with_protocol_version(dto.protocol_version) + .with_burned_mana(dto.burned_mana) .with_nonce(dto.nonce.parse::().map_err(|_| Error::InvalidField("nonce"))?); if let Some(p) = dto.payload { From 449565815f37a17ba90964d3cefd54556c22420a Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Tue, 25 Jul 2023 11:37:06 -0400 Subject: [PATCH 03/57] merge imports --- sdk/src/types/block/core.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 69f90df405..b87696ace6 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -11,9 +11,8 @@ use packable::{ Packable, PackableExt, }; -use super::parent::{ShallowLikeParents, WeakParents}; use crate::types::block::{ - parent::StrongParents, + parent::{ShallowLikeParents, StrongParents, WeakParents}, payload::{OptionalPayload, Payload}, protocol::ProtocolParameters, BlockId, Error, PROTOCOL_VERSION, From 5cbc0d3fba47ae03b767f88b34f19a251cd3bb2f Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Tue, 25 Jul 2023 13:52:52 -0400 Subject: [PATCH 04/57] Split block into basic and validation types --- bindings/core/src/method_handler/client.rs | 2 +- .../client/block/00_block_no_payload.rs | 2 +- .../block/01_block_confirmation_time.rs | 2 +- .../client/block/02_block_custom_parents.rs | 2 +- .../client/block/03_block_custom_payload.rs | 2 +- .../client/block/04_block_tagged_data.rs | 2 +- .../client/node_api_core/04_post_block.rs | 2 +- .../client/node_api_core/05_post_block_raw.rs | 2 +- sdk/src/client/api/block_builder/pow.rs | 12 +- sdk/src/client/api/high_level.rs | 6 +- sdk/src/client/node_api/core/routes.rs | 4 +- sdk/src/types/block/basic.rs | 167 ++++++++ sdk/src/types/block/core.rs | 388 ++++++++++++------ sdk/src/types/block/error.rs | 7 + sdk/src/types/block/mod.rs | 4 + sdk/src/types/block/protocol.rs | 16 +- sdk/src/types/block/rand/block.rs | 9 +- sdk/src/types/block/validation.rs | 178 ++++++++ sdk/src/wallet/account/operations/retry.rs | 4 +- .../transaction/submit_transaction.rs | 2 +- sdk/tests/client/node_api/mod.rs | 2 +- sdk/tests/types/block.rs | 15 +- 22 files changed, 682 insertions(+), 148 deletions(-) create mode 100644 sdk/src/types/block/basic.rs create mode 100644 sdk/src/types/block/validation.rs diff --git a/bindings/core/src/method_handler/client.rs b/bindings/core/src/method_handler/client.rs index 91fca7b572..080f924c4d 100644 --- a/bindings/core/src/method_handler/client.rs +++ b/bindings/core/src/method_handler/client.rs @@ -173,7 +173,7 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM ClientMethod::GetFallbackToLocalPow => Response::Bool(client.get_fallback_to_local_pow().await), ClientMethod::PostBlockPayload { payload } => { let block = client - .finish_block_builder( + .finish_basic_block_builder( None, Some(Payload::try_from_dto_with_params( payload, diff --git a/sdk/examples/client/block/00_block_no_payload.rs b/sdk/examples/client/block/00_block_no_payload.rs index f8a79b8a72..44c9346d9b 100644 --- a/sdk/examples/client/block/00_block_no_payload.rs +++ b/sdk/examples/client/block/00_block_no_payload.rs @@ -21,7 +21,7 @@ async fn main() -> Result<()> { let client = Client::builder().with_node(&node_url)?.finish().await?; // Create and send the block. - let block = client.finish_block_builder(None, None).await?; + let block = client.finish_basic_block_builder(None, None).await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/01_block_confirmation_time.rs b/sdk/examples/client/block/01_block_confirmation_time.rs index c63c5309e9..ee36a57e80 100644 --- a/sdk/examples/client/block/01_block_confirmation_time.rs +++ b/sdk/examples/client/block/01_block_confirmation_time.rs @@ -21,7 +21,7 @@ async fn main() -> Result<()> { let client = Client::builder().with_node(&node_url)?.finish().await?; // Create and send a block. - let block = client.finish_block_builder(None, None).await?; + let block = client.finish_basic_block_builder(None, None).await?; let block_id = block.id(); println!("{block:#?}"); diff --git a/sdk/examples/client/block/02_block_custom_parents.rs b/sdk/examples/client/block/02_block_custom_parents.rs index af097c5a03..fe4536824e 100644 --- a/sdk/examples/client/block/02_block_custom_parents.rs +++ b/sdk/examples/client/block/02_block_custom_parents.rs @@ -29,7 +29,7 @@ async fn main() -> Result<()> { // Create and send the block with custom parents. let block = client - .finish_block_builder(Some(StrongParents::from_vec(tips)?), None) + .finish_basic_block_builder(Some(StrongParents::from_vec(tips)?), None) .await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/03_block_custom_payload.rs b/sdk/examples/client/block/03_block_custom_payload.rs index 2484ba780c..522156676d 100644 --- a/sdk/examples/client/block/03_block_custom_payload.rs +++ b/sdk/examples/client/block/03_block_custom_payload.rs @@ -28,7 +28,7 @@ async fn main() -> Result<()> { // Create and send the block with the custom payload. let block = client - .finish_block_builder(None, Some(Payload::from(tagged_data_payload))) + .finish_basic_block_builder(None, Some(Payload::from(tagged_data_payload))) .await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/04_block_tagged_data.rs b/sdk/examples/client/block/04_block_tagged_data.rs index 76a2080b67..6472517c23 100644 --- a/sdk/examples/client/block/04_block_tagged_data.rs +++ b/sdk/examples/client/block/04_block_tagged_data.rs @@ -25,7 +25,7 @@ async fn main() -> Result<()> { // Create and send the block with tag and data. let block = client - .finish_block_builder( + .finish_basic_block_builder( None, Some(Payload::TaggedData(Box::new( TaggedDataPayload::new( diff --git a/sdk/examples/client/node_api_core/04_post_block.rs b/sdk/examples/client/node_api_core/04_post_block.rs index 4c7c78a9cf..c0632c638a 100644 --- a/sdk/examples/client/node_api_core/04_post_block.rs +++ b/sdk/examples/client/node_api_core/04_post_block.rs @@ -24,7 +24,7 @@ async fn main() -> Result<()> { let client = Client::builder().with_node(&node_url)?.finish().await?; // Create the block. - let block = client.finish_block_builder(None, None).await?; + let block = client.finish_basic_block_builder(None, None).await?; // Post the block. let block_id = client.post_block(&block).await?; diff --git a/sdk/examples/client/node_api_core/05_post_block_raw.rs b/sdk/examples/client/node_api_core/05_post_block_raw.rs index def4eca144..f8181280b3 100644 --- a/sdk/examples/client/node_api_core/05_post_block_raw.rs +++ b/sdk/examples/client/node_api_core/05_post_block_raw.rs @@ -24,7 +24,7 @@ async fn main() -> Result<()> { let client = Client::builder().with_node(&node_url)?.finish().await?; // Create the block. - let block = client.finish_block_builder(None, None).await?; + let block = client.finish_basic_block_builder(None, None).await?; // Post the block as raw bytes. let block_id = client.post_block_raw(&block).await?; diff --git a/sdk/src/client/api/block_builder/pow.rs b/sdk/src/client/api/block_builder/pow.rs index 46e66a00ef..8b0fb3d91f 100644 --- a/sdk/src/client/api/block_builder/pow.rs +++ b/sdk/src/client/api/block_builder/pow.rs @@ -9,13 +9,15 @@ use crate::pow::miner::{Miner, MinerBuilder, MinerCancel}; use crate::pow::wasm_miner::{SingleThreadedMiner, SingleThreadedMinerBuilder}; use crate::{ client::{ClientInner, Error, Result}, - types::block::{parent::StrongParents, payload::Payload, Block, BlockBuilder, Error as BlockError}, + types::block::{ + basic::BasicBlock, parent::StrongParents, payload::Payload, Block, BlockBuilder, Error as BlockError, + }, }; impl ClientInner { /// Finishes the block with local PoW if needed. /// Without local PoW, it will finish the block with a 0 nonce. - pub async fn finish_block_builder( + pub async fn finish_basic_block_builder( &self, strong_parents: Option, payload: Option, @@ -29,7 +31,9 @@ impl ClientInner { None => StrongParents::from_vec(self.get_tips().await?)?, }; - Ok(BlockBuilder::new(strong_parents).with_payload(payload).finish()?) + Ok(BlockBuilder::::new(strong_parents) + .with_payload(payload) + .finish()?) } } @@ -133,7 +137,7 @@ fn do_pow( payload: Option, strong_parents: StrongParents, ) -> Result { - Ok(BlockBuilder::new(strong_parents) + Ok(BlockBuilder::::new(strong_parents) .with_payload(payload) .finish_nonce(|bytes| miner.nonce(bytes, min_pow_score))?) } diff --git a/sdk/src/client/api/high_level.rs b/sdk/src/client/api/high_level.rs index 6ca05027e3..51fb9b5f02 100644 --- a/sdk/src/client/api/high_level.rs +++ b/sdk/src/client/api/high_level.rs @@ -235,7 +235,7 @@ impl Client { pub async fn reattach_unchecked(&self, block_id: &BlockId) -> Result<(BlockId, Block)> { // Get the Block object by the BlockID. let block = self.get_block(block_id).await?; - let reattach_block = self.finish_block_builder(None, block.payload().cloned()).await?; + let reattach_block = self.finish_basic_block_builder(None, block.payload().cloned()).await?; // Post the modified let block_id = self.post_block_raw(&reattach_block).await?; @@ -267,7 +267,9 @@ impl Client { *tip = *block_id; } - let promote_block = self.finish_block_builder(Some(Parents::from_vec(tips)?), None).await?; + let promote_block = self + .finish_basic_block_builder(Some(Parents::from_vec(tips)?), None) + .await?; let block_id = self.post_block_raw(&promote_block).await?; // Get block if we use remote Pow, because the node will change parents and nonce. diff --git a/sdk/src/client/node_api/core/routes.rs b/sdk/src/client/node_api/core/routes.rs index 1c32d3a31c..b9815f612c 100644 --- a/sdk/src/client/node_api/core/routes.rs +++ b/sdk/src/client/node_api/core/routes.rs @@ -136,7 +136,7 @@ impl ClientInner { self.network_info.write().await.local_pow = true; - let block_res = self.finish_block_builder(None, block.payload().cloned()).await; + let block_res = self.finish_basic_block_builder(None, block.payload().cloned()).await; let block_with_local_pow = match block_res { Ok(block) => { // reset local PoW state @@ -190,7 +190,7 @@ impl ClientInner { self.network_info.write().await.local_pow = true; - let block_res = self.finish_block_builder(None, block.payload().cloned()).await; + let block_res = self.finish_basic_block_builder(None, block.payload().cloned()).await; let block_with_local_pow = match block_res { Ok(block) => { // reset local PoW state diff --git a/sdk/src/types/block/basic.rs b/sdk/src/types/block/basic.rs new file mode 100644 index 0000000000..340a983ac1 --- /dev/null +++ b/sdk/src/types/block/basic.rs @@ -0,0 +1,167 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use packable::{ + error::{UnpackError, UnpackErrorExt}, + packer::Packer, + unpacker::Unpacker, + Packable, +}; + +use super::{ + core::verify_parents, + parent::{ShallowLikeParents, StrongParents, WeakParents}, + payload::{OptionalPayload, Payload}, + protocol::ProtocolParameters, + Error, +}; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct BasicBlock { + /// Blocks that are strongly directly approved. + pub(crate) strong_parents: StrongParents, + /// Blocks that are weakly directly approved. + pub(crate) weak_parents: WeakParents, + /// Blocks that are directly referenced to adjust opinion. + pub(crate) shallow_like_parents: ShallowLikeParents, + /// The optional [Payload] of the block. + pub(crate) payload: OptionalPayload, + /// The amount of mana the Account identified by [`IssuerId`](super::IssuerId) is at most + /// willing to burn for this block. + pub(crate) burned_mana: u64, +} + +impl BasicBlock { + pub const KIND: u8 = 0; + + /// Returns the strong parents of a [`BasicBlock`]. + #[inline(always)] + pub fn strong_parents(&self) -> &StrongParents { + &self.strong_parents + } + + /// Returns the weak parents of a [`BasicBlock`]. + #[inline(always)] + pub fn weak_parents(&self) -> &WeakParents { + &self.weak_parents + } + + /// Returns the shallow like parents of a [`BasicBlock`]. + #[inline(always)] + pub fn shallow_like_parents(&self) -> &ShallowLikeParents { + &self.shallow_like_parents + } + + /// Returns the optional payload of a [`BasicBlock`]. + #[inline(always)] + pub fn payload(&self) -> Option<&Payload> { + self.payload.as_ref() + } + + /// Returns the burned mana of a [`BasicBlock`]. + #[inline(always)] + pub fn burned_mana(&self) -> u64 { + self.burned_mana + } +} + +impl Packable for BasicBlock { + type UnpackError = Error; + type UnpackVisitor = ProtocolParameters; + + fn pack(&self, packer: &mut P) -> Result<(), P::Error> { + self.strong_parents.pack(packer)?; + self.weak_parents.pack(packer)?; + self.shallow_like_parents.pack(packer)?; + self.payload.pack(packer)?; + self.burned_mana.pack(packer)?; + + Ok(()) + } + + fn unpack( + unpacker: &mut U, + visitor: &Self::UnpackVisitor, + ) -> Result> { + let strong_parents = StrongParents::unpack::<_, VERIFY>(unpacker, &())?; + let weak_parents = WeakParents::unpack::<_, VERIFY>(unpacker, &())?; + let shallow_like_parents = ShallowLikeParents::unpack::<_, VERIFY>(unpacker, &())?; + + if VERIFY { + verify_parents(&strong_parents, &weak_parents, &shallow_like_parents).map_err(UnpackError::Packable)?; + } + + let payload = OptionalPayload::unpack::<_, VERIFY>(unpacker, visitor)?; + + let burned_mana = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let block = Self { + strong_parents, + weak_parents, + shallow_like_parents, + payload, + burned_mana, + }; + + Ok(block) + } +} + +pub(crate) mod dto { + use alloc::collections::BTreeSet; + + use serde::{Deserialize, Serialize}; + + use super::*; + use crate::types::{ + block::{payload::dto::PayloadDto, BlockId, Error}, + TryFromDto, ValidationParams, + }; + + /// The block object that nodes gossip around in the network. + #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct BasicBlockDto { + #[serde(rename = "type")] + pub kind: u8, + pub strong_parents: BTreeSet, + pub weak_parents: BTreeSet, + pub shallow_like_parents: BTreeSet, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub payload: Option, + #[serde(with = "crate::utils::serde::string")] + pub burned_mana: u64, + } + + impl From<&BasicBlock> for BasicBlockDto { + fn from(value: &BasicBlock) -> Self { + Self { + kind: BasicBlock::KIND, + strong_parents: value.strong_parents().to_set(), + weak_parents: value.weak_parents().to_set(), + shallow_like_parents: value.shallow_like_parents().to_set(), + payload: value.payload().map(Into::into), + burned_mana: value.burned_mana(), + } + } + } + + impl TryFromDto for BasicBlock { + type Dto = BasicBlockDto; + type Error = Error; + + fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { + Ok(Self { + strong_parents: StrongParents::from_set(dto.strong_parents)?, + weak_parents: WeakParents::from_set(dto.weak_parents)?, + shallow_like_parents: ShallowLikeParents::from_set(dto.shallow_like_parents)?, + payload: dto + .payload + .map(|payload| Payload::try_from_dto_with_params_inner(payload, params)) + .transpose()? + .into(), + burned_mana: dto.burned_mana, + }) + } + } +} diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index b87696ace6..279564916a 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -4,6 +4,7 @@ use alloc::vec::Vec; use crypto::hashes::{blake2b::Blake2b256, Digest}; +use derive_more::From; use packable::{ error::{UnexpectedEOF, UnpackError, UnpackErrorExt}, packer::Packer, @@ -11,6 +12,7 @@ use packable::{ Packable, PackableExt, }; +use super::{basic::BasicBlock, validation::ValidationBlock}; use crate::types::block::{ parent::{ShallowLikeParents, StrongParents, WeakParents}, payload::{OptionalPayload, Payload}, @@ -21,85 +23,134 @@ use crate::types::block::{ /// A builder to build a [`Block`]. #[derive(Clone)] #[must_use] -pub struct BlockBuilder { +pub struct BlockBuilder { protocol_version: Option, - strong_parents: StrongParents, - weak_parents: WeakParents, - shallow_like_parents: ShallowLikeParents, - payload: OptionalPayload, + inner: B, nonce: Option, - burned_mana: u64, } -impl BlockBuilder { +impl BlockBuilder { const DEFAULT_NONCE: u64 = 0; - /// Creates a new [`BlockBuilder`]. + /// Adds a protocol version to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_protocol_version(mut self, protocol_version: impl Into>) -> Self { + self.protocol_version = protocol_version.into(); + self + } + + /// Adds a nonce to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_nonce(mut self, nonce: impl Into>) -> Self { + self.nonce = nonce.into(); + self + } +} + +impl BlockBuilder { + /// Creates a new [`BlockBuilder`] for a [`BasicBlock`]. #[inline(always)] pub fn new(strong_parents: StrongParents) -> Self { Self { protocol_version: None, - strong_parents, - weak_parents: Default::default(), - shallow_like_parents: Default::default(), - payload: OptionalPayload::default(), + inner: BasicBlock { + strong_parents, + weak_parents: Default::default(), + shallow_like_parents: Default::default(), + payload: OptionalPayload::default(), + burned_mana: Default::default(), + }, nonce: None, - burned_mana: Default::default(), } } - /// Adds a protocol version to a [`BlockBuilder`]. - #[inline(always)] - pub fn with_protocol_version(mut self, protocol_version: impl Into>) -> Self { - self.protocol_version = protocol_version.into(); - self - } - /// Adds weak parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { - self.weak_parents = weak_parents.into(); + self.inner.weak_parents = weak_parents.into(); self } /// Adds shallow like parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { - self.shallow_like_parents = shallow_like_parents.into(); + self.inner.shallow_like_parents = shallow_like_parents.into(); self } /// Adds a payload to a [`BlockBuilder`]. #[inline(always)] pub fn with_payload(mut self, payload: impl Into) -> Self { - self.payload = payload.into(); + self.inner.payload = payload.into(); self } - /// Adds a nonce to a [`BlockBuilder`]. + /// Adds burned mana to a [`BlockBuilder`]. #[inline(always)] - pub fn with_nonce(mut self, nonce: impl Into>) -> Self { - self.nonce = nonce.into(); + pub fn with_burned_mana(mut self, burned_mana: u64) -> Self { + self.inner.burned_mana = burned_mana; self } +} - /// Adds burned mana to a [`BlockBuilder`]. +impl BlockBuilder { + /// Creates a new [`BlockBuilder`] for a [`ValidationBlock`]. #[inline(always)] - pub fn with_burned_mana(mut self, burned_mana: u64) -> Self { - self.burned_mana = burned_mana; + pub fn new( + strong_parents: StrongParents, + highest_supported_version: u8, + protocol_parameters: &ProtocolParameters, + ) -> Self { + Self { + protocol_version: None, + inner: ValidationBlock { + strong_parents, + weak_parents: Default::default(), + shallow_like_parents: Default::default(), + highest_supported_version, + protocol_parameters_hash: protocol_parameters.hash(), + }, + nonce: None, + } + } + + /// Adds weak parents to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { + self.inner.weak_parents = weak_parents.into(); + self + } + + /// Adds shallow like parents to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { + self.inner.shallow_like_parents = shallow_like_parents.into(); self } +} + +impl> From for BlockBuilder { + fn from(inner: B) -> Self { + Self { + protocol_version: None, + inner, + nonce: None, + } + } +} +impl> BlockBuilder { fn _finish(self) -> Result<(Block, Vec), Error> { - verify_parents(&self.strong_parents, &self.weak_parents, &self.shallow_like_parents)?; + let inner = self.inner.into(); + verify_parents( + inner.strong_parents(), + inner.weak_parents(), + inner.shallow_like_parents(), + )?; let block = Block { protocol_version: self.protocol_version.unwrap_or(PROTOCOL_VERSION), - strong_parents: self.strong_parents, - weak_parents: self.weak_parents, - shallow_like_parents: self.shallow_like_parents, - payload: self.payload, - burned_mana: self.burned_mana, + inner, nonce: self.nonce.unwrap_or(Self::DEFAULT_NONCE), }; @@ -128,22 +179,87 @@ impl BlockBuilder { } } +#[derive(Clone, Debug, Eq, PartialEq, From)] +pub enum BlockType { + Basic(BasicBlock), + Validation(ValidationBlock), +} + +impl Packable for BlockType { + type UnpackError = Error; + type UnpackVisitor = ProtocolParameters; + + fn pack(&self, packer: &mut P) -> Result<(), P::Error> { + match self { + Self::Basic(block) => { + BasicBlock::KIND.pack(packer)?; + block.pack(packer) + } + Self::Validation(block) => { + ValidationBlock::KIND.pack(packer)?; + block.pack(packer) + } + }?; + + Ok(()) + } + + fn unpack( + unpacker: &mut U, + visitor: &Self::UnpackVisitor, + ) -> Result> { + Ok(match u8::unpack::<_, VERIFY>(unpacker, &()).coerce()? { + BasicBlock::KIND => Self::from(BasicBlock::unpack::<_, VERIFY>(unpacker, visitor).coerce()?), + ValidationBlock::KIND => Self::from(ValidationBlock::unpack::<_, VERIFY>(unpacker, visitor).coerce()?), + k => return Err(Error::InvalidOutputKind(k)).map_err(UnpackError::Packable), + }) + } +} + +impl BlockType { + /// Returns the strong parents of a [`BlockType`]. + #[inline(always)] + pub fn strong_parents(&self) -> &StrongParents { + match self { + Self::Basic(b) => b.strong_parents(), + Self::Validation(b) => b.strong_parents(), + } + } + + /// Returns the weak parents of a [`BlockType`]. + #[inline(always)] + pub fn weak_parents(&self) -> &WeakParents { + match self { + Self::Basic(b) => b.weak_parents(), + Self::Validation(b) => b.weak_parents(), + } + } + + /// Returns the shallow like parents of a [`BlockType`]. + #[inline(always)] + pub fn shallow_like_parents(&self) -> &ShallowLikeParents { + match self { + Self::Basic(b) => b.shallow_like_parents(), + Self::Validation(b) => b.shallow_like_parents(), + } + } + + /// Returns the optional payload of a [`Block`]. + #[inline(always)] + pub fn payload(&self) -> Option<&Payload> { + match self { + Self::Basic(b) => b.payload(), + Self::Validation(_) => None, + } + } +} + /// Represent the object that nodes gossip around the network. #[derive(Clone, Debug, Eq, PartialEq)] pub struct Block { /// Protocol version of the block. protocol_version: u8, - /// Blocks that are strongly directly approved. - strong_parents: StrongParents, - /// Blocks that are weakly directly approved. - weak_parents: WeakParents, - /// Blocks that are directly referenced to adjust opinion. - shallow_like_parents: ShallowLikeParents, - /// The optional [Payload] of the block. - payload: OptionalPayload, - /// The amount of mana the Account identified by [`IssuerId`](super::IssuerId) is at most - /// willing to burn for this block. - burned_mana: u64, + pub(crate) inner: BlockType, /// The result of the Proof of Work in order for the block to be accepted into the tangle. nonce: u64, } @@ -154,10 +270,20 @@ impl Block { /// The maximum number of bytes in a block. pub const LENGTH_MAX: usize = 32768; - /// Creates a new [`BlockBuilder`] to construct an instance of a [`Block`]. + /// Creates a new [`BlockBuilder`] to construct an instance of a [`BasicBlock`]. #[inline(always)] - pub fn build(strong_parents: StrongParents) -> BlockBuilder { - BlockBuilder::new(strong_parents) + pub fn build_basic(strong_parents: StrongParents) -> BlockBuilder { + BlockBuilder::::new(strong_parents) + } + + /// Creates a new [`BlockBuilder`] to construct an instance of a [`ValidationBlock`]. + #[inline(always)] + pub fn build_validation( + strong_parents: StrongParents, + highest_supported_version: u8, + protocol_parameters: &ProtocolParameters, + ) -> BlockBuilder { + BlockBuilder::::new(strong_parents, highest_supported_version, protocol_parameters) } /// Returns the protocol version of a [`Block`]. @@ -169,25 +295,25 @@ impl Block { /// Returns the strong parents of a [`Block`]. #[inline(always)] pub fn strong_parents(&self) -> &StrongParents { - &self.strong_parents + self.inner.strong_parents() } /// Returns the weak parents of a [`Block`]. #[inline(always)] pub fn weak_parents(&self) -> &WeakParents { - &self.weak_parents + self.inner.weak_parents() } /// Returns the shallow like parents of a [`Block`]. #[inline(always)] pub fn shallow_like_parents(&self) -> &ShallowLikeParents { - &self.shallow_like_parents + self.inner.shallow_like_parents() } /// Returns the optional payload of a [`Block`]. #[inline(always)] pub fn payload(&self) -> Option<&Payload> { - self.payload.as_ref() + self.inner.payload() } /// Returns the nonce of a [`Block`]. @@ -196,10 +322,10 @@ impl Block { self.nonce } - /// Returns the burned mana of a [`Block`]. + /// Returns the inner block type of a [`Block`]. #[inline(always)] - pub fn burned_mana(&self) -> u64 { - self.burned_mana + pub fn inner(&self) -> &BlockType { + &self.inner } /// Computes the identifier of the block. @@ -208,12 +334,6 @@ impl Block { BlockId::new(Blake2b256::digest(self.pack_to_vec()).into()) } - /// Consumes the [`Block`], and returns ownership over its [`StrongParents`]. - #[inline(always)] - pub fn into_strong_parents(self) -> StrongParents { - self.strong_parents - } - /// Unpacks a [`Block`] from a sequence of bytes doing syntactical checks and verifying that /// there are no trailing bytes in the sequence. pub fn unpack_strict>( @@ -238,11 +358,7 @@ impl Packable for Block { fn pack(&self, packer: &mut P) -> Result<(), P::Error> { self.protocol_version.pack(packer)?; - self.strong_parents.pack(packer)?; - self.weak_parents.pack(packer)?; - self.shallow_like_parents.pack(packer)?; - self.payload.pack(packer)?; - self.burned_mana.pack(packer)?; + self.inner.pack(packer)?; self.nonce.pack(packer)?; Ok(()) @@ -263,27 +379,13 @@ impl Packable for Block { })); } - let strong_parents = StrongParents::unpack::<_, VERIFY>(unpacker, &())?; - let weak_parents = WeakParents::unpack::<_, VERIFY>(unpacker, &())?; - let shallow_like_parents = ShallowLikeParents::unpack::<_, VERIFY>(unpacker, &())?; - - if VERIFY { - verify_parents(&strong_parents, &weak_parents, &shallow_like_parents).map_err(UnpackError::Packable)?; - } - - let payload = OptionalPayload::unpack::<_, VERIFY>(unpacker, visitor)?; - - let burned_mana = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + let inner = BlockType::unpack::<_, VERIFY>(unpacker, visitor)?; let nonce = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; let block = Self { protocol_version, - strong_parents, - weak_parents, - shallow_like_parents, - payload, - burned_mana, + inner, nonce, }; @@ -303,7 +405,7 @@ impl Packable for Block { } } -fn verify_parents( +pub(crate) fn verify_parents( strong_parents: &StrongParents, weak_parents: &WeakParents, shallow_like_parents: &ShallowLikeParents, @@ -320,35 +422,90 @@ fn verify_parents( } pub(crate) mod dto { - use alloc::{ - collections::BTreeSet, - string::{String, ToString}, - }; + use alloc::string::{String, ToString}; use serde::{Deserialize, Serialize}; + use serde_json::Value; use super::*; use crate::types::{ - block::{payload::dto::PayloadDto, Error}, + block::{basic::dto::BasicBlockDto, validation::dto::ValidationBlockDto, Error}, TryFromDto, ValidationParams, }; + #[derive(Clone, Debug, Eq, PartialEq, From)] + pub enum BlockTypeDto { + Basic(BasicBlockDto), + Validation(ValidationBlockDto), + } + + impl From<&BlockType> for BlockTypeDto { + fn from(value: &BlockType) -> Self { + match value { + BlockType::Basic(b) => Self::Basic(b.into()), + BlockType::Validation(b) => Self::Validation(b.into()), + } + } + } + + impl<'de> Deserialize<'de> for BlockTypeDto { + fn deserialize>(d: D) -> Result { + let value = Value::deserialize(d)?; + Ok( + match value + .get("type") + .and_then(Value::as_u64) + .ok_or_else(|| serde::de::Error::custom("invalid block type"))? as u8 + { + BasicBlock::KIND => Self::Basic( + BasicBlockDto::deserialize(value) + .map_err(|e| serde::de::Error::custom(format!("cannot deserialize basic block: {e}")))?, + ), + ValidationBlock::KIND => { + Self::Validation(ValidationBlockDto::deserialize(value).map_err(|e| { + serde::de::Error::custom(format!("cannot deserialize validation block: {e}")) + })?) + } + _ => return Err(serde::de::Error::custom("invalid output type")), + }, + ) + } + } + + impl Serialize for BlockTypeDto { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + #[derive(Serialize)] + #[serde(untagged)] + enum BlockTypeDto_<'a> { + T0(&'a BasicBlockDto), + T1(&'a ValidationBlockDto), + } + #[derive(Serialize)] + struct TypedBlock<'a> { + #[serde(flatten)] + kind: BlockTypeDto_<'a>, + } + let output = match self { + Self::Basic(o) => TypedBlock { + kind: BlockTypeDto_::T0(o), + }, + Self::Validation(o) => TypedBlock { + kind: BlockTypeDto_::T1(o), + }, + }; + output.serialize(serializer) + } + } + /// The block object that nodes gossip around in the network. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct BlockDto { - /// pub protocol_version: u8, - /// - pub strong_parents: BTreeSet, - pub weak_parents: BTreeSet, - pub shallow_like_parents: BTreeSet, - /// - #[serde(default, skip_serializing_if = "Option::is_none")] - pub payload: Option, - #[serde(with = "crate::utils::serde::string")] - pub burned_mana: u64, - /// + pub inner: BlockTypeDto, pub nonce: String, } @@ -356,11 +513,7 @@ pub(crate) mod dto { fn from(value: &Block) -> Self { Self { protocol_version: value.protocol_version(), - strong_parents: value.strong_parents().to_set(), - weak_parents: value.weak_parents().to_set(), - shallow_like_parents: value.shallow_like_parents().to_set(), - payload: value.payload().map(Into::into), - burned_mana: value.burned_mana(), + inner: value.inner().into(), nonce: value.nonce().to_string(), } } @@ -371,20 +524,23 @@ pub(crate) mod dto { type Error = Error; fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { - let strong_parents = StrongParents::from_set(dto.strong_parents)?; - - let mut builder = BlockBuilder::new(strong_parents) - .with_weak_parents(WeakParents::from_set(dto.weak_parents)?) - .with_shallow_like_parents(ShallowLikeParents::from_set(dto.shallow_like_parents)?) + let inner = BlockType::try_from_dto_with_params_inner(dto.inner, params)?; + BlockBuilder::from(inner) .with_protocol_version(dto.protocol_version) - .with_burned_mana(dto.burned_mana) - .with_nonce(dto.nonce.parse::().map_err(|_| Error::InvalidField("nonce"))?); + .with_nonce(dto.nonce.parse::().map_err(|_| Error::InvalidField("nonce"))?) + .finish() + } + } - if let Some(p) = dto.payload { - builder = builder.with_payload(Payload::try_from_dto_with_params_inner(p, params)?); - } + impl TryFromDto for BlockType { + type Dto = BlockTypeDto; + type Error = Error; - builder.finish() + fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { + Ok(match dto { + BlockTypeDto::Basic(b) => Self::Basic(BasicBlock::try_from_dto_with_params(b, ¶ms)?), + BlockTypeDto::Validation(b) => Self::Validation(ValidationBlock::try_from_dto_with_params(b, ¶ms)?), + }) } } } diff --git a/sdk/src/types/block/error.rs b/sdk/src/types/block/error.rs index 53f24077f6..da1837d3b0 100644 --- a/sdk/src/types/block/error.rs +++ b/sdk/src/types/block/error.rs @@ -65,6 +65,7 @@ pub enum Error { InvalidParentCount, InvalidPayloadKind(u32), InvalidPayloadLength { expected: usize, actual: usize }, + InvalidProtocolParametersHash { expected: String, actual: String }, InvalidReferenceIndex(>::Error), InvalidSignature, InvalidSignatureKind(u8), @@ -193,6 +194,12 @@ impl fmt::Display for Error { Self::InvalidPayloadLength { expected, actual } => { write!(f, "invalid payload length: expected {expected} but got {actual}") } + Self::InvalidProtocolParametersHash { expected, actual } => { + write!( + f, + "invalid protocol parameters hash: expected {expected} but got {actual}" + ) + } Self::InvalidReferenceIndex(index) => write!(f, "invalid reference index: {index}"), Self::InvalidSignature => write!(f, "invalid signature provided"), Self::InvalidSignatureKind(k) => write!(f, "invalid signature kind: {k}"), diff --git a/sdk/src/types/block/mod.rs b/sdk/src/types/block/mod.rs index 2228ce58db..8db9cffe8f 100644 --- a/sdk/src/types/block/mod.rs +++ b/sdk/src/types/block/mod.rs @@ -12,6 +12,8 @@ mod issuer_id; /// A module that provides types and syntactic validations of addresses. pub mod address; +/// A module that provides types and syntactic validations of basic blocks. +pub mod basic; /// A module that provides types and syntactic validations of blocks. pub mod core; /// A module that contains helper functions and types. @@ -37,6 +39,8 @@ pub mod signature; pub mod slot; /// A module that provides types and syntactic validations of unlocks. pub mod unlock; +/// A module that provides types and syntactic validations of validation blocks. +pub mod validation; #[cfg(feature = "serde")] pub(crate) use r#macro::string_serde_impl; diff --git a/sdk/src/types/block/protocol.rs b/sdk/src/types/block/protocol.rs index e3fc3669ef..6ad96794ce 100644 --- a/sdk/src/types/block/protocol.rs +++ b/sdk/src/types/block/protocol.rs @@ -4,7 +4,8 @@ use alloc::string::String; use core::borrow::Borrow; -use packable::{prefix::StringPrefix, Packable}; +use crypto::hashes::{blake2b::Blake2b256, Digest}; +use packable::{prefix::StringPrefix, Packable, PackableExt}; use super::address::Hrp; use crate::types::block::{helper::network_name_to_id, output::RentStructure, ConvertTo, Error, PROTOCOL_VERSION}; @@ -143,6 +144,10 @@ impl ProtocolParameters { pub fn slot_duration_in_seconds(&self) -> u8 { self.slot_duration_in_seconds } + + pub fn hash(&self) -> ProtocolParametersHash { + ProtocolParametersHash::new(Blake2b256::digest(self.pack_to_vec()).into()) + } } /// Returns a [`ProtocolParameters`] for testing purposes. @@ -161,3 +166,12 @@ pub fn protocol_parameters() -> ProtocolParameters { ) .unwrap() } + +impl_id!( + pub ProtocolParametersHash, + 32, + "The hash of the protocol parameters for the Highest Supported Version." +); + +#[cfg(feature = "serde")] +string_serde_impl!(ProtocolParametersHash); diff --git a/sdk/src/types/block/rand/block.rs b/sdk/src/types/block/rand/block.rs index 973a7be44b..4762d0fb43 100644 --- a/sdk/src/types/block/rand/block.rs +++ b/sdk/src/types/block/rand/block.rs @@ -4,6 +4,7 @@ use alloc::vec::Vec; use crate::types::block::{ + basic::BasicBlock, parent::StrongParents, rand::{ bytes::rand_bytes_array, number::rand_number, parents::rand_strong_parents, payload::rand_payload_for_block, @@ -23,9 +24,9 @@ pub fn rand_block_ids(len: usize) -> Vec { parents } -/// Generates a random block with given parents. -pub fn rand_block_with_strong_parents(strong_parents: StrongParents) -> Block { - BlockBuilder::new(strong_parents) +/// Generates a random basic block with given parents. +pub fn rand_basic_block_with_strong_parents(strong_parents: StrongParents) -> Block { + BlockBuilder::::new(strong_parents) .with_payload(rand_payload_for_block()) .with_nonce(rand_number::()) .finish() @@ -34,5 +35,5 @@ pub fn rand_block_with_strong_parents(strong_parents: StrongParents) -> Block { /// Generates a random block. pub fn rand_block() -> Block { - rand_block_with_strong_parents(rand_strong_parents()) + rand_basic_block_with_strong_parents(rand_strong_parents()) } diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs new file mode 100644 index 0000000000..0700c96f05 --- /dev/null +++ b/sdk/src/types/block/validation.rs @@ -0,0 +1,178 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use packable::{ + error::{UnpackError, UnpackErrorExt}, + packer::Packer, + unpacker::Unpacker, + Packable, +}; + +use super::{ + core::verify_parents, + parent::{ShallowLikeParents, StrongParents, WeakParents}, + protocol::{ProtocolParameters, ProtocolParametersHash}, + Error, +}; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ValidationBlock { + /// Blocks that are strongly directly approved. + pub(crate) strong_parents: StrongParents, + /// Blocks that are weakly directly approved. + pub(crate) weak_parents: WeakParents, + /// Blocks that are directly referenced to adjust opinion. + pub(crate) shallow_like_parents: ShallowLikeParents, + /// The highest supported protocol version the issuer of this block supports. + pub(crate) highest_supported_version: u8, + /// The hash of the protocol parameters for the Highest Supported Version. + pub(crate) protocol_parameters_hash: ProtocolParametersHash, +} + +impl ValidationBlock { + pub const KIND: u8 = 1; + + /// Returns the strong parents of a [`ValidationBlock`]. + #[inline(always)] + pub fn strong_parents(&self) -> &StrongParents { + &self.strong_parents + } + + /// Returns the weak parents of a [`ValidationBlock`]. + #[inline(always)] + pub fn weak_parents(&self) -> &WeakParents { + &self.weak_parents + } + + /// Returns the shallow like parents of a [`ValidationBlock`]. + #[inline(always)] + pub fn shallow_like_parents(&self) -> &ShallowLikeParents { + &self.shallow_like_parents + } + + /// Returns the shallow like parents of a [`ValidationBlock`]. + #[inline(always)] + pub fn highest_supported_version(&self) -> u8 { + self.highest_supported_version + } + + /// Returns the protocol parameters hash of a [`ValidationBlock`]. + #[inline(always)] + pub fn protocol_parameters_hash(&self) -> ProtocolParametersHash { + self.protocol_parameters_hash + } +} + +impl Packable for ValidationBlock { + type UnpackError = Error; + type UnpackVisitor = ProtocolParameters; + + fn pack(&self, packer: &mut P) -> Result<(), P::Error> { + self.strong_parents.pack(packer)?; + self.weak_parents.pack(packer)?; + self.shallow_like_parents.pack(packer)?; + self.highest_supported_version.pack(packer)?; + self.protocol_parameters_hash.pack(packer)?; + + Ok(()) + } + + fn unpack( + unpacker: &mut U, + visitor: &Self::UnpackVisitor, + ) -> Result> { + let strong_parents = StrongParents::unpack::<_, VERIFY>(unpacker, &())?; + let weak_parents = WeakParents::unpack::<_, VERIFY>(unpacker, &())?; + let shallow_like_parents = ShallowLikeParents::unpack::<_, VERIFY>(unpacker, &())?; + + if VERIFY { + verify_parents(&strong_parents, &weak_parents, &shallow_like_parents).map_err(UnpackError::Packable)?; + } + + let highest_supported_version = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let protocol_parameters_hash = ProtocolParametersHash::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + // TODO: Is this actually right/needed? + if VERIFY { + validate_protocol_params_hash(&protocol_parameters_hash, visitor).map_err(UnpackError::Packable)?; + } + + let block = Self { + strong_parents, + weak_parents, + shallow_like_parents, + highest_supported_version, + protocol_parameters_hash, + }; + + Ok(block) + } +} + +fn validate_protocol_params_hash(hash: &ProtocolParametersHash, params: &ProtocolParameters) -> Result<(), Error> { + let params_hash = params.hash(); + if hash != ¶ms_hash { + return Err(Error::InvalidProtocolParametersHash { + expected: params_hash.to_string(), + actual: hash.to_string(), + }); + } + Ok(()) +} + +pub(crate) mod dto { + use alloc::collections::BTreeSet; + + use serde::{Deserialize, Serialize}; + + use super::*; + use crate::types::{ + block::{BlockId, Error}, + TryFromDto, ValidationParams, + }; + + /// The block object that nodes gossip around in the network. + #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct ValidationBlockDto { + #[serde(rename = "type")] + pub kind: u8, + pub strong_parents: BTreeSet, + pub weak_parents: BTreeSet, + pub shallow_like_parents: BTreeSet, + pub highest_supported_version: u8, + pub protocol_parameters_hash: ProtocolParametersHash, + } + + impl From<&ValidationBlock> for ValidationBlockDto { + fn from(value: &ValidationBlock) -> Self { + Self { + kind: ValidationBlock::KIND, + strong_parents: value.strong_parents().to_set(), + weak_parents: value.weak_parents().to_set(), + shallow_like_parents: value.shallow_like_parents().to_set(), + highest_supported_version: value.highest_supported_version(), + protocol_parameters_hash: value.protocol_parameters_hash(), + } + } + } + + impl TryFromDto for ValidationBlock { + type Dto = ValidationBlockDto; + type Error = Error; + + fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { + if let Some(protocol_params) = params.protocol_parameters() { + validate_protocol_params_hash(&dto.protocol_parameters_hash, protocol_params)?; + } + Ok(Self { + strong_parents: StrongParents::from_set(dto.strong_parents)?, + weak_parents: WeakParents::from_set(dto.weak_parents)?, + shallow_like_parents: ShallowLikeParents::from_set(dto.shallow_like_parents)?, + highest_supported_version: dto.highest_supported_version, + protocol_parameters_hash: dto.protocol_parameters_hash, + }) + } + } +} diff --git a/sdk/src/wallet/account/operations/retry.rs b/sdk/src/wallet/account/operations/retry.rs index b43936fbd9..b3751cdc95 100644 --- a/sdk/src/wallet/account/operations/retry.rs +++ b/sdk/src/wallet/account/operations/retry.rs @@ -69,7 +69,7 @@ where Some(block_id) => block_id, None => self .client() - .finish_block_builder(None, Some(Payload::Transaction(Box::new(transaction.payload.clone())))) + .finish_basic_block_builder(None, Some(Payload::Transaction(Box::new(transaction.payload.clone())))) .await? .id(), }; @@ -109,7 +109,7 @@ where } else if block_metadata.should_reattach.unwrap_or(false) { let reattached_block = self .client() - .finish_block_builder( + .finish_basic_block_builder( None, Some(Payload::Transaction(Box::new(transaction.payload.clone()))), ) diff --git a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs index 3485a58cd9..d8ea17e79d 100644 --- a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs +++ b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs @@ -34,7 +34,7 @@ where } let block = self .client() - .finish_block_builder(None, Some(Payload::from(transaction_payload))) + .finish_basic_block_builder(None, Some(Payload::from(transaction_payload))) .await?; #[cfg(feature = "events")] diff --git a/sdk/tests/client/node_api/mod.rs b/sdk/tests/client/node_api/mod.rs index 2f8b5d3798..fdd5d8fa6e 100644 --- a/sdk/tests/client/node_api/mod.rs +++ b/sdk/tests/client/node_api/mod.rs @@ -27,7 +27,7 @@ async fn setup_tagged_data_block() -> BlockId { let client = setup_client_with_node_health_ignored().await; client - .finish_block_builder( + .finish_basic_block_builder( None, Some(Payload::TaggedData(Box::new( TaggedDataPayload::new(b"Hello".to_vec(), b"Tangle".to_vec()).unwrap(), diff --git a/sdk/tests/types/block.rs b/sdk/tests/types/block.rs index cc8a26a366..b15ab3e084 100644 --- a/sdk/tests/types/block.rs +++ b/sdk/tests/types/block.rs @@ -4,6 +4,7 @@ use iota_sdk::{ pow::{miner::get_miner, score::PowScorer}, types::block::{ + basic::BasicBlock, parent::Parents, payload::{Payload, TaggedDataPayload}, protocol::protocol_parameters, @@ -17,7 +18,7 @@ use packable::{error::UnpackError, PackableExt}; #[test] fn default_finish_zero_nonce() { - let block = BlockBuilder::new(rand_strong_parents()).finish().unwrap(); + let block = BlockBuilder::::new(rand_strong_parents()).finish().unwrap(); assert!(block.nonce() == 0); } @@ -25,7 +26,7 @@ fn default_finish_zero_nonce() { #[test] fn pow_provider() { let min_pow_score = protocol_parameters().min_pow_score(); - let block = BlockBuilder::new(rand_strong_parents()) + let block = BlockBuilder::::new(rand_strong_parents()) .finish_nonce(get_miner(min_pow_score)) .unwrap(); @@ -37,7 +38,7 @@ fn pow_provider() { #[test] fn invalid_length() { - let res = BlockBuilder::new(Parents::from_vec(rand_block_ids(2)).unwrap()) + let res = BlockBuilder::::new(Parents::from_vec(rand_block_ids(2)).unwrap()) .with_nonce(42) .with_payload(TaggedDataPayload::new(vec![42], vec![0u8; Block::LENGTH_MAX - Block::LENGTH_MIN - 9]).unwrap()) .finish(); @@ -83,7 +84,7 @@ fn unpack_invalid_remaining_bytes() { #[test] fn pack_unpack_valid() { let protocol_parameters = protocol_parameters(); - let block = BlockBuilder::new(rand_strong_parents()).finish().unwrap(); + let block = BlockBuilder::::new(rand_strong_parents()).finish().unwrap(); let packed_block = block.pack_to_vec(); assert_eq!(packed_block.len(), block.packed_len()); @@ -100,7 +101,7 @@ fn getters() { let payload = Payload::from(rand_tagged_data_payload()); let nonce: u64 = rand_number(); - let block = BlockBuilder::new(parents.clone()) + let block = BlockBuilder::::new(parents.clone()) .with_payload(payload.clone()) .with_nonce(nonce) .finish() @@ -115,7 +116,7 @@ fn getters() { #[test] fn build_into_parents() { let parents = rand_strong_parents(); - let block = Block::build(parents.clone()).finish().unwrap(); + let block = Block::build_basic(parents.clone()).finish().unwrap(); - assert_eq!(block.into_strong_parents(), parents); + assert_eq!(block.strong_parents(), &parents); } From 57a1f63ffc6543888338cd758a67724e26e3b861 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 26 Jul 2023 08:38:41 -0400 Subject: [PATCH 05/57] udep --- Cargo.lock | 1 - sdk/Cargo.toml | 3 --- 2 files changed, 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87741823b7..96b07d7a3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1648,7 +1648,6 @@ dependencies = [ "gloo-storage", "gloo-timers", "hashbrown 0.14.0", - "heck", "hex", "instant", "iota-crypto", diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 8c8310f75e..3178aa10ee 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -60,7 +60,6 @@ fern-logger = { version = "0.5.0", default-features = false, optional = true } futures = { version = "0.3.28", default-features = false, features = [ "thread-pool", ], optional = true } -heck = { version = "0.4.1", default-features = false, optional = true } instant = { version = "0.1.12", default-features = false, optional = true } iota-ledger-nano = { version = "1.0.0-alpha.4", default-features = false, optional = true } iota_stronghold = { version = "2.0.0-rc.2", default-features = false, optional = true } @@ -169,7 +168,6 @@ storage = [ "dep:time", "dep:anymap", "dep:once_cell", - "dep:heck", ] stronghold = [ "iota_stronghold", @@ -178,7 +176,6 @@ stronghold = [ "dep:time", "dep:anymap", "dep:once_cell", - "dep:heck", ] tls = ["reqwest?/rustls-tls", "rumqttc?/use-rustls"] From d5edb2d4bdef86544e1c9940a3e49e79c89a9f54 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 26 Jul 2023 08:44:01 -0400 Subject: [PATCH 06/57] Comment out more tests that will change --- sdk/tests/types/block.rs | 86 ++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/sdk/tests/types/block.rs b/sdk/tests/types/block.rs index cc8a26a366..bdcf891fb9 100644 --- a/sdk/tests/types/block.rs +++ b/sdk/tests/types/block.rs @@ -35,49 +35,49 @@ fn pow_provider() { assert!(score >= min_pow_score as f64); } -#[test] -fn invalid_length() { - let res = BlockBuilder::new(Parents::from_vec(rand_block_ids(2)).unwrap()) - .with_nonce(42) - .with_payload(TaggedDataPayload::new(vec![42], vec![0u8; Block::LENGTH_MAX - Block::LENGTH_MIN - 9]).unwrap()) - .finish(); - - assert!(matches!(res, Err(Error::InvalidBlockLength(len)) if len == Block::LENGTH_MAX + 33)); -} - -#[test] -fn unpack_valid_no_remaining_bytes() { - assert!( - Block::unpack_strict( - vec![ - 2, 2, 140, 28, 186, 52, 147, 145, 96, 9, 105, 89, 78, 139, 3, 71, 249, 97, 149, 190, 63, 238, 168, 202, - 82, 140, 227, 66, 173, 19, 110, 93, 117, 34, 225, 202, 251, 10, 156, 58, 144, 225, 54, 79, 62, 38, 20, - 121, 95, 90, 112, 109, 6, 166, 126, 145, 13, 62, 52, 68, 248, 135, 223, 119, 137, 13, 0, 0, 0, 0, 21, - 205, 91, 7, 0, 0, 0, 0, - ] - .as_slice(), - &protocol_parameters() - ) - .is_ok() - ) -} - -#[test] -fn unpack_invalid_remaining_bytes() { - assert!(matches!( - Block::unpack_strict( - vec![ - 2, 2, 140, 28, 186, 52, 147, 145, 96, 9, 105, 89, 78, 139, 3, 71, 249, 97, 149, 190, 63, 238, 168, 202, - 82, 140, 227, 66, 173, 19, 110, 93, 117, 34, 225, 202, 251, 10, 156, 58, 144, 225, 54, 79, 62, 38, 20, - 121, 95, 90, 112, 109, 6, 166, 126, 145, 13, 62, 52, 68, 248, 135, 223, 119, 137, 13, 0, 0, 0, 0, 21, - 205, 91, 7, 0, 0, 0, 0, 42 - ] - .as_slice(), - &protocol_parameters() - ), - Err(UnpackError::Packable(Error::RemainingBytesAfterBlock)) - )) -} +// #[test] +// fn invalid_length() { +// let res = BlockBuilder::new(Parents::from_vec(rand_block_ids(2)).unwrap()) +// .with_nonce(42) +// .with_payload(TaggedDataPayload::new(vec![42], vec![0u8; Block::LENGTH_MAX - Block::LENGTH_MIN - +// 9]).unwrap()) .finish(); + +// assert!(matches!(res, Err(Error::InvalidBlockLength(len)) if len == Block::LENGTH_MAX + 33)); +// } + +// #[test] +// fn unpack_valid_no_remaining_bytes() { +// assert!( +// Block::unpack_strict( +// vec![ +// 2, 2, 140, 28, 186, 52, 147, 145, 96, 9, 105, 89, 78, 139, 3, 71, 249, 97, 149, 190, 63, 238, 168, +// 202, 82, 140, 227, 66, 173, 19, 110, 93, 117, 34, 225, 202, 251, 10, 156, 58, 144, 225, 54, 79, 62, +// 38, 20, 121, 95, 90, 112, 109, 6, 166, 126, 145, 13, 62, 52, 68, 248, 135, 223, 119, 137, 13, 0, 0, +// 0, 0, 21, 205, 91, 7, 0, 0, 0, 0, +// ] +// .as_slice(), +// &protocol_parameters() +// ) +// .is_ok() +// ) +// } + +// #[test] +// fn unpack_invalid_remaining_bytes() { +// assert!(matches!( +// Block::unpack_strict( +// vec![ +// 2, 2, 140, 28, 186, 52, 147, 145, 96, 9, 105, 89, 78, 139, 3, 71, 249, 97, 149, 190, 63, 238, 168, +// 202, 82, 140, 227, 66, 173, 19, 110, 93, 117, 34, 225, 202, 251, 10, 156, 58, 144, 225, 54, 79, 62, +// 38, 20, 121, 95, 90, 112, 109, 6, 166, 126, 145, 13, 62, 52, 68, 248, 135, 223, 119, 137, 13, 0, 0, +// 0, 0, 21, 205, 91, 7, 0, 0, 0, 0, 42 +// ] +// .as_slice(), +// &protocol_parameters() +// ), +// Err(UnpackError::Packable(Error::RemainingBytesAfterBlock)) +// )) +// } // Validate that a `unpack` ∘ `pack` round-trip results in the original block. #[test] From 24e295df354c630e842a4fded577ad5b0f8a9c5e Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 26 Jul 2023 08:44:25 -0400 Subject: [PATCH 07/57] oop --- sdk/tests/types/block.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sdk/tests/types/block.rs b/sdk/tests/types/block.rs index bdcf891fb9..bff7f6af86 100644 --- a/sdk/tests/types/block.rs +++ b/sdk/tests/types/block.rs @@ -4,16 +4,13 @@ use iota_sdk::{ pow::{miner::get_miner, score::PowScorer}, types::block::{ - parent::Parents, - payload::{Payload, TaggedDataPayload}, + payload::Payload, protocol::protocol_parameters, - rand::{ - block::rand_block_ids, number::rand_number, parents::rand_strong_parents, payload::rand_tagged_data_payload, - }, - Block, BlockBuilder, Error, + rand::{number::rand_number, parents::rand_strong_parents, payload::rand_tagged_data_payload}, + Block, BlockBuilder, }, }; -use packable::{error::UnpackError, PackableExt}; +use packable::PackableExt; #[test] fn default_finish_zero_nonce() { From 53f0d3f560bf820da779b14d8245df9b47fd584a Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 26 Jul 2023 09:49:49 -0400 Subject: [PATCH 08/57] no_std --- sdk/src/types/block/core.rs | 5 ++++- sdk/src/types/block/validation.rs | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 62f3ccafbc..2a1a9c4de3 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -422,7 +422,10 @@ pub(crate) fn verify_parents( } pub(crate) mod dto { - use alloc::string::{String, ToString}; + use alloc::{ + format, + string::{String, ToString}, + }; use serde::{Deserialize, Serialize}; use serde_json::Value; diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs index 0700c96f05..087448e3bc 100644 --- a/sdk/src/types/block/validation.rs +++ b/sdk/src/types/block/validation.rs @@ -1,6 +1,8 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use alloc::string::ToString; + use packable::{ error::{UnpackError, UnpackErrorExt}, packer::Packer, From 4039714768aaf185020561de2ae0cd37e856e919 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 26 Jul 2023 12:22:55 -0400 Subject: [PATCH 09/57] impl more of BlockWrapper --- sdk/Cargo.toml | 1 + sdk/src/client/api/block_builder/pow.rs | 30 ++- sdk/src/types/api/core/response.rs | 18 +- sdk/src/types/block/core.rs | 227 ++++++++++++++++++++--- sdk/src/types/block/signature/ed25519.rs | 2 +- sdk/src/types/block/slot/index.rs | 8 +- 6 files changed, 246 insertions(+), 40 deletions(-) diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 3178aa10ee..9a185e4ba1 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -22,6 +22,7 @@ bech32 = { version = "0.9.1", default-features = false } bitflags = { version = "2.3.3", default-features = false } derive_more = { version = "0.99.17", default-features = false, features = [ "from", + "from_str", "as_ref", "deref", "deref_mut", diff --git a/sdk/src/client/api/block_builder/pow.rs b/sdk/src/client/api/block_builder/pow.rs index 8b0fb3d91f..b850860c00 100644 --- a/sdk/src/client/api/block_builder/pow.rs +++ b/sdk/src/client/api/block_builder/pow.rs @@ -31,9 +31,33 @@ impl ClientInner { None => StrongParents::from_vec(self.get_tips().await?)?, }; - Ok(BlockBuilder::::new(strong_parents) - .with_payload(payload) - .finish()?) + #[cfg(feature = "std")] + let issuing_time = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .expect("Time went backwards") + .as_nanos() as u64; + // TODO no_std way to have a nanosecond timestamp + // https://github.com/iotaledger/iota-sdk/issues/647 + #[cfg(not(feature = "std"))] + let issuing_time = 0; + + let node_info = self.get_info().await?.node_info; + let latest_finalized_slot = node_info.status.latest_finalized_slot; + let slot_commitment_id = self.get_slot_commitment_by_index(latest_finalized_slot).await?.id(); + + let signature = todo!(); + + Ok(Block::build_basic( + self.get_network_id().await?, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + node_info.issuer_id, + strong_parents, + signature, + ) + .with_payload(payload) + .finish()?) } } diff --git a/sdk/src/types/api/core/response.rs b/sdk/src/types/api/core/response.rs index 56d7afafea..af0b33044b 100644 --- a/sdk/src/types/api/core/response.rs +++ b/sdk/src/types/api/core/response.rs @@ -47,19 +47,15 @@ impl core::fmt::Display for InfoResponse { )] pub struct StatusResponse { pub is_healthy: bool, - pub last_accepted_block_id: BlockId, - pub last_confirmed_block_id: BlockId, - pub finalized_slot: SlotIndex, - #[cfg_attr(feature = "serde", serde(rename = "ATT"))] - pub att: u64, - #[cfg_attr(feature = "serde", serde(rename = "RATT"))] - pub ratt: u64, - #[cfg_attr(feature = "serde", serde(rename = "CTT"))] - pub ctt: u64, - #[cfg_attr(feature = "serde", serde(rename = "RCTT"))] - pub rctt: u64, + pub accepted_tangle_time: u64, + pub relative_accepted_tangle_time: u64, + pub confirmed_tangle_time: u64, + pub relative_confirmed_tangle_time: u64, pub latest_committed_slot: SlotIndex, + pub latest_finalized_slot: SlotIndex, pub pruning_slot: SlotIndex, + pub latest_accepted_block_id: BlockId, + pub latest_confirmed_block_id: BlockId, } /// Returned in [`InfoResponse`]. diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 2a1a9c4de3..74bad820b9 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -12,7 +12,13 @@ use packable::{ Packable, PackableExt, }; -use super::{basic::BasicBlock, validation::ValidationBlock}; +use super::{ + basic::BasicBlock, + signature::Ed25519Signature, + slot::{SlotCommitmentId, SlotIndex}, + validation::ValidationBlock, + IssuerId, +}; use crate::types::block::{ parent::{ShallowLikeParents, StrongParents, WeakParents}, payload::{OptionalPayload, Payload}, @@ -25,7 +31,13 @@ use crate::types::block::{ #[must_use] pub struct BlockBuilder { protocol_version: Option, + network_id: u64, + issuing_time: u64, + slot_commitment_id: SlotCommitmentId, + latest_finalized_slot: SlotIndex, + issuer_id: IssuerId, inner: B, + signature: Ed25519Signature, nonce: Option, } @@ -50,9 +62,22 @@ impl BlockBuilder { impl BlockBuilder { /// Creates a new [`BlockBuilder`] for a [`BasicBlock`]. #[inline(always)] - pub fn new(strong_parents: StrongParents) -> Self { + pub fn new( + network_id: u64, + issuing_time: u64, + slot_commitment_id: SlotCommitmentId, + latest_finalized_slot: SlotIndex, + issuer_id: IssuerId, + strong_parents: StrongParents, + signature: Ed25519Signature, + ) -> Self { Self { - protocol_version: None, + protocol_version: Default::default(), + network_id, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + issuer_id, inner: BasicBlock { strong_parents, weak_parents: Default::default(), @@ -60,7 +85,8 @@ impl BlockBuilder { payload: OptionalPayload::default(), burned_mana: Default::default(), }, - nonce: None, + signature, + nonce: Default::default(), } } @@ -97,12 +123,23 @@ impl BlockBuilder { /// Creates a new [`BlockBuilder`] for a [`ValidationBlock`]. #[inline(always)] pub fn new( + network_id: u64, + issuing_time: u64, + slot_commitment_id: SlotCommitmentId, + latest_finalized_slot: SlotIndex, + issuer_id: IssuerId, strong_parents: StrongParents, highest_supported_version: u8, protocol_parameters: &ProtocolParameters, + signature: Ed25519Signature, ) -> Self { Self { - protocol_version: None, + protocol_version: Default::default(), + network_id, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + issuer_id, inner: ValidationBlock { strong_parents, weak_parents: Default::default(), @@ -110,7 +147,8 @@ impl BlockBuilder { highest_supported_version, protocol_parameters_hash: protocol_parameters.hash(), }, - nonce: None, + signature, + nonce: Default::default(), } } @@ -129,17 +167,29 @@ impl BlockBuilder { } } -impl> From for BlockBuilder { - fn from(inner: B) -> Self { +impl> BlockBuilder { + pub fn from_block_type( + network_id: u64, + issuing_time: u64, + slot_commitment_id: SlotCommitmentId, + latest_finalized_slot: SlotIndex, + issuer_id: IssuerId, + inner: B, + signature: Ed25519Signature, + ) -> Self { Self { - protocol_version: None, + protocol_version: Default::default(), + network_id, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + issuer_id, inner, - nonce: None, + signature, + nonce: Default::default(), } } -} -impl> BlockBuilder { fn _finish(self) -> Result<(Block, Vec), Error> { let inner = self.inner.into(); verify_parents( @@ -150,7 +200,13 @@ impl> BlockBuilder { let block = Block { protocol_version: self.protocol_version.unwrap_or(PROTOCOL_VERSION), + network_id: self.network_id, + issuing_time: self.issuing_time, + slot_commitment_id: self.slot_commitment_id, + latest_finalized_slot: self.latest_finalized_slot, + issuer_id: self.issuer_id, inner, + signature: self.signature, nonce: self.nonce.unwrap_or(Self::DEFAULT_NONCE), }; @@ -259,7 +315,20 @@ impl BlockType { pub struct Block { /// Protocol version of the block. protocol_version: u8, + /// Network identifier. + network_id: u64, + /// The time at which the block was issued. It is a Unix timestamp in nanoseconds. + issuing_time: u64, + /// The identifier of the slot to which this block commits. + slot_commitment_id: SlotCommitmentId, + /// The slot index of the latest finalized slot. + latest_finalized_slot: SlotIndex, + /// The identifier of the account that issued this block. + issuer_id: IssuerId, + /// The inner block variant, either [`BasicBlock`] or [`ValidationBlock`]. pub(crate) inner: BlockType, + /// + signature: Ed25519Signature, /// The result of the Proof of Work in order for the block to be accepted into the tangle. nonce: u64, } @@ -272,18 +341,50 @@ impl Block { /// Creates a new [`BlockBuilder`] to construct an instance of a [`BasicBlock`]. #[inline(always)] - pub fn build_basic(strong_parents: StrongParents) -> BlockBuilder { - BlockBuilder::::new(strong_parents) + pub fn build_basic( + network_id: u64, + issuing_time: u64, + slot_commitment_id: SlotCommitmentId, + latest_finalized_slot: SlotIndex, + issuer_id: IssuerId, + strong_parents: StrongParents, + signature: Ed25519Signature, + ) -> BlockBuilder { + BlockBuilder::::new( + network_id, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + issuer_id, + strong_parents, + signature, + ) } /// Creates a new [`BlockBuilder`] to construct an instance of a [`ValidationBlock`]. #[inline(always)] pub fn build_validation( + network_id: u64, + issuing_time: u64, + slot_commitment_id: SlotCommitmentId, + latest_finalized_slot: SlotIndex, + issuer_id: IssuerId, strong_parents: StrongParents, highest_supported_version: u8, protocol_parameters: &ProtocolParameters, + signature: Ed25519Signature, ) -> BlockBuilder { - BlockBuilder::::new(strong_parents, highest_supported_version, protocol_parameters) + BlockBuilder::::new( + network_id, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + issuer_id, + strong_parents, + highest_supported_version, + protocol_parameters, + signature, + ) } /// Returns the protocol version of a [`Block`]. @@ -292,6 +393,36 @@ impl Block { self.protocol_version } + /// Returns the network id of a [`Block`]. + #[inline(always)] + pub fn network_id(&self) -> u64 { + self.network_id + } + + /// Returns the issuing time of a [`Block`]. + #[inline(always)] + pub fn issuing_time(&self) -> u64 { + self.issuing_time + } + + /// Returns the slot commitment ID of a [`Block`]. + #[inline(always)] + pub fn slot_commitment_id(&self) -> SlotCommitmentId { + self.slot_commitment_id + } + + /// Returns the latest finalized slot of a [`Block`]. + #[inline(always)] + pub fn latest_finalized_slot(&self) -> SlotIndex { + self.latest_finalized_slot + } + + /// Returns the issuer ID of a [`Block`]. + #[inline(always)] + pub fn issuer_id(&self) -> IssuerId { + self.issuer_id + } + /// Returns the strong parents of a [`Block`]. #[inline(always)] pub fn strong_parents(&self) -> &StrongParents { @@ -316,6 +447,12 @@ impl Block { self.inner.payload() } + /// Returns the signature of a [`Block`]. + #[inline(always)] + pub fn signature(&self) -> &Ed25519Signature { + &self.signature + } + /// Returns the nonce of a [`Block`]. #[inline(always)] pub fn nonce(&self) -> u64 { @@ -379,13 +516,31 @@ impl Packable for Block { })); } + let network_id = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let issuing_time = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let slot_commitment_id = SlotCommitmentId::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let latest_finalized_slot = SlotIndex::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let issuer_id = IssuerId::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + let inner = BlockType::unpack::<_, VERIFY>(unpacker, visitor)?; + let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; + let nonce = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; let block = Self { protocol_version, + network_id, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + issuer_id, inner, + signature, nonce, }; @@ -431,9 +586,15 @@ pub(crate) mod dto { use serde_json::Value; use super::*; - use crate::types::{ - block::{basic::dto::BasicBlockDto, validation::dto::ValidationBlockDto, Error}, - TryFromDto, ValidationParams, + use crate::{ + types::{ + block::{ + basic::dto::BasicBlockDto, signature::dto::Ed25519SignatureDto, validation::dto::ValidationBlockDto, + Error, + }, + TryFromDto, ValidationParams, + }, + utils::serde::string, }; #[derive(Clone, Debug, Eq, PartialEq, From)] @@ -508,7 +669,15 @@ pub(crate) mod dto { #[serde(rename_all = "camelCase")] pub struct BlockDto { pub protocol_version: u8, + #[serde(with = "string")] + pub network_id: u64, + #[serde(with = "string")] + pub issuing_time: u64, + pub slot_commitment_id: SlotCommitmentId, + pub latest_finalized_slot: SlotIndex, + pub issuer_id: IssuerId, pub inner: BlockTypeDto, + pub signature: Ed25519SignatureDto, pub nonce: String, } @@ -516,7 +685,13 @@ pub(crate) mod dto { fn from(value: &Block) -> Self { Self { protocol_version: value.protocol_version(), + network_id: value.network_id(), + issuing_time: value.issuing_time(), + slot_commitment_id: value.slot_commitment_id(), + latest_finalized_slot: value.latest_finalized_slot(), + issuer_id: value.issuer_id(), inner: value.inner().into(), + signature: value.signature().into(), nonce: value.nonce().to_string(), } } @@ -528,10 +703,18 @@ pub(crate) mod dto { fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { let inner = BlockType::try_from_dto_with_params_inner(dto.inner, params)?; - BlockBuilder::from(inner) - .with_protocol_version(dto.protocol_version) - .with_nonce(dto.nonce.parse::().map_err(|_| Error::InvalidField("nonce"))?) - .finish() + BlockBuilder::from_block_type( + dto.network_id, + dto.issuing_time, + dto.slot_commitment_id, + dto.latest_finalized_slot, + dto.issuer_id, + inner, + Ed25519Signature::try_from(dto.signature)?, + ) + .with_protocol_version(dto.protocol_version) + .with_nonce(dto.nonce.parse::().map_err(|_| Error::InvalidField("nonce"))?) + .finish() } } diff --git a/sdk/src/types/block/signature/ed25519.rs b/sdk/src/types/block/signature/ed25519.rs index 7063d7aeca..0e9dd8dfdf 100644 --- a/sdk/src/types/block/signature/ed25519.rs +++ b/sdk/src/types/block/signature/ed25519.rs @@ -17,7 +17,7 @@ use packable::{ use crate::types::block::{address::Ed25519Address, Error}; /// An Ed25519 signature. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Ed25519Signature { public_key: PublicKey, signature: Signature, diff --git a/sdk/src/types/block/slot/index.rs b/sdk/src/types/block/slot/index.rs index b78ed69ad1..8d92a4f5a1 100644 --- a/sdk/src/types/block/slot/index.rs +++ b/sdk/src/types/block/slot/index.rs @@ -1,13 +1,12 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use derive_more::{Deref, Display, From}; +use derive_more::{Deref, Display, From, FromStr}; /// Timeline is divided into slots, and each slot has a corresponding slot index. /// To calculate the slot index of a timestamp, `genesisTimestamp` and the duration of a slot are needed. /// The slot index of timestamp `ts` is `(ts - genesisTimestamp)/duration + 1`. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, From, Deref, Display, packable::Packable)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, From, Deref, Display, FromStr, packable::Packable)] pub struct SlotIndex(u64); impl SlotIndex { @@ -16,3 +15,6 @@ impl SlotIndex { Self::from(index) } } + +#[cfg(feature = "serde")] +string_serde_impl!(SlotIndex); From 2eea8e1eb0696a3fc165e97d38bb966d37f694f3 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 26 Jul 2023 13:23:37 -0400 Subject: [PATCH 10/57] fix client block builder --- sdk/src/client/api/block_builder/pow.rs | 31 +++++++++++-------- sdk/src/client/api/high_level.rs | 28 ++++++++++++----- sdk/src/client/node_api/core/routes.rs | 20 ++++++++++-- sdk/src/types/api/core/response.rs | 3 +- .../types/api/plugins/participation/mod.rs | 1 + sdk/src/types/block/rand/block.rs | 22 ++++++++----- 6 files changed, 73 insertions(+), 32 deletions(-) diff --git a/sdk/src/client/api/block_builder/pow.rs b/sdk/src/client/api/block_builder/pow.rs index b850860c00..91fad9a044 100644 --- a/sdk/src/client/api/block_builder/pow.rs +++ b/sdk/src/client/api/block_builder/pow.rs @@ -10,7 +10,8 @@ use crate::pow::wasm_miner::{SingleThreadedMiner, SingleThreadedMinerBuilder}; use crate::{ client::{ClientInner, Error, Result}, types::block::{ - basic::BasicBlock, parent::StrongParents, payload::Payload, Block, BlockBuilder, Error as BlockError, + basic::BasicBlock, parent::StrongParents, payload::Payload, signature::Ed25519Signature, Block, BlockBuilder, + Error as BlockError, IssuerId, }, }; @@ -19,6 +20,9 @@ impl ClientInner { /// Without local PoW, it will finish the block with a 0 nonce. pub async fn finish_basic_block_builder( &self, + issuer_id: IssuerId, + signature: Ed25519Signature, + issuing_time: Option, strong_parents: Option, payload: Option, ) -> Result { @@ -31,28 +35,29 @@ impl ClientInner { None => StrongParents::from_vec(self.get_tips().await?)?, }; - #[cfg(feature = "std")] - let issuing_time = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .expect("Time went backwards") - .as_nanos() as u64; - // TODO no_std way to have a nanosecond timestamp - // https://github.com/iotaledger/iota-sdk/issues/647 - #[cfg(not(feature = "std"))] - let issuing_time = 0; + let issuing_time = issuing_time.unwrap_or_else(|| { + #[cfg(feature = "std")] + let issuing_time = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .expect("Time went backwards") + .as_nanos() as u64; + // TODO no_std way to have a nanosecond timestamp + // https://github.com/iotaledger/iota-sdk/issues/647 + #[cfg(not(feature = "std"))] + let issuing_time = 0; + issuing_time + }); let node_info = self.get_info().await?.node_info; let latest_finalized_slot = node_info.status.latest_finalized_slot; let slot_commitment_id = self.get_slot_commitment_by_index(latest_finalized_slot).await?.id(); - let signature = todo!(); - Ok(Block::build_basic( self.get_network_id().await?, issuing_time, slot_commitment_id, latest_finalized_slot, - node_info.issuer_id, + issuer_id, strong_parents, signature, ) diff --git a/sdk/src/client/api/high_level.rs b/sdk/src/client/api/high_level.rs index 51fb9b5f02..7e25839833 100644 --- a/sdk/src/client/api/high_level.rs +++ b/sdk/src/client/api/high_level.rs @@ -235,7 +235,15 @@ impl Client { pub async fn reattach_unchecked(&self, block_id: &BlockId) -> Result<(BlockId, Block)> { // Get the Block object by the BlockID. let block = self.get_block(block_id).await?; - let reattach_block = self.finish_basic_block_builder(None, block.payload().cloned()).await?; + let reattach_block = self + .finish_basic_block_builder( + block.issuer_id(), + *block.signature(), + None, + None, + block.payload().cloned(), + ) + .await?; // Post the modified let block_id = self.post_block_raw(&reattach_block).await?; @@ -267,17 +275,21 @@ impl Client { *tip = *block_id; } + // Get block if we use remote Pow, because the node will change parents and nonce. + let block = self.get_block(&block_id).await?; + let promote_block = self - .finish_basic_block_builder(Some(Parents::from_vec(tips)?), None) + .finish_basic_block_builder( + block.issuer_id(), + *block.signature(), + None, + Some(Parents::from_vec(tips)?), + None, + ) .await?; let block_id = self.post_block_raw(&promote_block).await?; - // Get block if we use remote Pow, because the node will change parents and nonce. - let block = if self.get_local_pow().await { - promote_block - } else { - self.get_block(&block_id).await? - }; + Ok((block_id, block)) } diff --git a/sdk/src/client/node_api/core/routes.rs b/sdk/src/client/node_api/core/routes.rs index b9815f612c..330ca80718 100644 --- a/sdk/src/client/node_api/core/routes.rs +++ b/sdk/src/client/node_api/core/routes.rs @@ -136,7 +136,15 @@ impl ClientInner { self.network_info.write().await.local_pow = true; - let block_res = self.finish_basic_block_builder(None, block.payload().cloned()).await; + let block_res = self + .finish_basic_block_builder( + block.issuer_id(), + *block.signature(), + None, + None, + block.payload().cloned(), + ) + .await; let block_with_local_pow = match block_res { Ok(block) => { // reset local PoW state @@ -190,7 +198,15 @@ impl ClientInner { self.network_info.write().await.local_pow = true; - let block_res = self.finish_basic_block_builder(None, block.payload().cloned()).await; + let block_res = self + .finish_basic_block_builder( + block.issuer_id(), + *block.signature(), + None, + None, + block.payload().cloned(), + ) + .await; let block_with_local_pow = match block_res { Ok(block) => { // reset local PoW state diff --git a/sdk/src/types/api/core/response.rs b/sdk/src/types/api/core/response.rs index af0b33044b..cc0eeddfdf 100644 --- a/sdk/src/types/api/core/response.rs +++ b/sdk/src/types/api/core/response.rs @@ -7,7 +7,7 @@ use crate::types::block::{ output::{dto::OutputDto, OutputId, OutputMetadata, OutputWithMetadata}, protocol::ProtocolParameters, slot::SlotIndex, - BlockId, IssuerId, + BlockId, }; /// Response of GET /api/core/v3/info. @@ -21,7 +21,6 @@ use crate::types::block::{ pub struct InfoResponse { pub name: String, pub version: String, - pub issuer_id: IssuerId, pub status: StatusResponse, pub metrics: MetricsResponse, pub supported_protocol_versions: Vec, diff --git a/sdk/src/types/api/plugins/participation/mod.rs b/sdk/src/types/api/plugins/participation/mod.rs index 46680582a5..9a1e83d645 100644 --- a/sdk/src/types/api/plugins/participation/mod.rs +++ b/sdk/src/types/api/plugins/participation/mod.rs @@ -6,4 +6,5 @@ pub mod error; pub mod responses; +#[allow(non_camel_case_types)] pub mod types; diff --git a/sdk/src/types/block/rand/block.rs b/sdk/src/types/block/rand/block.rs index 4762d0fb43..aabeeba166 100644 --- a/sdk/src/types/block/rand/block.rs +++ b/sdk/src/types/block/rand/block.rs @@ -3,13 +3,13 @@ use alloc::vec::Vec; +use super::signature::rand_ed25519_signature; use crate::types::block::{ - basic::BasicBlock, parent::StrongParents, rand::{ bytes::rand_bytes_array, number::rand_number, parents::rand_strong_parents, payload::rand_payload_for_block, }, - Block, BlockBuilder, BlockId, + Block, BlockId, }; /// Generates a random block id. @@ -26,11 +26,19 @@ pub fn rand_block_ids(len: usize) -> Vec { /// Generates a random basic block with given parents. pub fn rand_basic_block_with_strong_parents(strong_parents: StrongParents) -> Block { - BlockBuilder::::new(strong_parents) - .with_payload(rand_payload_for_block()) - .with_nonce(rand_number::()) - .finish() - .unwrap() + Block::build_basic( + 0, + 0, + rand_bytes_array().into(), + 0.into(), + rand_bytes_array().into(), + strong_parents, + rand_ed25519_signature(), + ) + .with_payload(rand_payload_for_block()) + .with_nonce(rand_number::()) + .finish() + .unwrap() } /// Generates a random block. From 9bd73a6970765b1a5ab186d08cb14c70dd89a14e Mon Sep 17 00:00:00 2001 From: Alexandcoats Date: Thu, 27 Jul 2023 09:59:51 -0400 Subject: [PATCH 11/57] Update sdk/src/types/block/protocol.rs Co-authored-by: Thibault Martinez --- sdk/src/types/block/protocol.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/protocol.rs b/sdk/src/types/block/protocol.rs index 6e9c478931..48dbc5ef33 100644 --- a/sdk/src/types/block/protocol.rs +++ b/sdk/src/types/block/protocol.rs @@ -159,7 +159,7 @@ pub fn protocol_parameters() -> ProtocolParameters { impl_id!( pub ProtocolParametersHash, 32, - "The hash of the protocol parameters for the Highest Supported Version." + "The hash of the protocol parameters." ); #[cfg(feature = "serde")] From aca79620b357187709a46f439cea951c697b3791 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Thu, 27 Jul 2023 10:03:01 -0400 Subject: [PATCH 12/57] PR suggestion --- sdk/src/types/block/error.rs | 62 +++++++++++++++++++++++++------ sdk/src/types/block/validation.rs | 6 +-- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/sdk/src/types/block/error.rs b/sdk/src/types/block/error.rs index 1818b8a97e..c446ec6961 100644 --- a/sdk/src/types/block/error.rs +++ b/sdk/src/types/block/error.rs @@ -9,6 +9,7 @@ use crypto::Error as CryptoError; use prefix_hex::Error as HexError; use primitive_types::U256; +use super::protocol::ProtocolParametersHash; use crate::types::block::{ input::UtxoInput, output::{ @@ -32,19 +33,35 @@ pub enum Error { DuplicateUtxo(UtxoInput), ExpirationUnlockConditionZero, FeaturesNotUniqueSorted, - InputUnlockCountMismatch { input_count: usize, unlock_count: usize }, + InputUnlockCountMismatch { + input_count: usize, + unlock_count: usize, + }, InvalidAddress, InvalidAddressKind(u8), InvalidAccountIndex(>::Error), InvalidStorageDepositAmount(u64), // The above is used by `Packable` to denote out-of-range values. The following denotes the actual amount. - InsufficientStorageDepositAmount { amount: u64, required: u64 }, - StorageDepositReturnExceedsOutputAmount { deposit: u64, amount: u64 }, - InsufficientStorageDepositReturnAmount { deposit: u64, required: u64 }, + InsufficientStorageDepositAmount { + amount: u64, + required: u64, + }, + StorageDepositReturnExceedsOutputAmount { + deposit: u64, + amount: u64, + }, + InsufficientStorageDepositReturnAmount { + deposit: u64, + required: u64, + }, InvalidEssenceKind(u8), InvalidFeatureCount(>::Error), InvalidFeatureKind(u8), - InvalidFoundryOutputSupply { minted: U256, melted: U256, max: U256 }, + InvalidFoundryOutputSupply { + minted: U256, + melted: U256, + max: U256, + }, Hex(HexError), InvalidInputKind(u8), InvalidInputCount(>::Error), @@ -64,8 +81,14 @@ pub enum Error { // InvalidParentCount(>::Error), InvalidParentCount, InvalidPayloadKind(u32), - InvalidPayloadLength { expected: usize, actual: usize }, - InvalidProtocolParametersHash { expected: String, actual: String }, + InvalidPayloadLength { + expected: usize, + actual: usize, + }, + InvalidProtocolParametersHash { + expected: ProtocolParametersHash, + actual: ProtocolParametersHash, + }, InvalidReferenceIndex(>::Error), InvalidSignature, InvalidSignatureKind(u8), @@ -91,19 +114,34 @@ pub enum Error { NativeTokensNotUniqueSorted, NativeTokensNullAmount, NativeTokensOverflow, - NetworkIdMismatch { expected: u64, actual: u64 }, + NetworkIdMismatch { + expected: u64, + actual: u64, + }, NonDisjointParents, NonZeroStateIndexOrFoundryCounter, ParentsNotUniqueSorted, - ProtocolVersionMismatch { expected: u8, actual: u8 }, + ProtocolVersionMismatch { + expected: u8, + actual: u8, + }, RemainingBytesAfterBlock, SelfControlledAccountOutput(AccountId), SelfDepositNft(NftId), - SignaturePublicKeyMismatch { expected: String, actual: String }, + SignaturePublicKeyMismatch { + expected: String, + actual: String, + }, StorageDepositReturnOverflow, TimelockUnlockConditionZero, - UnallowedFeature { index: usize, kind: u8 }, - UnallowedUnlockCondition { index: usize, kind: u8 }, + UnallowedFeature { + index: usize, + kind: u8, + }, + UnallowedUnlockCondition { + index: usize, + kind: u8, + }, UnlockConditionsNotUniqueSorted, UnsupportedOutputKind(u8), DuplicateOutputChain(ChainId), diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs index 087448e3bc..1a8c1fdb04 100644 --- a/sdk/src/types/block/validation.rs +++ b/sdk/src/types/block/validation.rs @@ -1,8 +1,6 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use alloc::string::ToString; - use packable::{ error::{UnpackError, UnpackErrorExt}, packer::Packer, @@ -116,8 +114,8 @@ fn validate_protocol_params_hash(hash: &ProtocolParametersHash, params: &Protoco let params_hash = params.hash(); if hash != ¶ms_hash { return Err(Error::InvalidProtocolParametersHash { - expected: params_hash.to_string(), - actual: hash.to_string(), + expected: params_hash, + actual: *hash, }); } Ok(()) From de3bb5266277f3c9c941d4bc750dca52e51c59b5 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Thu, 27 Jul 2023 10:34:22 -0400 Subject: [PATCH 13/57] no_std --- sdk/src/types/block/core.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 9c23a267fd..12738c27d0 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -1,6 +1,8 @@ // Copyright 2020-2021 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use alloc::vec::Vec; + use crypto::hashes::{blake2b::Blake2b256, Digest}; use derive_more::From; use packable::{ From 4598158a3ae8a9ff6df40239e61ab2841ae23ad0 Mon Sep 17 00:00:00 2001 From: Alexandcoats Date: Thu, 27 Jul 2023 15:26:03 -0400 Subject: [PATCH 14/57] Update sdk/src/types/block/validation.rs Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --- sdk/src/types/block/validation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs index 1a8c1fdb04..81f32265b4 100644 --- a/sdk/src/types/block/validation.rs +++ b/sdk/src/types/block/validation.rs @@ -50,7 +50,7 @@ impl ValidationBlock { &self.shallow_like_parents } - /// Returns the shallow like parents of a [`ValidationBlock`]. + /// Returns the highest supported protocol version of a [`ValidationBlock`]. #[inline(always)] pub fn highest_supported_version(&self) -> u8 { self.highest_supported_version From cbad02b2c98de237bb957bb13323ea434b5f240c Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Thu, 27 Jul 2023 15:27:22 -0400 Subject: [PATCH 15/57] invalid block kind --- sdk/src/types/block/core.rs | 2 +- sdk/src/types/block/error.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 12738c27d0..a96e2efbc1 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -187,7 +187,7 @@ impl Packable for BlockType { Ok(match u8::unpack::<_, VERIFY>(unpacker, &()).coerce()? { BasicBlock::KIND => Self::from(BasicBlock::unpack::<_, VERIFY>(unpacker, visitor).coerce()?), ValidationBlock::KIND => Self::from(ValidationBlock::unpack::<_, VERIFY>(unpacker, visitor).coerce()?), - k => return Err(Error::InvalidOutputKind(k)).map_err(UnpackError::Packable), + k => return Err(Error::InvalidBlockKind(k)).map_err(UnpackError::Packable), }) } } diff --git a/sdk/src/types/block/error.rs b/sdk/src/types/block/error.rs index c446ec6961..395b1a061a 100644 --- a/sdk/src/types/block/error.rs +++ b/sdk/src/types/block/error.rs @@ -40,6 +40,7 @@ pub enum Error { InvalidAddress, InvalidAddressKind(u8), InvalidAccountIndex(>::Error), + InvalidBlockKind(u8), InvalidStorageDepositAmount(u64), // The above is used by `Packable` to denote out-of-range values. The following denotes the actual amount. InsufficientStorageDepositAmount { @@ -183,6 +184,7 @@ impl fmt::Display for Error { Self::InvalidAddressKind(k) => write!(f, "invalid address kind: {k}"), Self::InvalidAccountIndex(index) => write!(f, "invalid account index: {index}"), Self::InvalidBech32Hrp(err) => write!(f, "invalid bech32 hrp: {err}"), + Self::InvalidBlockKind(k) => write!(f, "invalid block kind: {k}"), Self::InvalidStorageDepositAmount(amount) => { write!(f, "invalid storage deposit amount: {amount}") } From 039828c9487606b2ec4a84040b46e65eb455287a Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Fri, 28 Jul 2023 10:23:28 -0400 Subject: [PATCH 16/57] Refactor types so that `Block` is the highest level enum --- sdk/src/client/api/block_builder/mod.rs | 2 +- sdk/src/client/api/high_level.rs | 3 +- sdk/src/types/block/basic.rs | 123 ++++- sdk/src/types/block/core.rs | 523 ++++++++++++--------- sdk/src/types/block/rand/block.rs | 7 +- sdk/src/types/block/validation.rs | 124 ++++- sdk/src/wallet/account/operations/retry.rs | 3 +- 7 files changed, 512 insertions(+), 273 deletions(-) diff --git a/sdk/src/client/api/block_builder/mod.rs b/sdk/src/client/api/block_builder/mod.rs index 5a1274604f..00381423dd 100644 --- a/sdk/src/client/api/block_builder/mod.rs +++ b/sdk/src/client/api/block_builder/mod.rs @@ -7,7 +7,7 @@ pub mod transaction; pub use self::transaction::verify_semantic; use crate::{ client::{ClientInner, Result}, - types::block::{parent::StrongParents, payload::Payload, signature::Ed25519Signature, Block, IssuerId}, + types::block::{core::Block, parent::StrongParents, payload::Payload, signature::Ed25519Signature, IssuerId}, }; impl ClientInner { diff --git a/sdk/src/client/api/high_level.rs b/sdk/src/client/api/high_level.rs index a77ed89e22..b1b2059933 100644 --- a/sdk/src/client/api/high_level.rs +++ b/sdk/src/client/api/high_level.rs @@ -19,6 +19,7 @@ use crate::{ api::core::response::LedgerInclusionState, block::{ address::Bech32Address, + core::Block, input::{Input, UtxoInput, INPUT_COUNT_MAX}, output::OutputWithMetadata, parent::Parents, @@ -26,7 +27,7 @@ use crate::{ transaction::{TransactionEssence, TransactionId}, Payload, }, - Block, BlockId, + BlockId, }, }, utils::unix_timestamp_now, diff --git a/sdk/src/types/block/basic.rs b/sdk/src/types/block/basic.rs index 340a983ac1..e73bba2616 100644 --- a/sdk/src/types/block/basic.rs +++ b/sdk/src/types/block/basic.rs @@ -5,19 +5,23 @@ use packable::{ error::{UnpackError, UnpackErrorExt}, packer::Packer, unpacker::Unpacker, - Packable, + Packable, PackableExt, }; use super::{ - core::verify_parents, + core::{verify_parents, BlockWrapper}, parent::{ShallowLikeParents, StrongParents, WeakParents}, payload::{OptionalPayload, Payload}, protocol::ProtocolParameters, - Error, + signature::Ed25519Signature, + slot::{SlotCommitmentId, SlotIndex}, + Block, Error, IssuerId, }; +pub type BasicBlock = BlockWrapper; + #[derive(Clone, Debug, Eq, PartialEq)] -pub struct BasicBlock { +pub struct BasicBlockData { /// Blocks that are strongly directly approved. pub(crate) strong_parents: StrongParents, /// Blocks that are weakly directly approved. @@ -37,35 +41,35 @@ impl BasicBlock { /// Returns the strong parents of a [`BasicBlock`]. #[inline(always)] pub fn strong_parents(&self) -> &StrongParents { - &self.strong_parents + &self.data.strong_parents } /// Returns the weak parents of a [`BasicBlock`]. #[inline(always)] pub fn weak_parents(&self) -> &WeakParents { - &self.weak_parents + &self.data.weak_parents } /// Returns the shallow like parents of a [`BasicBlock`]. #[inline(always)] pub fn shallow_like_parents(&self) -> &ShallowLikeParents { - &self.shallow_like_parents + &self.data.shallow_like_parents } /// Returns the optional payload of a [`BasicBlock`]. #[inline(always)] pub fn payload(&self) -> Option<&Payload> { - self.payload.as_ref() + self.data.payload.as_ref() } /// Returns the burned mana of a [`BasicBlock`]. #[inline(always)] pub fn burned_mana(&self) -> u64 { - self.burned_mana + self.data.burned_mana } } -impl Packable for BasicBlock { +impl Packable for BasicBlockData { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; @@ -95,14 +99,91 @@ impl Packable for BasicBlock { let burned_mana = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - let block = Self { + Ok(Self { strong_parents, weak_parents, shallow_like_parents, payload, burned_mana, + }) + } +} + +impl Packable for BasicBlock { + type UnpackError = Error; + type UnpackVisitor = ProtocolParameters; + + fn pack(&self, packer: &mut P) -> Result<(), P::Error> { + self.protocol_version.pack(packer)?; + self.network_id.pack(packer)?; + self.issuing_time.pack(packer)?; + self.slot_commitment_id.pack(packer)?; + self.latest_finalized_slot.pack(packer)?; + self.issuer_id.pack(packer)?; + self.data.pack(packer)?; + self.signature.pack(packer)?; + + Ok(()) + } + + fn unpack( + unpacker: &mut U, + visitor: &Self::UnpackVisitor, + ) -> Result> { + let start_opt = unpacker.read_bytes(); + + let protocol_version = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + if VERIFY && protocol_version != visitor.protocol_version() { + return Err(UnpackError::Packable(Error::ProtocolVersionMismatch { + expected: visitor.protocol_version(), + actual: protocol_version, + })); + } + + let network_id = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let issuing_time = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let slot_commitment_id = SlotCommitmentId::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let latest_finalized_slot = SlotIndex::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let issuer_id = IssuerId::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let kind = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + if kind != BasicBlock::KIND { + return Err(Error::InvalidBlockKind(kind)).map_err(UnpackError::Packable); + } + + let data = BasicBlockData::unpack::<_, VERIFY>(unpacker, visitor)?; + + let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; + + let block = Self { + protocol_version, + network_id, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + issuer_id, + data, + signature, }; + if VERIFY { + let block_len = if let (Some(start), Some(end)) = (start_opt, unpacker.read_bytes()) { + end - start + } else { + block.packed_len() + }; + + if block_len > Block::LENGTH_MAX { + return Err(UnpackError::Packable(Error::InvalidBlockLength(block_len))); + } + } + Ok(block) } } @@ -121,7 +202,7 @@ pub(crate) mod dto { /// The block object that nodes gossip around in the network. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] - pub struct BasicBlockDto { + pub struct BasicBlockDataDto { #[serde(rename = "type")] pub kind: u8, pub strong_parents: BTreeSet, @@ -133,21 +214,21 @@ pub(crate) mod dto { pub burned_mana: u64, } - impl From<&BasicBlock> for BasicBlockDto { - fn from(value: &BasicBlock) -> Self { + impl From<&BasicBlockData> for BasicBlockDataDto { + fn from(value: &BasicBlockData) -> Self { Self { kind: BasicBlock::KIND, - strong_parents: value.strong_parents().to_set(), - weak_parents: value.weak_parents().to_set(), - shallow_like_parents: value.shallow_like_parents().to_set(), - payload: value.payload().map(Into::into), - burned_mana: value.burned_mana(), + strong_parents: value.strong_parents.to_set(), + weak_parents: value.weak_parents.to_set(), + shallow_like_parents: value.shallow_like_parents.to_set(), + payload: value.payload.as_ref().map(Into::into), + burned_mana: value.burned_mana, } } } - impl TryFromDto for BasicBlock { - type Dto = BasicBlockDto; + impl TryFromDto for BasicBlockData { + type Dto = BasicBlockDataDto; type Error = Error; fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index c81829f40b..c976fe91e6 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -13,10 +13,10 @@ use packable::{ }; use super::{ - basic::BasicBlock, + basic::{BasicBlock, BasicBlockData}, signature::Ed25519Signature, slot::{SlotCommitmentId, SlotIndex}, - validation::ValidationBlock, + validation::{ValidationBlock, ValidationBlockData}, IssuerId, }; use crate::types::block::{ @@ -36,7 +36,7 @@ pub struct BlockBuilder { slot_commitment_id: SlotCommitmentId, latest_finalized_slot: SlotIndex, issuer_id: IssuerId, - inner: B, + data: B, signature: Ed25519Signature, } @@ -49,7 +49,7 @@ impl BlockBuilder { } } -impl BlockBuilder { +impl BlockBuilder { /// Creates a new [`BlockBuilder`] for a [`BasicBlock`]. #[inline(always)] pub fn new( @@ -68,7 +68,7 @@ impl BlockBuilder { slot_commitment_id, latest_finalized_slot, issuer_id, - inner: BasicBlock { + data: BasicBlockData { strong_parents, weak_parents: Default::default(), shallow_like_parents: Default::default(), @@ -82,33 +82,33 @@ impl BlockBuilder { /// Adds weak parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { - self.inner.weak_parents = weak_parents.into(); + self.data.weak_parents = weak_parents.into(); self } /// Adds shallow like parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { - self.inner.shallow_like_parents = shallow_like_parents.into(); + self.data.shallow_like_parents = shallow_like_parents.into(); self } /// Adds a payload to a [`BlockBuilder`]. #[inline(always)] pub fn with_payload(mut self, payload: impl Into) -> Self { - self.inner.payload = payload.into(); + self.data.payload = payload.into(); self } /// Adds burned mana to a [`BlockBuilder`]. #[inline(always)] pub fn with_burned_mana(mut self, burned_mana: u64) -> Self { - self.inner.burned_mana = burned_mana; + self.data.burned_mana = burned_mana; self } } -impl BlockBuilder { +impl BlockBuilder { /// Creates a new [`BlockBuilder`] for a [`ValidationBlock`]. #[inline(always)] pub fn new( @@ -129,7 +129,7 @@ impl BlockBuilder { slot_commitment_id, latest_finalized_slot, issuer_id, - inner: ValidationBlock { + data: ValidationBlockData { strong_parents, weak_parents: Default::default(), shallow_like_parents: Default::default(), @@ -143,26 +143,26 @@ impl BlockBuilder { /// Adds weak parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { - self.inner.weak_parents = weak_parents.into(); + self.data.weak_parents = weak_parents.into(); self } /// Adds shallow like parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { - self.inner.shallow_like_parents = shallow_like_parents.into(); + self.data.shallow_like_parents = shallow_like_parents.into(); self } } -impl> BlockBuilder { - pub fn from_block_type( +impl BlockBuilder { + pub fn from_block_data( network_id: u64, issuing_time: u64, slot_commitment_id: SlotCommitmentId, latest_finalized_slot: SlotIndex, issuer_id: IssuerId, - inner: B, + data: B, signature: Ed25519Signature, ) -> Self { Self { @@ -172,29 +172,34 @@ impl> BlockBuilder { slot_commitment_id, latest_finalized_slot, issuer_id, - inner, + data, signature, } } +} +impl BlockBuilder +where + BlockWrapper: Packable, + Block: From>, +{ fn _finish(self) -> Result<(Block, Vec), Error> { - let inner = self.inner.into(); - verify_parents( - inner.strong_parents(), - inner.weak_parents(), - inner.shallow_like_parents(), - )?; - - let block = Block { + let block = Block::from(BlockWrapper { protocol_version: self.protocol_version.unwrap_or(PROTOCOL_VERSION), network_id: self.network_id, issuing_time: self.issuing_time, slot_commitment_id: self.slot_commitment_id, latest_finalized_slot: self.latest_finalized_slot, issuer_id: self.issuer_id, - inner, + data: self.data, signature: self.signature, - }; + }); + + verify_parents( + block.strong_parents(), + block.weak_parents(), + block.shallow_like_parents(), + )?; let block_bytes = block.pack_to_vec(); @@ -212,25 +217,19 @@ impl> BlockBuilder { } #[derive(Clone, Debug, Eq, PartialEq, From)] -pub enum BlockType { +pub enum Block { Basic(BasicBlock), Validation(ValidationBlock), } -impl Packable for BlockType { +impl Packable for Block { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; fn pack(&self, packer: &mut P) -> Result<(), P::Error> { match self { - Self::Basic(block) => { - BasicBlock::KIND.pack(packer)?; - block.pack(packer) - } - Self::Validation(block) => { - ValidationBlock::KIND.pack(packer)?; - block.pack(packer) - } + Self::Basic(block) => block.pack(packer), + Self::Validation(block) => block.pack(packer), }?; Ok(()) @@ -240,71 +239,141 @@ impl Packable for BlockType { unpacker: &mut U, visitor: &Self::UnpackVisitor, ) -> Result> { - Ok(match u8::unpack::<_, VERIFY>(unpacker, &()).coerce()? { - BasicBlock::KIND => Self::from(BasicBlock::unpack::<_, VERIFY>(unpacker, visitor).coerce()?), - ValidationBlock::KIND => Self::from(ValidationBlock::unpack::<_, VERIFY>(unpacker, visitor).coerce()?), - k => return Err(Error::InvalidBlockKind(k)).map_err(UnpackError::Packable), - }) - } -} + let start_opt = unpacker.read_bytes(); -impl BlockType { - /// Returns the strong parents of a [`BlockType`]. - #[inline(always)] - pub fn strong_parents(&self) -> &StrongParents { - match self { - Self::Basic(b) => b.strong_parents(), - Self::Validation(b) => b.strong_parents(), - } - } + let protocol_version = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - /// Returns the weak parents of a [`BlockType`]. - #[inline(always)] - pub fn weak_parents(&self) -> &WeakParents { - match self { - Self::Basic(b) => b.weak_parents(), - Self::Validation(b) => b.weak_parents(), + if VERIFY && protocol_version != visitor.protocol_version() { + return Err(UnpackError::Packable(Error::ProtocolVersionMismatch { + expected: visitor.protocol_version(), + actual: protocol_version, + })); } - } - /// Returns the shallow like parents of a [`BlockType`]. - #[inline(always)] - pub fn shallow_like_parents(&self) -> &ShallowLikeParents { - match self { - Self::Basic(b) => b.shallow_like_parents(), - Self::Validation(b) => b.shallow_like_parents(), - } - } + let network_id = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - /// Returns the optional payload of a [`Block`]. - #[inline(always)] - pub fn payload(&self) -> Option<&Payload> { - match self { - Self::Basic(b) => b.payload(), - Self::Validation(_) => None, + let issuing_time = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let slot_commitment_id = SlotCommitmentId::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let latest_finalized_slot = SlotIndex::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let issuer_id = IssuerId::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let kind = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let block = match kind { + BasicBlock::KIND => { + let data = BasicBlockData::unpack::<_, VERIFY>(unpacker, visitor)?; + let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; + + Block::from(BlockWrapper { + protocol_version, + network_id, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + issuer_id, + data, + signature, + }) + } + ValidationBlock::KIND => { + let data = ValidationBlockData::unpack::<_, VERIFY>(unpacker, visitor)?; + let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; + + Block::from(BlockWrapper { + protocol_version, + network_id, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + issuer_id, + data, + signature, + }) + } + }; + + if VERIFY { + let block_len = if let (Some(start), Some(end)) = (start_opt, unpacker.read_bytes()) { + end - start + } else { + block.packed_len() + }; + + if block_len > Block::LENGTH_MAX { + return Err(UnpackError::Packable(Error::InvalidBlockLength(block_len))); + } } + + Ok(block) } } /// Represent the object that nodes gossip around the network. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Block { +pub struct BlockWrapper { /// Protocol version of the block. - protocol_version: u8, + pub(crate) protocol_version: u8, /// Network identifier. - network_id: u64, + pub(crate) network_id: u64, /// The time at which the block was issued. It is a Unix timestamp in nanoseconds. - issuing_time: u64, + pub(crate) issuing_time: u64, /// The identifier of the slot to which this block commits. - slot_commitment_id: SlotCommitmentId, + pub(crate) slot_commitment_id: SlotCommitmentId, /// The slot index of the latest finalized slot. - latest_finalized_slot: SlotIndex, + pub(crate) latest_finalized_slot: SlotIndex, /// The identifier of the account that issued this block. - issuer_id: IssuerId, - /// The inner block variant, either [`BasicBlock`] or [`ValidationBlock`]. - pub(crate) inner: BlockType, + pub(crate) issuer_id: IssuerId, + /// The inner block data, either [`BasicBlock`] or [`ValidationBlock`]. + pub(crate) data: B, /// - signature: Ed25519Signature, + pub(crate) signature: Ed25519Signature, +} + +impl BlockWrapper { + /// Returns the protocol version of a [`Block`]. + #[inline(always)] + pub fn protocol_version(&self) -> u8 { + self.protocol_version + } + + /// Returns the network id of a [`Block`]. + #[inline(always)] + pub fn network_id(&self) -> u64 { + self.network_id + } + + /// Returns the issuing time of a [`Block`]. + #[inline(always)] + pub fn issuing_time(&self) -> u64 { + self.issuing_time + } + + /// Returns the slot commitment ID of a [`Block`]. + #[inline(always)] + pub fn slot_commitment_id(&self) -> SlotCommitmentId { + self.slot_commitment_id + } + + /// Returns the latest finalized slot of a [`Block`]. + #[inline(always)] + pub fn latest_finalized_slot(&self) -> SlotIndex { + self.latest_finalized_slot + } + + /// Returns the issuer ID of a [`Block`]. + #[inline(always)] + pub fn issuer_id(&self) -> IssuerId { + self.issuer_id + } + + /// Returns the signature of a [`Block`]. + #[inline(always)] + pub fn signature(&self) -> &Ed25519Signature { + &self.signature + } } impl Block { @@ -323,8 +392,8 @@ impl Block { issuer_id: IssuerId, strong_parents: StrongParents, signature: Ed25519Signature, - ) -> BlockBuilder { - BlockBuilder::::new( + ) -> BlockBuilder { + BlockBuilder::::new( network_id, issuing_time, slot_commitment_id, @@ -347,8 +416,8 @@ impl Block { highest_supported_version: u8, protocol_parameters: &ProtocolParameters, signature: Ed25519Signature, - ) -> BlockBuilder { - BlockBuilder::::new( + ) -> BlockBuilder { + BlockBuilder::::new( network_id, issuing_time, slot_commitment_id, @@ -364,73 +433,130 @@ impl Block { /// Returns the protocol version of a [`Block`]. #[inline(always)] pub fn protocol_version(&self) -> u8 { - self.protocol_version + match self { + Self::Basic(b) => b.protocol_version(), + Self::Validation(b) => b.protocol_version(), + } } /// Returns the network id of a [`Block`]. #[inline(always)] pub fn network_id(&self) -> u64 { - self.network_id + match self { + Self::Basic(b) => b.network_id(), + Self::Validation(b) => b.network_id(), + } } /// Returns the issuing time of a [`Block`]. #[inline(always)] pub fn issuing_time(&self) -> u64 { - self.issuing_time + match self { + Self::Basic(b) => b.issuing_time(), + Self::Validation(b) => b.issuing_time(), + } } /// Returns the slot commitment ID of a [`Block`]. #[inline(always)] pub fn slot_commitment_id(&self) -> SlotCommitmentId { - self.slot_commitment_id + match self { + Self::Basic(b) => b.slot_commitment_id(), + Self::Validation(b) => b.slot_commitment_id(), + } } /// Returns the latest finalized slot of a [`Block`]. #[inline(always)] pub fn latest_finalized_slot(&self) -> SlotIndex { - self.latest_finalized_slot + match self { + Self::Basic(b) => b.latest_finalized_slot(), + Self::Validation(b) => b.latest_finalized_slot(), + } } /// Returns the issuer ID of a [`Block`]. #[inline(always)] pub fn issuer_id(&self) -> IssuerId { - self.issuer_id + match self { + Self::Basic(b) => b.issuer_id(), + Self::Validation(b) => b.issuer_id(), + } } - /// Returns the strong parents of a [`Block`]. + /// Returns the strong parents of a [`BlockType`]. #[inline(always)] pub fn strong_parents(&self) -> &StrongParents { - self.inner.strong_parents() + match self { + Self::Basic(b) => b.strong_parents(), + Self::Validation(b) => b.strong_parents(), + } } - /// Returns the weak parents of a [`Block`]. + /// Returns the weak parents of a [`BlockType`]. #[inline(always)] pub fn weak_parents(&self) -> &WeakParents { - self.inner.weak_parents() + match self { + Self::Basic(b) => b.weak_parents(), + Self::Validation(b) => b.weak_parents(), + } } - /// Returns the shallow like parents of a [`Block`]. + /// Returns the shallow like parents of a [`BlockType`]. #[inline(always)] pub fn shallow_like_parents(&self) -> &ShallowLikeParents { - self.inner.shallow_like_parents() + match self { + Self::Basic(b) => b.shallow_like_parents(), + Self::Validation(b) => b.shallow_like_parents(), + } } /// Returns the optional payload of a [`Block`]. #[inline(always)] pub fn payload(&self) -> Option<&Payload> { - self.inner.payload() + match self { + Self::Basic(b) => b.payload(), + Self::Validation(_) => None, + } } /// Returns the signature of a [`Block`]. #[inline(always)] pub fn signature(&self) -> &Ed25519Signature { - &self.signature + match self { + Self::Basic(b) => b.signature(), + Self::Validation(b) => b.signature(), + } } - /// Returns the inner block type of a [`Block`]. - #[inline(always)] - pub fn inner(&self) -> &BlockType { - &self.inner + /// Gets the block as an actual [`BasicBlock`]. + /// PANIC: do not call on a non-basic block. + pub fn as_basic(&self) -> &BasicBlock { + if let Self::Basic(block) = self { + block + } else { + panic!("as_basic called on a non-basic block"); + } + } + + /// Checks whether the block is a [`BasicBlock`]. + pub fn is_basic(&self) -> bool { + matches!(self, Self::Basic(_)) + } + + /// Gets the block as an actual [`BasicBlock`]. + /// PANIC: do not call on a non-basic block. + pub fn as_validation(&self) -> &ValidationBlock { + if let Self::Validation(block) = self { + block + } else { + panic!("as_validation called on a non-validation block"); + } + } + + /// Checks whether the block is a [`ValidationBlock`]. + pub fn is_validation(&self) -> bool { + matches!(self, Self::Validation(_)) } /// Computes the identifier of the block. @@ -457,73 +583,6 @@ impl Block { } } -impl Packable for Block { - type UnpackError = Error; - type UnpackVisitor = ProtocolParameters; - - fn pack(&self, packer: &mut P) -> Result<(), P::Error> { - self.protocol_version.pack(packer)?; - self.inner.pack(packer)?; - - Ok(()) - } - - fn unpack( - unpacker: &mut U, - visitor: &Self::UnpackVisitor, - ) -> Result> { - let start_opt = unpacker.read_bytes(); - - let protocol_version = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - - if VERIFY && protocol_version != visitor.protocol_version() { - return Err(UnpackError::Packable(Error::ProtocolVersionMismatch { - expected: visitor.protocol_version(), - actual: protocol_version, - })); - } - - let network_id = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - - let issuing_time = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - - let slot_commitment_id = SlotCommitmentId::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - - let latest_finalized_slot = SlotIndex::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - - let issuer_id = IssuerId::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - - let inner = BlockType::unpack::<_, VERIFY>(unpacker, visitor)?; - - let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; - - let block = Self { - protocol_version, - network_id, - issuing_time, - slot_commitment_id, - latest_finalized_slot, - issuer_id, - inner, - signature, - }; - - if VERIFY { - let block_len = if let (Some(start), Some(end)) = (start_opt, unpacker.read_bytes()) { - end - start - } else { - block.packed_len() - }; - - if block_len > Self::LENGTH_MAX { - return Err(UnpackError::Packable(Error::InvalidBlockLength(block_len))); - } - } - - Ok(block) - } -} - pub(crate) fn verify_parents( strong_parents: &StrongParents, weak_parents: &WeakParents, @@ -550,8 +609,8 @@ pub(crate) mod dto { use crate::{ types::{ block::{ - basic::dto::BasicBlockDto, signature::dto::Ed25519SignatureDto, validation::dto::ValidationBlockDto, - Error, + basic::dto::BasicBlockDataDto, signature::dto::Ed25519SignatureDto, + validation::dto::ValidationBlockDataDto, Error, }, TryFromDto, ValidationParams, }, @@ -559,21 +618,24 @@ pub(crate) mod dto { }; #[derive(Clone, Debug, Eq, PartialEq, From)] - pub enum BlockTypeDto { - Basic(BasicBlockDto), - Validation(ValidationBlockDto), + pub enum BlockDataDto { + Basic(BasicBlockDataDto), + Validation(ValidationBlockDataDto), } - impl From<&BlockType> for BlockTypeDto { - fn from(value: &BlockType) -> Self { - match value { - BlockType::Basic(b) => Self::Basic(b.into()), - BlockType::Validation(b) => Self::Validation(b.into()), - } + impl From<&BasicBlockData> for BlockDataDto { + fn from(value: &BasicBlockData) -> Self { + Self::Basic(value.into()) + } + } + + impl From<&ValidationBlockData> for BlockDataDto { + fn from(value: &ValidationBlockData) -> Self { + Self::Validation(value.into()) } } - impl<'de> Deserialize<'de> for BlockTypeDto { + impl<'de> Deserialize<'de> for BlockDataDto { fn deserialize>(d: D) -> Result { let value = Value::deserialize(d)?; Ok( @@ -583,11 +645,11 @@ pub(crate) mod dto { .ok_or_else(|| serde::de::Error::custom("invalid block type"))? as u8 { BasicBlock::KIND => Self::Basic( - BasicBlockDto::deserialize(value) + BasicBlockDataDto::deserialize(value) .map_err(|e| serde::de::Error::custom(format!("cannot deserialize basic block: {e}")))?, ), ValidationBlock::KIND => { - Self::Validation(ValidationBlockDto::deserialize(value).map_err(|e| { + Self::Validation(ValidationBlockDataDto::deserialize(value).map_err(|e| { serde::de::Error::custom(format!("cannot deserialize validation block: {e}")) })?) } @@ -597,7 +659,7 @@ pub(crate) mod dto { } } - impl Serialize for BlockTypeDto { + impl Serialize for BlockDataDto { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -605,8 +667,8 @@ pub(crate) mod dto { #[derive(Serialize)] #[serde(untagged)] enum BlockTypeDto_<'a> { - T0(&'a BasicBlockDto), - T1(&'a ValidationBlockDto), + T0(&'a BasicBlockDataDto), + T1(&'a ValidationBlockDataDto), } #[derive(Serialize)] struct TypedBlock<'a> { @@ -637,21 +699,34 @@ pub(crate) mod dto { pub slot_commitment_id: SlotCommitmentId, pub latest_finalized_slot: SlotIndex, pub issuer_id: IssuerId, - pub inner: BlockTypeDto, + #[serde(flatten)] + pub data: BlockDataDto, pub signature: Ed25519SignatureDto, } impl From<&Block> for BlockDto { fn from(value: &Block) -> Self { - Self { - protocol_version: value.protocol_version(), - network_id: value.network_id(), - issuing_time: value.issuing_time(), - slot_commitment_id: value.slot_commitment_id(), - latest_finalized_slot: value.latest_finalized_slot(), - issuer_id: value.issuer_id(), - inner: value.inner().into(), - signature: value.signature().into(), + match value { + Block::Basic(b) => Self { + protocol_version: b.protocol_version(), + network_id: b.network_id(), + issuing_time: b.issuing_time(), + slot_commitment_id: b.slot_commitment_id(), + latest_finalized_slot: b.latest_finalized_slot(), + issuer_id: b.issuer_id(), + data: (&b.data).into(), + signature: b.signature().into(), + }, + Block::Validation(b) => Self { + protocol_version: b.protocol_version(), + network_id: b.network_id(), + issuing_time: b.issuing_time(), + slot_commitment_id: b.slot_commitment_id(), + latest_finalized_slot: b.latest_finalized_slot(), + issuer_id: b.issuer_id(), + data: (&b.data).into(), + signature: b.signature().into(), + }, } } } @@ -661,30 +736,30 @@ pub(crate) mod dto { type Error = Error; fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { - let inner = BlockType::try_from_dto_with_params_inner(dto.inner, params)?; - BlockBuilder::from_block_type( - dto.network_id, - dto.issuing_time, - dto.slot_commitment_id, - dto.latest_finalized_slot, - dto.issuer_id, - inner, - Ed25519Signature::try_from(dto.signature)?, - ) - .with_protocol_version(dto.protocol_version) - .finish() - } - } - - impl TryFromDto for BlockType { - type Dto = BlockTypeDto; - type Error = Error; - - fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { - Ok(match dto { - BlockTypeDto::Basic(b) => Self::Basic(BasicBlock::try_from_dto_with_params(b, ¶ms)?), - BlockTypeDto::Validation(b) => Self::Validation(ValidationBlock::try_from_dto_with_params(b, ¶ms)?), - }) + match dto.data { + BlockDataDto::Basic(b) => BlockBuilder::from_block_data( + dto.network_id, + dto.issuing_time, + dto.slot_commitment_id, + dto.latest_finalized_slot, + dto.issuer_id, + BasicBlockData::try_from_dto_with_params_inner(b, params)?, + Ed25519Signature::try_from(dto.signature)?, + ) + .with_protocol_version(dto.protocol_version) + .finish(), + BlockDataDto::Validation(b) => BlockBuilder::from_block_data( + dto.network_id, + dto.issuing_time, + dto.slot_commitment_id, + dto.latest_finalized_slot, + dto.issuer_id, + ValidationBlockData::try_from_dto_with_params_inner(b, params)?, + Ed25519Signature::try_from(dto.signature)?, + ) + .with_protocol_version(dto.protocol_version) + .finish(), + } } } } diff --git a/sdk/src/types/block/rand/block.rs b/sdk/src/types/block/rand/block.rs index 6f6929ee85..ced637ce8d 100644 --- a/sdk/src/types/block/rand/block.rs +++ b/sdk/src/types/block/rand/block.rs @@ -5,12 +5,13 @@ use alloc::vec::Vec; use super::signature::rand_ed25519_signature; use crate::types::block::{ - basic::BasicBlock, + basic::BasicBlockData, + core::Block, parent::StrongParents, rand::{ bytes::rand_bytes_array, number::rand_number, parents::rand_strong_parents, payload::rand_payload_for_block, }, - Block, BlockBuilder, BlockId, + BlockBuilder, BlockId, }; /// Generates a random block id. @@ -34,7 +35,7 @@ pub fn rand_basic_block_with_strong_parents(strong_parents: StrongParents) -> Bl } /// Generates a random basic block builder with given parents. -pub fn rand_basic_block_builder_with_strong_parents(strong_parents: StrongParents) -> BlockBuilder { +pub fn rand_basic_block_builder_with_strong_parents(strong_parents: StrongParents) -> BlockBuilder { Block::build_basic( rand_number(), rand_number(), diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs index 81f32265b4..938c58671f 100644 --- a/sdk/src/types/block/validation.rs +++ b/sdk/src/types/block/validation.rs @@ -5,18 +5,22 @@ use packable::{ error::{UnpackError, UnpackErrorExt}, packer::Packer, unpacker::Unpacker, - Packable, + Packable, PackableExt, }; use super::{ - core::verify_parents, + core::{verify_parents, BlockWrapper}, parent::{ShallowLikeParents, StrongParents, WeakParents}, protocol::{ProtocolParameters, ProtocolParametersHash}, - Error, + signature::Ed25519Signature, + slot::{SlotCommitmentId, SlotIndex}, + Block, Error, IssuerId, }; +pub type ValidationBlock = BlockWrapper; + #[derive(Clone, Debug, Eq, PartialEq)] -pub struct ValidationBlock { +pub struct ValidationBlockData { /// Blocks that are strongly directly approved. pub(crate) strong_parents: StrongParents, /// Blocks that are weakly directly approved. @@ -35,35 +39,35 @@ impl ValidationBlock { /// Returns the strong parents of a [`ValidationBlock`]. #[inline(always)] pub fn strong_parents(&self) -> &StrongParents { - &self.strong_parents + &self.data.strong_parents } /// Returns the weak parents of a [`ValidationBlock`]. #[inline(always)] pub fn weak_parents(&self) -> &WeakParents { - &self.weak_parents + &self.data.weak_parents } /// Returns the shallow like parents of a [`ValidationBlock`]. #[inline(always)] pub fn shallow_like_parents(&self) -> &ShallowLikeParents { - &self.shallow_like_parents + &self.data.shallow_like_parents } /// Returns the highest supported protocol version of a [`ValidationBlock`]. #[inline(always)] pub fn highest_supported_version(&self) -> u8 { - self.highest_supported_version + self.data.highest_supported_version } /// Returns the protocol parameters hash of a [`ValidationBlock`]. #[inline(always)] pub fn protocol_parameters_hash(&self) -> ProtocolParametersHash { - self.protocol_parameters_hash + self.data.protocol_parameters_hash } } -impl Packable for ValidationBlock { +impl Packable for ValidationBlockData { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; @@ -73,7 +77,6 @@ impl Packable for ValidationBlock { self.shallow_like_parents.pack(packer)?; self.highest_supported_version.pack(packer)?; self.protocol_parameters_hash.pack(packer)?; - Ok(()) } @@ -98,14 +101,91 @@ impl Packable for ValidationBlock { validate_protocol_params_hash(&protocol_parameters_hash, visitor).map_err(UnpackError::Packable)?; } - let block = Self { + Ok(Self { strong_parents, weak_parents, shallow_like_parents, highest_supported_version, protocol_parameters_hash, + }) + } +} + +impl Packable for ValidationBlock { + type UnpackError = Error; + type UnpackVisitor = ProtocolParameters; + + fn pack(&self, packer: &mut P) -> Result<(), P::Error> { + self.protocol_version.pack(packer)?; + self.network_id.pack(packer)?; + self.issuing_time.pack(packer)?; + self.slot_commitment_id.pack(packer)?; + self.latest_finalized_slot.pack(packer)?; + self.issuer_id.pack(packer)?; + self.data.pack(packer)?; + self.signature.pack(packer)?; + + Ok(()) + } + + fn unpack( + unpacker: &mut U, + visitor: &Self::UnpackVisitor, + ) -> Result> { + let start_opt = unpacker.read_bytes(); + + let protocol_version = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + if VERIFY && protocol_version != visitor.protocol_version() { + return Err(UnpackError::Packable(Error::ProtocolVersionMismatch { + expected: visitor.protocol_version(), + actual: protocol_version, + })); + } + + let network_id = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let issuing_time = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let slot_commitment_id = SlotCommitmentId::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let latest_finalized_slot = SlotIndex::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let issuer_id = IssuerId::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + let kind = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?; + + if kind != ValidationBlock::KIND { + return Err(Error::InvalidBlockKind(kind)).map_err(UnpackError::Packable); + } + + let data = ValidationBlockData::unpack::<_, VERIFY>(unpacker, visitor)?; + + let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; + + let block = Self { + protocol_version, + network_id, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + issuer_id, + data, + signature, }; + if VERIFY { + let block_len = if let (Some(start), Some(end)) = (start_opt, unpacker.read_bytes()) { + end - start + } else { + block.packed_len() + }; + + if block_len > Block::LENGTH_MAX { + return Err(UnpackError::Packable(Error::InvalidBlockLength(block_len))); + } + } + Ok(block) } } @@ -135,7 +215,7 @@ pub(crate) mod dto { /// The block object that nodes gossip around in the network. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] - pub struct ValidationBlockDto { + pub struct ValidationBlockDataDto { #[serde(rename = "type")] pub kind: u8, pub strong_parents: BTreeSet, @@ -145,21 +225,21 @@ pub(crate) mod dto { pub protocol_parameters_hash: ProtocolParametersHash, } - impl From<&ValidationBlock> for ValidationBlockDto { - fn from(value: &ValidationBlock) -> Self { + impl From<&ValidationBlockData> for ValidationBlockDataDto { + fn from(value: &ValidationBlockData) -> Self { Self { kind: ValidationBlock::KIND, - strong_parents: value.strong_parents().to_set(), - weak_parents: value.weak_parents().to_set(), - shallow_like_parents: value.shallow_like_parents().to_set(), - highest_supported_version: value.highest_supported_version(), - protocol_parameters_hash: value.protocol_parameters_hash(), + strong_parents: value.strong_parents.to_set(), + weak_parents: value.weak_parents.to_set(), + shallow_like_parents: value.shallow_like_parents.to_set(), + highest_supported_version: value.highest_supported_version, + protocol_parameters_hash: value.protocol_parameters_hash, } } } - impl TryFromDto for ValidationBlock { - type Dto = ValidationBlockDto; + impl TryFromDto for ValidationBlockData { + type Dto = ValidationBlockDataDto; type Error = Error; fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { diff --git a/sdk/src/wallet/account/operations/retry.rs b/sdk/src/wallet/account/operations/retry.rs index b3751cdc95..8862ba252b 100644 --- a/sdk/src/wallet/account/operations/retry.rs +++ b/sdk/src/wallet/account/operations/retry.rs @@ -6,8 +6,9 @@ use crate::{ types::{ api::core::response::LedgerInclusionState, block::{ + core::Block, payload::{transaction::TransactionId, Payload}, - Block, BlockId, + BlockId, }, }, wallet::{ From 3f6317ddc90388f58a1a2ce6426141cc440d1ea0 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Fri, 28 Jul 2023 10:35:59 -0400 Subject: [PATCH 17/57] small improvements --- sdk/src/types/block/core.rs | 93 +++++++++++++------------------ sdk/src/types/block/rand/block.rs | 4 +- 2 files changed, 42 insertions(+), 55 deletions(-) diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index c976fe91e6..9663b61ded 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -29,27 +29,9 @@ use crate::types::block::{ /// A builder to build a [`Block`]. #[derive(Clone)] #[must_use] -pub struct BlockBuilder { - protocol_version: Option, - network_id: u64, - issuing_time: u64, - slot_commitment_id: SlotCommitmentId, - latest_finalized_slot: SlotIndex, - issuer_id: IssuerId, - data: B, - signature: Ed25519Signature, -} - -impl BlockBuilder { - /// Adds a protocol version to a [`BlockBuilder`]. - #[inline(always)] - pub fn with_protocol_version(mut self, protocol_version: impl Into>) -> Self { - self.protocol_version = protocol_version.into(); - self - } -} +pub struct BlockBuilder(B); -impl BlockBuilder { +impl BlockBuilder { /// Creates a new [`BlockBuilder`] for a [`BasicBlock`]. #[inline(always)] pub fn new( @@ -61,8 +43,8 @@ impl BlockBuilder { strong_parents: StrongParents, signature: Ed25519Signature, ) -> Self { - Self { - protocol_version: Default::default(), + Self(BlockWrapper { + protocol_version: PROTOCOL_VERSION, network_id, issuing_time, slot_commitment_id, @@ -76,39 +58,46 @@ impl BlockBuilder { burned_mana: Default::default(), }, signature, - } + }) + } + + /// Adds a protocol version to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_protocol_version(mut self, protocol_version: u8) -> Self { + self.0.protocol_version = protocol_version; + self } /// Adds weak parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { - self.data.weak_parents = weak_parents.into(); + self.0.data.weak_parents = weak_parents.into(); self } /// Adds shallow like parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { - self.data.shallow_like_parents = shallow_like_parents.into(); + self.0.data.shallow_like_parents = shallow_like_parents.into(); self } /// Adds a payload to a [`BlockBuilder`]. #[inline(always)] pub fn with_payload(mut self, payload: impl Into) -> Self { - self.data.payload = payload.into(); + self.0.data.payload = payload.into(); self } /// Adds burned mana to a [`BlockBuilder`]. #[inline(always)] pub fn with_burned_mana(mut self, burned_mana: u64) -> Self { - self.data.burned_mana = burned_mana; + self.0.data.burned_mana = burned_mana; self } } -impl BlockBuilder { +impl BlockBuilder { /// Creates a new [`BlockBuilder`] for a [`ValidationBlock`]. #[inline(always)] pub fn new( @@ -122,8 +111,8 @@ impl BlockBuilder { protocol_parameters: &ProtocolParameters, signature: Ed25519Signature, ) -> Self { - Self { - protocol_version: Default::default(), + Self(BlockWrapper { + protocol_version: PROTOCOL_VERSION, network_id, issuing_time, slot_commitment_id, @@ -137,25 +126,32 @@ impl BlockBuilder { protocol_parameters_hash: protocol_parameters.hash(), }, signature, - } + }) + } + + /// Adds a protocol version to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_protocol_version(mut self, protocol_version: u8) -> Self { + self.0.protocol_version = protocol_version; + self } /// Adds weak parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { - self.data.weak_parents = weak_parents.into(); + self.0.data.weak_parents = weak_parents.into(); self } /// Adds shallow like parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { - self.data.shallow_like_parents = shallow_like_parents.into(); + self.0.data.shallow_like_parents = shallow_like_parents.into(); self } } -impl BlockBuilder { +impl BlockBuilder> { pub fn from_block_data( network_id: u64, issuing_time: u64, @@ -165,8 +161,8 @@ impl BlockBuilder { data: B, signature: Ed25519Signature, ) -> Self { - Self { - protocol_version: Default::default(), + Self(BlockWrapper { + protocol_version: PROTOCOL_VERSION, network_id, issuing_time, slot_commitment_id, @@ -174,26 +170,17 @@ impl BlockBuilder { issuer_id, data, signature, - } + }) } } impl BlockBuilder where - BlockWrapper: Packable, - Block: From>, + B: Packable, + Block: From, { fn _finish(self) -> Result<(Block, Vec), Error> { - let block = Block::from(BlockWrapper { - protocol_version: self.protocol_version.unwrap_or(PROTOCOL_VERSION), - network_id: self.network_id, - issuing_time: self.issuing_time, - slot_commitment_id: self.slot_commitment_id, - latest_finalized_slot: self.latest_finalized_slot, - issuer_id: self.issuer_id, - data: self.data, - signature: self.signature, - }); + let block = Block::from(self.0); verify_parents( block.strong_parents(), @@ -392,8 +379,8 @@ impl Block { issuer_id: IssuerId, strong_parents: StrongParents, signature: Ed25519Signature, - ) -> BlockBuilder { - BlockBuilder::::new( + ) -> BlockBuilder { + BlockBuilder::::new( network_id, issuing_time, slot_commitment_id, @@ -416,8 +403,8 @@ impl Block { highest_supported_version: u8, protocol_parameters: &ProtocolParameters, signature: Ed25519Signature, - ) -> BlockBuilder { - BlockBuilder::::new( + ) -> BlockBuilder { + BlockBuilder::::new( network_id, issuing_time, slot_commitment_id, diff --git a/sdk/src/types/block/rand/block.rs b/sdk/src/types/block/rand/block.rs index ced637ce8d..187dafc370 100644 --- a/sdk/src/types/block/rand/block.rs +++ b/sdk/src/types/block/rand/block.rs @@ -5,7 +5,7 @@ use alloc::vec::Vec; use super::signature::rand_ed25519_signature; use crate::types::block::{ - basic::BasicBlockData, + basic::BasicBlock, core::Block, parent::StrongParents, rand::{ @@ -35,7 +35,7 @@ pub fn rand_basic_block_with_strong_parents(strong_parents: StrongParents) -> Bl } /// Generates a random basic block builder with given parents. -pub fn rand_basic_block_builder_with_strong_parents(strong_parents: StrongParents) -> BlockBuilder { +pub fn rand_basic_block_builder_with_strong_parents(strong_parents: StrongParents) -> BlockBuilder { Block::build_basic( rand_number(), rand_number(), From 2ec174d2d15fc4d0bea2e489043502c937114d73 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Fri, 28 Jul 2023 12:29:44 -0400 Subject: [PATCH 18/57] Pr suggestions --- sdk/src/types/block/basic.rs | 49 +++++++++++++++++- sdk/src/types/block/core.rs | 86 ++----------------------------- sdk/src/types/block/validation.rs | 40 ++++++++++++-- 3 files changed, 87 insertions(+), 88 deletions(-) diff --git a/sdk/src/types/block/basic.rs b/sdk/src/types/block/basic.rs index 340a983ac1..707f7bb36c 100644 --- a/sdk/src/types/block/basic.rs +++ b/sdk/src/types/block/basic.rs @@ -13,9 +13,54 @@ use super::{ parent::{ShallowLikeParents, StrongParents, WeakParents}, payload::{OptionalPayload, Payload}, protocol::ProtocolParameters, - Error, + BlockBuilder, Error, }; +impl BlockBuilder { + /// Creates a new [`BlockBuilder`] for a [`BasicBlock`]. + #[inline(always)] + pub fn new(strong_parents: StrongParents) -> Self { + Self { + protocol_version: None, + inner: BasicBlock { + strong_parents, + weak_parents: Default::default(), + shallow_like_parents: Default::default(), + payload: OptionalPayload::default(), + burned_mana: Default::default(), + }, + } + } + + /// Adds weak parents to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { + self.inner.weak_parents = weak_parents.into(); + self + } + + /// Adds shallow like parents to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { + self.inner.shallow_like_parents = shallow_like_parents.into(); + self + } + + /// Adds a payload to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_payload(mut self, payload: impl Into) -> Self { + self.inner.payload = payload.into(); + self + } + + /// Adds burned mana to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_burned_mana(mut self, burned_mana: u64) -> Self { + self.inner.burned_mana = burned_mana; + self + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub struct BasicBlock { /// Blocks that are strongly directly approved. @@ -118,7 +163,7 @@ pub(crate) mod dto { TryFromDto, ValidationParams, }; - /// The block object that nodes gossip around in the network. + /// A basic block. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct BasicBlockDto { diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index a96e2efbc1..38a68ec176 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -15,7 +15,7 @@ use packable::{ use super::{basic::BasicBlock, validation::ValidationBlock}; use crate::types::block::{ parent::{ShallowLikeParents, StrongParents, WeakParents}, - payload::{OptionalPayload, Payload}, + payload::Payload, protocol::ProtocolParameters, BlockId, Error, PROTOCOL_VERSION, }; @@ -24,8 +24,8 @@ use crate::types::block::{ #[derive(Clone)] #[must_use] pub struct BlockBuilder { - protocol_version: Option, - inner: B, + pub(crate) protocol_version: Option, + pub(crate) inner: B, } impl BlockBuilder { @@ -37,86 +37,6 @@ impl BlockBuilder { } } -impl BlockBuilder { - /// Creates a new [`BlockBuilder`] for a [`BasicBlock`]. - #[inline(always)] - pub fn new(strong_parents: StrongParents) -> Self { - Self { - protocol_version: None, - inner: BasicBlock { - strong_parents, - weak_parents: Default::default(), - shallow_like_parents: Default::default(), - payload: OptionalPayload::default(), - burned_mana: Default::default(), - }, - } - } - - /// Adds weak parents to a [`BlockBuilder`]. - #[inline(always)] - pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { - self.inner.weak_parents = weak_parents.into(); - self - } - - /// Adds shallow like parents to a [`BlockBuilder`]. - #[inline(always)] - pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { - self.inner.shallow_like_parents = shallow_like_parents.into(); - self - } - - /// Adds a payload to a [`BlockBuilder`]. - #[inline(always)] - pub fn with_payload(mut self, payload: impl Into) -> Self { - self.inner.payload = payload.into(); - self - } - - /// Adds burned mana to a [`BlockBuilder`]. - #[inline(always)] - pub fn with_burned_mana(mut self, burned_mana: u64) -> Self { - self.inner.burned_mana = burned_mana; - self - } -} - -impl BlockBuilder { - /// Creates a new [`BlockBuilder`] for a [`ValidationBlock`]. - #[inline(always)] - pub fn new( - strong_parents: StrongParents, - highest_supported_version: u8, - protocol_parameters: &ProtocolParameters, - ) -> Self { - Self { - protocol_version: None, - inner: ValidationBlock { - strong_parents, - weak_parents: Default::default(), - shallow_like_parents: Default::default(), - highest_supported_version, - protocol_parameters_hash: protocol_parameters.hash(), - }, - } - } - - /// Adds weak parents to a [`BlockBuilder`]. - #[inline(always)] - pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { - self.inner.weak_parents = weak_parents.into(); - self - } - - /// Adds shallow like parents to a [`BlockBuilder`]. - #[inline(always)] - pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { - self.inner.shallow_like_parents = shallow_like_parents.into(); - self - } -} - impl> From for BlockBuilder { fn from(inner: B) -> Self { Self { diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs index 81f32265b4..83d0a63d5c 100644 --- a/sdk/src/types/block/validation.rs +++ b/sdk/src/types/block/validation.rs @@ -12,9 +12,44 @@ use super::{ core::verify_parents, parent::{ShallowLikeParents, StrongParents, WeakParents}, protocol::{ProtocolParameters, ProtocolParametersHash}, - Error, + BlockBuilder, Error, }; +impl BlockBuilder { + /// Creates a new [`BlockBuilder`] for a [`ValidationBlock`]. + #[inline(always)] + pub fn new( + strong_parents: StrongParents, + highest_supported_version: u8, + protocol_parameters: &ProtocolParameters, + ) -> Self { + Self { + protocol_version: None, + inner: ValidationBlock { + strong_parents, + weak_parents: Default::default(), + shallow_like_parents: Default::default(), + highest_supported_version, + protocol_parameters_hash: protocol_parameters.hash(), + }, + } + } + + /// Adds weak parents to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { + self.inner.weak_parents = weak_parents.into(); + self + } + + /// Adds shallow like parents to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { + self.inner.shallow_like_parents = shallow_like_parents.into(); + self + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub struct ValidationBlock { /// Blocks that are strongly directly approved. @@ -93,7 +128,6 @@ impl Packable for ValidationBlock { let protocol_parameters_hash = ProtocolParametersHash::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - // TODO: Is this actually right/needed? if VERIFY { validate_protocol_params_hash(&protocol_parameters_hash, visitor).map_err(UnpackError::Packable)?; } @@ -132,7 +166,7 @@ pub(crate) mod dto { TryFromDto, ValidationParams, }; - /// The block object that nodes gossip around in the network. + /// A special type of block used by validators to secure the network. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ValidationBlockDto { From 3c096df7b5014e76ee34354efa7aceb79753615d Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 31 Jul 2023 09:44:30 -0400 Subject: [PATCH 19/57] Allow warnings and stub in missing values --- bindings/core/src/method_handler/client.rs | 3 +++ sdk/examples/client/block/00_block_no_payload.rs | 10 +++++++++- .../client/block/01_block_confirmation_time.rs | 10 +++++++++- sdk/examples/client/block/02_block_custom_parents.rs | 8 +++++++- sdk/examples/client/block/03_block_custom_payload.rs | 8 +++++++- sdk/examples/client/block/04_block_tagged_data.rs | 3 +++ sdk/examples/client/node_api_core/04_post_block.rs | 10 +++++++++- .../client/node_api_core/05_post_block_raw.rs | 10 +++++++++- sdk/src/lib.rs | 2 +- sdk/src/types/block/core.rs | 1 + sdk/src/wallet/account/operations/retry.rs | 11 ++++++++++- .../operations/transaction/submit_transaction.rs | 8 +++++++- sdk/tests/client/node_api/mod.rs | 3 +++ sdk/tests/types/block.rs | 9 ++++++--- 14 files changed, 84 insertions(+), 12 deletions(-) diff --git a/bindings/core/src/method_handler/client.rs b/bindings/core/src/method_handler/client.rs index 32db94ce96..41b41f41c6 100644 --- a/bindings/core/src/method_handler/client.rs +++ b/bindings/core/src/method_handler/client.rs @@ -176,6 +176,9 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM ClientMethod::PostBlockPayload { payload } => { let block = client .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), None, Some(Payload::try_from_dto_with_params( payload, diff --git a/sdk/examples/client/block/00_block_no_payload.rs b/sdk/examples/client/block/00_block_no_payload.rs index 44c9346d9b..4ed897dfd9 100644 --- a/sdk/examples/client/block/00_block_no_payload.rs +++ b/sdk/examples/client/block/00_block_no_payload.rs @@ -21,7 +21,15 @@ async fn main() -> Result<()> { let client = Client::builder().with_node(&node_url)?.finish().await?; // Create and send the block. - let block = client.finish_basic_block_builder(None, None).await?; + let block = client + .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), + None, + None, + ) + .await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/01_block_confirmation_time.rs b/sdk/examples/client/block/01_block_confirmation_time.rs index ee36a57e80..9fef1ecd65 100644 --- a/sdk/examples/client/block/01_block_confirmation_time.rs +++ b/sdk/examples/client/block/01_block_confirmation_time.rs @@ -21,7 +21,15 @@ async fn main() -> Result<()> { let client = Client::builder().with_node(&node_url)?.finish().await?; // Create and send a block. - let block = client.finish_basic_block_builder(None, None).await?; + let block = client + .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), + None, + None, + ) + .await?; let block_id = block.id(); println!("{block:#?}"); diff --git a/sdk/examples/client/block/02_block_custom_parents.rs b/sdk/examples/client/block/02_block_custom_parents.rs index fe4536824e..d82d253ab4 100644 --- a/sdk/examples/client/block/02_block_custom_parents.rs +++ b/sdk/examples/client/block/02_block_custom_parents.rs @@ -29,7 +29,13 @@ async fn main() -> Result<()> { // Create and send the block with custom parents. let block = client - .finish_basic_block_builder(Some(StrongParents::from_vec(tips)?), None) + .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), + Some(StrongParents::from_vec(tips)?), + None, + ) .await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/03_block_custom_payload.rs b/sdk/examples/client/block/03_block_custom_payload.rs index 522156676d..8ed209e5bc 100644 --- a/sdk/examples/client/block/03_block_custom_payload.rs +++ b/sdk/examples/client/block/03_block_custom_payload.rs @@ -28,7 +28,13 @@ async fn main() -> Result<()> { // Create and send the block with the custom payload. let block = client - .finish_basic_block_builder(None, Some(Payload::from(tagged_data_payload))) + .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), + None, + Some(Payload::from(tagged_data_payload)), + ) .await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/04_block_tagged_data.rs b/sdk/examples/client/block/04_block_tagged_data.rs index 6472517c23..4f0d21bd0a 100644 --- a/sdk/examples/client/block/04_block_tagged_data.rs +++ b/sdk/examples/client/block/04_block_tagged_data.rs @@ -26,6 +26,9 @@ async fn main() -> Result<()> { // Create and send the block with tag and data. let block = client .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), None, Some(Payload::TaggedData(Box::new( TaggedDataPayload::new( diff --git a/sdk/examples/client/node_api_core/04_post_block.rs b/sdk/examples/client/node_api_core/04_post_block.rs index c0632c638a..17b277fe9f 100644 --- a/sdk/examples/client/node_api_core/04_post_block.rs +++ b/sdk/examples/client/node_api_core/04_post_block.rs @@ -24,7 +24,15 @@ async fn main() -> Result<()> { let client = Client::builder().with_node(&node_url)?.finish().await?; // Create the block. - let block = client.finish_basic_block_builder(None, None).await?; + let block = client + .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), + None, + None, + ) + .await?; // Post the block. let block_id = client.post_block(&block).await?; diff --git a/sdk/examples/client/node_api_core/05_post_block_raw.rs b/sdk/examples/client/node_api_core/05_post_block_raw.rs index f8181280b3..c93f8129c8 100644 --- a/sdk/examples/client/node_api_core/05_post_block_raw.rs +++ b/sdk/examples/client/node_api_core/05_post_block_raw.rs @@ -24,7 +24,15 @@ async fn main() -> Result<()> { let client = Client::builder().with_node(&node_url)?.finish().await?; // Create the block. - let block = client.finish_basic_block_builder(None, None).await?; + let block = client + .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), + None, + None, + ) + .await?; // Post the block as raw bytes. let block_id = client.post_block_raw(&block).await?; diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 6bd76652ec..dc54411f41 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -4,7 +4,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(docsrs, feature(doc_cfg))] // TODO missing_docs -#![deny(clippy::nursery, rust_2018_idioms, warnings, unreachable_pub)] +#![deny(clippy::nursery, rust_2018_idioms, /* warnings, */ unreachable_pub)] #![allow( clippy::redundant_pub_crate, clippy::missing_const_for_fn, diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 8b3b6710cc..53f2b16ccf 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -160,6 +160,7 @@ impl Packable for Block { signature, }) } + _ => return Err(Error::InvalidBlockKind(kind)).map_err(UnpackError::Packable), }; if VERIFY { diff --git a/sdk/src/wallet/account/operations/retry.rs b/sdk/src/wallet/account/operations/retry.rs index 8862ba252b..932b4bac5a 100644 --- a/sdk/src/wallet/account/operations/retry.rs +++ b/sdk/src/wallet/account/operations/retry.rs @@ -70,7 +70,13 @@ where Some(block_id) => block_id, None => self .client() - .finish_basic_block_builder(None, Some(Payload::Transaction(Box::new(transaction.payload.clone())))) + .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), + None, + Some(Payload::Transaction(Box::new(transaction.payload.clone()))), + ) .await? .id(), }; @@ -111,6 +117,9 @@ where let reattached_block = self .client() .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), None, Some(Payload::Transaction(Box::new(transaction.payload.clone()))), ) diff --git a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs index 0c94181c88..916f21a875 100644 --- a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs +++ b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs @@ -24,7 +24,13 @@ where let block = self .client() - .finish_basic_block_builder(None, Some(Payload::from(transaction_payload))) + .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), + None, + Some(Payload::from(transaction_payload)), + ) .await?; #[cfg(feature = "events")] diff --git a/sdk/tests/client/node_api/mod.rs b/sdk/tests/client/node_api/mod.rs index fdd5d8fa6e..fae72ad491 100644 --- a/sdk/tests/client/node_api/mod.rs +++ b/sdk/tests/client/node_api/mod.rs @@ -28,6 +28,9 @@ async fn setup_tagged_data_block() -> BlockId { client .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), None, Some(Payload::TaggedData(Box::new( TaggedDataPayload::new(b"Hello".to_vec(), b"Tangle".to_vec()).unwrap(), diff --git a/sdk/tests/types/block.rs b/sdk/tests/types/block.rs index 39a2f6cc31..ecd84658fa 100644 --- a/sdk/tests/types/block.rs +++ b/sdk/tests/types/block.rs @@ -4,8 +4,11 @@ use iota_sdk::types::block::{ payload::Payload, protocol::protocol_parameters, - rand::{block::rand_block, parents::rand_strong_parents, payload::rand_tagged_data_payload}, - Block, BlockBuilder, + rand::{ + block::{rand_basic_block_builder_with_strong_parents, rand_basic_block_with_strong_parents, rand_block}, + parents::rand_strong_parents, + payload::rand_tagged_data_payload, + }, }; use packable::PackableExt; @@ -84,7 +87,7 @@ use packable::PackableExt; #[test] fn pack_unpack_valid() { let protocol_parameters = protocol_parameters(); - let block = rand_block().finish().unwrap(); + let block = rand_block(); let packed_block = block.pack_to_vec(); assert_eq!(packed_block.len(), block.packed_len()); From 1b6d04c3efe25c4452868d35a45e48f9fa7e16c0 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 31 Jul 2023 11:59:58 -0400 Subject: [PATCH 20/57] clippy --- sdk/src/client/api/high_level.rs | 2 +- sdk/src/types/block/basic.rs | 2 +- sdk/src/types/block/core.rs | 22 +++++++++++++++++----- sdk/src/types/block/signature/ed25519.rs | 2 +- sdk/src/types/block/validation.rs | 2 +- 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/sdk/src/client/api/high_level.rs b/sdk/src/client/api/high_level.rs index b1b2059933..338ebb8059 100644 --- a/sdk/src/client/api/high_level.rs +++ b/sdk/src/client/api/high_level.rs @@ -272,7 +272,7 @@ impl Client { } // Get block if we use remote Pow, because the node will change parents and nonce. - let block = self.get_block(&block_id).await?; + let block = self.get_block(block_id).await?; let promote_block = self .finish_basic_block_builder( diff --git a/sdk/src/types/block/basic.rs b/sdk/src/types/block/basic.rs index 38ba500945..6f92cd5990 100644 --- a/sdk/src/types/block/basic.rs +++ b/sdk/src/types/block/basic.rs @@ -219,7 +219,7 @@ impl Packable for BasicBlock { let kind = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - if kind != BasicBlock::KIND { + if kind != Self::KIND { return Err(Error::InvalidBlockKind(kind)).map_err(UnpackError::Packable); } diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 53f2b16ccf..45328c4564 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -85,8 +85,20 @@ where #[derive(Clone, Debug, Eq, PartialEq, From)] pub enum Block { - Basic(BasicBlock), - Validation(ValidationBlock), + Basic(Box), + Validation(Box), +} + +impl From for Block { + fn from(value: BasicBlock) -> Self { + Self::Basic(value.into()) + } +} + +impl From for Block { + fn from(value: ValidationBlock) -> Self { + Self::Validation(value.into()) + } } impl Packable for Block { @@ -134,7 +146,7 @@ impl Packable for Block { let data = BasicBlockData::unpack::<_, VERIFY>(unpacker, visitor)?; let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; - Block::from(BlockWrapper { + Self::from(BlockWrapper { protocol_version, network_id, issuing_time, @@ -149,7 +161,7 @@ impl Packable for Block { let data = ValidationBlockData::unpack::<_, VERIFY>(unpacker, visitor)?; let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; - Block::from(BlockWrapper { + Self::from(BlockWrapper { protocol_version, network_id, issuing_time, @@ -170,7 +182,7 @@ impl Packable for Block { block.packed_len() }; - if block_len > Block::LENGTH_MAX { + if block_len > Self::LENGTH_MAX { return Err(UnpackError::Packable(Error::InvalidBlockLength(block_len))); } } diff --git a/sdk/src/types/block/signature/ed25519.rs b/sdk/src/types/block/signature/ed25519.rs index a4c788530f..332dcbec2a 100644 --- a/sdk/src/types/block/signature/ed25519.rs +++ b/sdk/src/types/block/signature/ed25519.rs @@ -63,7 +63,7 @@ impl Ed25519Signature { /// Verifies the [`Ed25519Signature`] for a message against an [`Ed25519Address`]. pub fn is_valid(&self, message: &[u8], address: &Ed25519Address) -> Result<(), Error> { - let signature_address: [u8; Self::PUBLIC_KEY_LENGTH] = Blake2b256::digest(&self.public_key).into(); + let signature_address: [u8; Self::PUBLIC_KEY_LENGTH] = Blake2b256::digest(self.public_key).into(); if address.deref() != &signature_address { return Err(Error::SignaturePublicKeyMismatch { diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs index dc3b4fb44f..0e8db5bd42 100644 --- a/sdk/src/types/block/validation.rs +++ b/sdk/src/types/block/validation.rs @@ -208,7 +208,7 @@ impl Packable for ValidationBlock { let kind = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - if kind != ValidationBlock::KIND { + if kind != Self::KIND { return Err(Error::InvalidBlockKind(kind)).map_err(UnpackError::Packable); } From b6143e3a22fd4b2f9f12a794bf6c39c95c857d65 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 31 Jul 2023 13:18:03 -0400 Subject: [PATCH 21/57] properly pack kind and disable clippy CI for now --- .github/workflows/lint.yml | 30 +++++++++++++++--------------- sdk/src/types/block/basic.rs | 1 + sdk/src/types/block/core.rs | 2 +- sdk/src/types/block/validation.rs | 1 + 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 352b264f99..79357783e0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -51,21 +51,21 @@ jobs: sudo apt-get update sudo apt-get install libudev-dev libusb-1.0-0-dev - # A first run without features to detect feature related issues. - - name: Run Clippy - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --all-targets -- --deny warnings - name: Clippy Results for the Rust Core - - # The second run will continue from where the first left off. - - name: Run Clippy - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --all-features --all-targets -- --deny warnings - name: Clippy Results for the Rust Core + # # A first run without features to detect feature related issues. + # - name: Run Clippy + # uses: actions-rs/clippy-check@v1 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + # args: --all-targets -- --deny warnings + # name: Clippy Results for the Rust Core + + # # The second run will continue from where the first left off. + # - name: Run Clippy + # uses: actions-rs/clippy-check@v1 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + # args: --all-features --all-targets -- --deny warnings + # name: Clippy Results for the Rust Core check-unused-deps: name: Check Unused Dependencies diff --git a/sdk/src/types/block/basic.rs b/sdk/src/types/block/basic.rs index 6f92cd5990..677ca1a51c 100644 --- a/sdk/src/types/block/basic.rs +++ b/sdk/src/types/block/basic.rs @@ -186,6 +186,7 @@ impl Packable for BasicBlock { self.slot_commitment_id.pack(packer)?; self.latest_finalized_slot.pack(packer)?; self.issuer_id.pack(packer)?; + Self::KIND.pack(packer)?; self.data.pack(packer)?; self.signature.pack(packer)?; diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 45328c4564..1effec2037 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -1,7 +1,7 @@ // Copyright 2020-2021 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use alloc::vec::Vec; +use alloc::{boxed::Box, vec::Vec}; use crypto::hashes::{blake2b::Blake2b256, Digest}; use derive_more::From; diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs index 0e8db5bd42..44f2f53ae1 100644 --- a/sdk/src/types/block/validation.rs +++ b/sdk/src/types/block/validation.rs @@ -175,6 +175,7 @@ impl Packable for ValidationBlock { self.slot_commitment_id.pack(packer)?; self.latest_finalized_slot.pack(packer)?; self.issuer_id.pack(packer)?; + Self::KIND.pack(packer)?; self.data.pack(packer)?; self.signature.pack(packer)?; From 5e4c5bab283646b9b7eb5ca997a1e985c112ba02 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 31 Jul 2023 14:32:13 -0400 Subject: [PATCH 22/57] Implement new block ID --- bindings/core/src/method/utils.rs | 11 ++-- bindings/core/src/method_handler/client.rs | 8 +-- bindings/core/src/method_handler/utils.rs | 9 ++- .../client/block/00_block_no_payload.rs | 4 +- .../block/01_block_confirmation_time.rs | 4 +- .../client/block/02_block_custom_parents.rs | 4 +- .../client/block/03_block_custom_payload.rs | 4 +- .../client/block/04_block_tagged_data.rs | 4 +- sdk/src/client/api/high_level.rs | 5 +- .../api/plugins/participation/responses.rs | 2 +- sdk/src/types/block/basic.rs | 10 +-- sdk/src/types/block/block_id.rs | 2 +- sdk/src/types/block/core.rs | 65 ++++++++++++++++++- sdk/src/types/block/protocol.rs | 6 +- sdk/src/wallet/account/operations/retry.rs | 6 +- .../operations/syncing/transactions.rs | 2 +- sdk/tests/client/high_level.rs | 3 +- sdk/tests/client/node_api/mod.rs | 6 +- 18 files changed, 113 insertions(+), 42 deletions(-) diff --git a/bindings/core/src/method/utils.rs b/bindings/core/src/method/utils.rs index b336cbf918..da41a9de38 100644 --- a/bindings/core/src/method/utils.rs +++ b/bindings/core/src/method/utils.rs @@ -10,7 +10,6 @@ use iota_sdk::types::block::{ TransactionId, }, signature::dto::Ed25519SignatureDto, - BlockDto, }; use serde::{Deserialize, Serialize}; @@ -77,11 +76,11 @@ pub enum UtilsMethod { #[derivative(Debug(format_with = "OmittedDebug::omitted_fmt"))] mnemonic: String, }, - /// Returns a block ID (Blake2b256 hash of block bytes) from a block - BlockId { - /// Block - block: BlockDto, - }, + // /// Returns a block ID (Blake2b256 hash of block bytes) from a block + // BlockId { + // /// Block + // block: BlockDto, + // }, /// Returns the transaction ID (Blake2b256 hash of the provided transaction payload) TransactionId { /// Transaction Payload diff --git a/bindings/core/src/method_handler/client.rs b/bindings/core/src/method_handler/client.rs index 41b41f41c6..1939c1c5e3 100644 --- a/bindings/core/src/method_handler/client.rs +++ b/bindings/core/src/method_handler/client.rs @@ -174,20 +174,18 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM ClientMethod::GetBech32Hrp => Response::Bech32Hrp(client.get_bech32_hrp().await?), ClientMethod::GetProtocolParameters => Response::ProtocolParameters(client.get_protocol_parameters().await?), ClientMethod::PostBlockPayload { payload } => { + let protocol_params = client.get_protocol_parameters().await?; let block = client .finish_basic_block_builder( todo!("issuer id"), todo!("block signature"), todo!("issuing time"), None, - Some(Payload::try_from_dto_with_params( - payload, - &client.get_protocol_parameters().await?, - )?), + Some(Payload::try_from_dto_with_params(payload, &protocol_params)?), ) .await?; - let block_id = block.id(); + let block_id = block.id(&protocol_params); Response::BlockIdWithBlock(block_id, BlockDto::from(&block)) } diff --git a/bindings/core/src/method_handler/utils.rs b/bindings/core/src/method_handler/utils.rs index beb11e061c..914ad211e3 100644 --- a/bindings/core/src/method_handler/utils.rs +++ b/bindings/core/src/method_handler/utils.rs @@ -11,7 +11,6 @@ use iota_sdk::{ output::{AccountId, FoundryId, InputsCommitment, NftId, Output, OutputId, Rent, TokenId}, payload::{transaction::TransactionEssence, TransactionPayload}, signature::Ed25519Signature, - Block, }, TryFromDto, }, @@ -38,10 +37,10 @@ pub(crate) fn call_utils_method_internal(method: UtilsMethod) -> Result { - let block = Block::try_from_dto(block)?; - Response::BlockId(block.id()) - } + // UtilsMethod::BlockId { block } => { + // let block = Block::try_from_dto(block)?; + // Response::BlockId(block.id()) + // } UtilsMethod::TransactionId { payload } => { let payload = TransactionPayload::try_from_dto(payload)?; Response::TransactionId(payload.id()) diff --git a/sdk/examples/client/block/00_block_no_payload.rs b/sdk/examples/client/block/00_block_no_payload.rs index 4ed897dfd9..27fef95026 100644 --- a/sdk/examples/client/block/00_block_no_payload.rs +++ b/sdk/examples/client/block/00_block_no_payload.rs @@ -20,6 +20,8 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let protocol_parameters = client.get_protocol_parameters().await?; + // Create and send the block. let block = client .finish_basic_block_builder( @@ -36,7 +38,7 @@ async fn main() -> Result<()> { println!( "Block with no payload sent: {}/block/{}", std::env::var("EXPLORER_URL").unwrap(), - block.id() + block.id(&protocol_parameters) ); Ok(()) diff --git a/sdk/examples/client/block/01_block_confirmation_time.rs b/sdk/examples/client/block/01_block_confirmation_time.rs index 9fef1ecd65..5e663d88b9 100644 --- a/sdk/examples/client/block/01_block_confirmation_time.rs +++ b/sdk/examples/client/block/01_block_confirmation_time.rs @@ -20,6 +20,8 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let protocol_parameters = client.get_protocol_parameters().await?; + // Create and send a block. let block = client .finish_basic_block_builder( @@ -30,7 +32,7 @@ async fn main() -> Result<()> { None, ) .await?; - let block_id = block.id(); + let block_id = block.id(&protocol_parameters); println!("{block:#?}"); diff --git a/sdk/examples/client/block/02_block_custom_parents.rs b/sdk/examples/client/block/02_block_custom_parents.rs index d82d253ab4..dc92a93361 100644 --- a/sdk/examples/client/block/02_block_custom_parents.rs +++ b/sdk/examples/client/block/02_block_custom_parents.rs @@ -23,6 +23,8 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let protocol_parameters = client.get_protocol_parameters().await?; + // Use tips as custom parents. let tips = client.get_tips().await?; println!("Custom tips:\n{tips:#?}"); @@ -43,7 +45,7 @@ async fn main() -> Result<()> { println!( "Block with custom parents sent: {}/block/{}", std::env::var("EXPLORER_URL").unwrap(), - block.id() + block.id(&protocol_parameters) ); Ok(()) diff --git a/sdk/examples/client/block/03_block_custom_payload.rs b/sdk/examples/client/block/03_block_custom_payload.rs index 8ed209e5bc..6403d4209d 100644 --- a/sdk/examples/client/block/03_block_custom_payload.rs +++ b/sdk/examples/client/block/03_block_custom_payload.rs @@ -23,6 +23,8 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let protocol_parameters = client.get_protocol_parameters().await?; + // Create a custom payload. let tagged_data_payload = TaggedDataPayload::new(*b"Your tag", *b"Your data")?; @@ -42,7 +44,7 @@ async fn main() -> Result<()> { println!( "Block with custom payload sent: {}/block/{}", std::env::var("EXPLORER_URL").unwrap(), - block.id() + block.id(&protocol_parameters) ); Ok(()) diff --git a/sdk/examples/client/block/04_block_tagged_data.rs b/sdk/examples/client/block/04_block_tagged_data.rs index 4f0d21bd0a..e0a8e4ded6 100644 --- a/sdk/examples/client/block/04_block_tagged_data.rs +++ b/sdk/examples/client/block/04_block_tagged_data.rs @@ -23,6 +23,8 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let protocol_parameters = client.get_protocol_parameters().await?; + // Create and send the block with tag and data. let block = client .finish_basic_block_builder( @@ -62,7 +64,7 @@ async fn main() -> Result<()> { println!( "Block with tag and data sent: {}/block/{}", std::env::var("EXPLORER_URL").unwrap(), - block.id() + block.id(&protocol_parameters) ); Ok(()) diff --git a/sdk/src/client/api/high_level.rs b/sdk/src/client/api/high_level.rs index 338ebb8059..ba5f792e48 100644 --- a/sdk/src/client/api/high_level.rs +++ b/sdk/src/client/api/high_level.rs @@ -151,7 +151,10 @@ impl Client { let block = self.get_block(block_id).await?; if let Some(Payload::Transaction(transaction_payload)) = block.payload() { let included_block = self.get_included_block(&transaction_payload.id()).await?; - let mut included_and_reattached_blocks = vec![(included_block.id(), included_block)]; + let mut included_and_reattached_blocks = vec![( + included_block.id(&self.get_protocol_parameters().await?), + included_block, + )]; included_and_reattached_blocks.extend(blocks_with_id); return Ok(included_and_reattached_blocks); } diff --git a/sdk/src/types/api/plugins/participation/responses.rs b/sdk/src/types/api/plugins/participation/responses.rs index 36f676cb3c..9f38a22b28 100644 --- a/sdk/src/types/api/plugins/participation/responses.rs +++ b/sdk/src/types/api/plugins/participation/responses.rs @@ -68,7 +68,7 @@ impl OutputStatusResponse { participations: [( ParticipationEventId::new([42; 32]), TrackedParticipation { - block_id: BlockId::new([23; 32]), + block_id: BlockId::new([23; 40]), amount: 100, start_milestone_index: 1000, end_milestone_index: 9999, diff --git a/sdk/src/types/block/basic.rs b/sdk/src/types/block/basic.rs index 677ca1a51c..2be86256da 100644 --- a/sdk/src/types/block/basic.rs +++ b/sdk/src/types/block/basic.rs @@ -1,9 +1,10 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use crypto::hashes::{blake2b::Blake2b256, Digest}; use packable::{ error::{UnpackError, UnpackErrorExt}, - packer::Packer, + packer::{Packer, SlicePacker}, unpacker::Unpacker, Packable, PackableExt, }; @@ -180,12 +181,7 @@ impl Packable for BasicBlock { type UnpackVisitor = ProtocolParameters; fn pack(&self, packer: &mut P) -> Result<(), P::Error> { - self.protocol_version.pack(packer)?; - self.network_id.pack(packer)?; - self.issuing_time.pack(packer)?; - self.slot_commitment_id.pack(packer)?; - self.latest_finalized_slot.pack(packer)?; - self.issuer_id.pack(packer)?; + self.pack_header(packer)?; Self::KIND.pack(packer)?; self.data.pack(packer)?; self.signature.pack(packer)?; diff --git a/sdk/src/types/block/block_id.rs b/sdk/src/types/block/block_id.rs index 6dc6e1a22b..4920131b56 100644 --- a/sdk/src/types/block/block_id.rs +++ b/sdk/src/types/block/block_id.rs @@ -3,7 +3,7 @@ impl_id!( pub BlockId, - 32, + 40, "A block identifier, the BLAKE2b-256 hash of the block bytes. See for more information." ); diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 1effec2037..9623dddce7 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -2,12 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 use alloc::{boxed::Box, vec::Vec}; +use core::mem::size_of; use crypto::hashes::{blake2b::Blake2b256, Digest}; use derive_more::From; use packable::{ error::{UnexpectedEOF, UnpackError, UnpackErrorExt}, - packer::Packer, + packer::{Packer, SlicePacker}, unpacker::{CounterUnpacker, SliceUnpacker, Unpacker}, Packable, PackableExt, }; @@ -254,6 +255,22 @@ impl BlockWrapper { pub fn signature(&self) -> &Ed25519Signature { &self.signature } + + pub(crate) fn pack_header(&self, packer: &mut P) -> Result<(), P::Error> { + self.protocol_version.pack(packer)?; + self.network_id.pack(packer)?; + self.issuing_time.pack(packer)?; + self.slot_commitment_id.pack(packer)?; + self.latest_finalized_slot.pack(packer)?; + self.issuer_id.pack(packer)?; + Ok(()) + } + + pub(crate) fn header_hash(&self) -> [u8; 32] { + let mut bytes = [0u8; Block::HEADER_LENGTH]; + self.pack_header(&mut SlicePacker::new(&mut bytes)).unwrap(); + Blake2b256::digest(bytes).into() + } } impl Block { @@ -261,6 +278,14 @@ impl Block { pub const LENGTH_MIN: usize = 46; /// The maximum number of bytes in a block. pub const LENGTH_MAX: usize = 32768; + /// The length of the block header. + pub const HEADER_LENGTH: usize = size_of::() + + 2 * size_of::() + + size_of::() + + size_of::() + + size_of::(); + /// The length of the block signature. + pub const SIGNATURE_LENGTH: usize = Ed25519Signature::PUBLIC_KEY_LENGTH + Ed25519Signature::SIGNATURE_LENGTH; /// Creates a new [`BlockBuilder`] to construct an instance of a [`BasicBlock`]. #[inline(always)] @@ -441,8 +466,17 @@ impl Block { /// Computes the identifier of the block. #[inline(always)] - pub fn id(&self) -> BlockId { - BlockId::new(Blake2b256::digest(self.pack_to_vec()).into()) + pub fn id(&self, protocol_parameters: &ProtocolParameters) -> BlockId { + let mut res = [0u8; 40]; + let id = [ + &self.header_hash()[..], + &self.block_hash()[..], + &self.signature_bytes()[..], + ] + .concat(); + res[..32].copy_from_slice(&*Blake2b256::digest(id)); + res[32..].copy_from_slice(&self.slot_index_bytes(protocol_parameters)); + BlockId::new(res) } /// Unpacks a [`Block`] from a sequence of bytes doing syntactical checks and verifying that @@ -461,6 +495,31 @@ impl Block { Ok(block) } + + pub(crate) fn header_hash(&self) -> [u8; 32] { + match self { + Block::Basic(b) => b.header_hash(), + Block::Validation(b) => b.header_hash(), + } + } + + pub(crate) fn block_hash(&self) -> [u8; 32] { + let bytes = match self { + Block::Basic(b) => b.data.pack_to_vec(), + Block::Validation(b) => b.data.pack_to_vec(), + }; + Blake2b256::digest(bytes).into() + } + + pub(crate) fn signature_bytes(&self) -> [u8; Block::SIGNATURE_LENGTH] { + let mut bytes = [0u8; Block::SIGNATURE_LENGTH]; + self.signature().pack(&mut SlicePacker::new(&mut bytes)).unwrap(); + bytes + } + + pub(crate) fn slot_index_bytes(&self, protocol_parameters: &ProtocolParameters) -> [u8; 8] { + protocol_parameters.slot_index(self.issuing_time()).to_le_bytes() + } } pub(crate) fn verify_parents( diff --git a/sdk/src/types/block/protocol.rs b/sdk/src/types/block/protocol.rs index 48dbc5ef33..9d40880c0d 100644 --- a/sdk/src/types/block/protocol.rs +++ b/sdk/src/types/block/protocol.rs @@ -7,7 +7,7 @@ use core::borrow::Borrow; use crypto::hashes::{blake2b::Blake2b256, Digest}; use packable::{prefix::StringPrefix, Packable, PackableExt}; -use super::address::Hrp; +use super::{address::Hrp, slot::SlotIndex}; use crate::types::block::{helper::network_name_to_id, output::RentStructure, ConvertTo, Error, PROTOCOL_VERSION}; /// Defines the parameters of the protocol. @@ -135,6 +135,10 @@ impl ProtocolParameters { self.slot_duration_in_seconds } + pub fn slot_index(&self, timestamp: u64) -> SlotIndex { + (1 + (timestamp - self.genesis_unix_timestamp() as u64) / self.slot_duration_in_seconds() as u64).into() + } + pub fn hash(&self) -> ProtocolParametersHash { ProtocolParametersHash::new(Blake2b256::digest(self.pack_to_vec()).into()) } diff --git a/sdk/src/wallet/account/operations/retry.rs b/sdk/src/wallet/account/operations/retry.rs index 932b4bac5a..18c6fbc270 100644 --- a/sdk/src/wallet/account/operations/retry.rs +++ b/sdk/src/wallet/account/operations/retry.rs @@ -78,7 +78,7 @@ where Some(Payload::Transaction(Box::new(transaction.payload.clone()))), ) .await? - .id(), + .id(&self.client().get_protocol_parameters().await?), }; // Attachments of the Block to check inclusion state @@ -124,7 +124,7 @@ where Some(Payload::Transaction(Box::new(transaction.payload.clone()))), ) .await?; - block_ids.push(reattached_block.id()); + block_ids.push(reattached_block.id(&self.client().get_protocol_parameters().await?)); } } } @@ -139,7 +139,7 @@ where e } })?; - return Ok(included_block.id()); + return Ok(included_block.id(&self.client().get_protocol_parameters().await?)); } } Err(ClientError::TangleInclusion(block_id.to_string()).into()) diff --git a/sdk/src/wallet/account/operations/syncing/transactions.rs b/sdk/src/wallet/account/operations/syncing/transactions.rs index d2f2fc118d..9df9f07566 100644 --- a/sdk/src/wallet/account/operations/syncing/transactions.rs +++ b/sdk/src/wallet/account/operations/syncing/transactions.rs @@ -126,7 +126,7 @@ where confirmed_unknown_output = true; updated_transaction_and_outputs( transaction, - Some(included_block.id()), + Some(included_block.id(&self.client().get_protocol_parameters().await?)), // block metadata was Conflicting, but it's confirmed in another attachment InclusionState::Confirmed, &mut updated_transactions, diff --git a/sdk/tests/client/high_level.rs b/sdk/tests/client/high_level.rs index 308aa2f290..7932b00ce0 100644 --- a/sdk/tests/client/high_level.rs +++ b/sdk/tests/client/high_level.rs @@ -22,11 +22,12 @@ async fn test_find_inputs_from_transaction_id() { #[tokio::test] async fn test_find_blocks() { let client = setup_client_with_node_health_ignored().await; + let protocol_parameters = client.get_protocol_parameters().await.unwrap(); let (block_id, _transaction_id) = setup_transaction_block(&client).await; let blocks = client.find_blocks(&[block_id]).await.unwrap(); assert_eq!(blocks.len(), 1); - assert_eq!(blocks[0].id(), block_id); + assert_eq!(blocks[0].id(&protocol_parameters), block_id); } #[ignore] diff --git a/sdk/tests/client/node_api/mod.rs b/sdk/tests/client/node_api/mod.rs index fae72ad491..ac07da0913 100644 --- a/sdk/tests/client/node_api/mod.rs +++ b/sdk/tests/client/node_api/mod.rs @@ -26,6 +26,8 @@ const DEFAULT_DEVELOPMENT_SEED: &str = "0x256a818b2aac458941f7274985a410e57fb750 async fn setup_tagged_data_block() -> BlockId { let client = setup_client_with_node_health_ignored().await; + let protocol_parameters = client.get_protocol_parameters().await.unwrap(); + client .finish_basic_block_builder( todo!("issuer id"), @@ -38,7 +40,7 @@ async fn setup_tagged_data_block() -> BlockId { ) .await .unwrap() - .id() + .id(&protocol_parameters) } pub fn setup_secret_manager() -> SecretManager { @@ -90,7 +92,7 @@ pub async fn setup_transaction_block(client: &Client) -> (BlockId, TransactionId _ => unreachable!(), }; - let _ = client.retry_until_included(&block.id(), None, None).await.unwrap(); + let _ = client.retry_until_included(&block_id, None, None).await.unwrap(); (block_id, transaction_id) } From 6a1cd28a0736a9ee68952eb3e72491440e77904a Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 31 Jul 2023 15:44:20 -0400 Subject: [PATCH 23/57] Rework BlockId into struct --- bindings/core/src/method/client.rs | 5 + bindings/core/src/method/utils.rs | 15 ++- bindings/core/src/method_handler/client.rs | 4 + bindings/core/src/method_handler/utils.rs | 18 +++- sdk/src/types/block/basic.rs | 3 +- sdk/src/types/block/block_id.rs | 103 ++++++++++++++++++++- sdk/src/types/block/core.rs | 21 ++--- sdk/src/types/block/protocol.rs | 26 ++++-- sdk/src/types/block/slot/index.rs | 5 +- 9 files changed, 163 insertions(+), 37 deletions(-) diff --git a/bindings/core/src/method/client.rs b/bindings/core/src/method/client.rs index 6336351f75..2e5b9c15a6 100644 --- a/bindings/core/src/method/client.rs +++ b/bindings/core/src/method/client.rs @@ -369,4 +369,9 @@ pub enum ClientMethod { /// The address for request funds address: Bech32Address, }, + /// Returns a block ID (Blake2b256 hash of block bytes) from a block + BlockId { + /// Block + block: BlockDto, + }, } diff --git a/bindings/core/src/method/utils.rs b/bindings/core/src/method/utils.rs index 311a2fe6d4..f656d539bd 100644 --- a/bindings/core/src/method/utils.rs +++ b/bindings/core/src/method/utils.rs @@ -10,6 +10,7 @@ use iota_sdk::types::block::{ TransactionId, }, signature::Ed25519Signature, + BlockDto, }; use serde::{Deserialize, Serialize}; @@ -76,11 +77,15 @@ pub enum UtilsMethod { #[derivative(Debug(format_with = "OmittedDebug::omitted_fmt"))] mnemonic: String, }, - // /// Returns a block ID (Blake2b256 hash of block bytes) from a block - // BlockId { - // /// Block - // block: BlockDto, - // }, + /// Returns a block ID (Blake2b256 hash of block bytes) from a block + BlockId { + /// Block + block: BlockDto, + /// Genesis timestamp at which the slots start to count. + genesis_unix_timestamp: u32, + /// Duration of each slot in seconds. + slot_duration_in_seconds: u8, + }, /// Returns the transaction ID (Blake2b256 hash of the provided transaction payload) TransactionId { /// Transaction Payload diff --git a/bindings/core/src/method_handler/client.rs b/bindings/core/src/method_handler/client.rs index e4f4aa7b86..818b7f72a1 100644 --- a/bindings/core/src/method_handler/client.rs +++ b/bindings/core/src/method_handler/client.rs @@ -341,6 +341,10 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM .await?; Response::CustomJson(data) } + ClientMethod::BlockId { block } => { + let protocol_params = client.get_protocol_parameters().await?; + Response::BlockId(Block::try_from_dto_with_params(block, &protocol_params)?.id(&protocol_params)) + } }; Ok(response) } diff --git a/bindings/core/src/method_handler/utils.rs b/bindings/core/src/method_handler/utils.rs index f296990cb6..5c436a7334 100644 --- a/bindings/core/src/method_handler/utils.rs +++ b/bindings/core/src/method_handler/utils.rs @@ -10,6 +10,8 @@ use iota_sdk::{ input::UtxoInput, output::{AccountId, FoundryId, InputsCommitment, NftId, Output, OutputId, Rent, TokenId}, payload::{transaction::TransactionEssence, TransactionPayload}, + protocol::slot_index, + Block, }, TryFromDto, }, @@ -36,10 +38,18 @@ pub(crate) fn call_utils_method_internal(method: UtilsMethod) -> Result { - // let block = Block::try_from_dto(block)?; - // Response::BlockId(block.id()) - // } + UtilsMethod::BlockId { + block, + genesis_unix_timestamp, + slot_duration_in_seconds, + } => { + let block = Block::try_from_dto(block)?; + Response::BlockId(block.hash().with_slot_index(slot_index( + block.issuing_time(), + genesis_unix_timestamp, + slot_duration_in_seconds, + ))) + } UtilsMethod::TransactionId { payload } => { let payload = TransactionPayload::try_from_dto(payload)?; Response::TransactionId(payload.id()) diff --git a/sdk/src/types/block/basic.rs b/sdk/src/types/block/basic.rs index 2be86256da..41a0682ede 100644 --- a/sdk/src/types/block/basic.rs +++ b/sdk/src/types/block/basic.rs @@ -1,10 +1,9 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use crypto::hashes::{blake2b::Blake2b256, Digest}; use packable::{ error::{UnpackError, UnpackErrorExt}, - packer::{Packer, SlicePacker}, + packer::Packer, unpacker::Unpacker, Packable, PackableExt, }; diff --git a/sdk/src/types/block/block_id.rs b/sdk/src/types/block/block_id.rs index 4920131b56..815262c75e 100644 --- a/sdk/src/types/block/block_id.rs +++ b/sdk/src/types/block/block_id.rs @@ -1,11 +1,104 @@ // Copyright 2020-2021 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -impl_id!( - pub BlockId, - 40, - "A block identifier, the BLAKE2b-256 hash of the block bytes. See for more information." -); +use super::{slot::SlotIndex, ConvertTo}; +use crate::types::block::Error; +impl_id!(pub BlockHash, 32, "The hash of a [`Block`]."); + +impl BlockHash { + pub fn with_slot_index(self, slot_index: SlotIndex) -> BlockId { + BlockId { hash: self, slot_index } + } +} + +/// A block identifier, the BLAKE2b-256 hash of the block bytes. See for more information. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Debug, packable::Packable)] +#[packable(unpack_error = Error)] +#[repr(C)] +pub struct BlockId { + pub(crate) hash: BlockHash, + pub(crate) slot_index: SlotIndex, +} + +impl BlockId { + /// The length of a [`BlockId`] + pub const LENGTH: usize = 40; + + pub fn new(bytes: [u8; Self::LENGTH]) -> Self { + unsafe { core::mem::transmute(bytes) } + } + + /// Creates a null [`BlockId`]. + pub fn null() -> Self { + Self::new([0u8; Self::LENGTH]) + } + + /// Checks if the [`BlockId`] is null. + pub fn is_null(&self) -> bool { + self.as_ref().iter().all(|&b| b == 0) + } + + /// Returns the [`BlockId`]'s slot index part. + pub fn slot_index(&self) -> SlotIndex { + self.slot_index + } +} + +impl AsRef<[u8]> for BlockId { + fn as_ref(&self) -> &[u8] { + unsafe { core::mem::transmute::<_, &[u8; Self::LENGTH]>(self) } + } +} + +impl core::str::FromStr for BlockId { + type Err = Error; + + fn from_str(s: &str) -> Result { + Ok(BlockId::new(prefix_hex::decode(s).map_err(Error::Hex)?)) + } +} + +impl core::fmt::Display for BlockId { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + prefix_hex::encode(self.as_ref()).fmt(f) + } +} + +impl TryFrom<&alloc::string::String> for BlockId { + type Error = Error; + + fn try_from(s: &alloc::string::String) -> Result { + core::str::FromStr::from_str(s.as_str()) + } +} + +impl TryFrom<&str> for BlockId { + type Error = Error; + + fn try_from(s: &str) -> Result { + core::str::FromStr::from_str(s) + } +} + +impl ConvertTo for &alloc::string::String { + fn convert(self) -> Result { + self.try_into() + } +} + +impl ConvertTo for &str { + fn convert(self) -> Result { + self.try_into() + } +} + +impl core::ops::Deref for BlockId { + type Target = [u8; Self::LENGTH]; + + fn deref(&self) -> &Self::Target { + unsafe { core::mem::transmute::<_, &[u8; Self::LENGTH]>(self) } + } +} #[cfg(feature = "serde")] string_serde_impl!(BlockId); diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index cf11e9c4f9..895d74e9ec 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -15,6 +15,7 @@ use packable::{ use super::{ basic::{BasicBlock, BasicBlockData}, + block_id::BlockHash, signature::Ed25519Signature, slot::{SlotCommitmentId, SlotIndex}, validation::{ValidationBlock, ValidationBlockData}, @@ -464,19 +465,21 @@ impl Block { matches!(self, Self::Validation(_)) } - /// Computes the identifier of the block. - #[inline(always)] - pub fn id(&self, protocol_parameters: &ProtocolParameters) -> BlockId { - let mut res = [0u8; 40]; + /// Computes the block hash. + pub fn hash(&self) -> BlockHash { let id = [ &self.header_hash()[..], &self.block_hash()[..], &self.signature_bytes()[..], ] .concat(); - res[..32].copy_from_slice(&*Blake2b256::digest(id)); - res[32..].copy_from_slice(&self.slot_index_bytes(protocol_parameters)); - BlockId::new(res) + BlockHash::new(Blake2b256::digest(id).into()) + } + + /// Computes the identifier of the block. + pub fn id(&self, protocol_parameters: &ProtocolParameters) -> BlockId { + self.hash() + .with_slot_index(protocol_parameters.slot_index(self.issuing_time())) } /// Unpacks a [`Block`] from a sequence of bytes doing syntactical checks and verifying that @@ -516,10 +519,6 @@ impl Block { self.signature().pack(&mut SlicePacker::new(&mut bytes)).unwrap(); bytes } - - pub(crate) fn slot_index_bytes(&self, protocol_parameters: &ProtocolParameters) -> [u8; 8] { - protocol_parameters.slot_index(self.issuing_time()).to_le_bytes() - } } pub(crate) fn verify_parents( diff --git a/sdk/src/types/block/protocol.rs b/sdk/src/types/block/protocol.rs index 9d40880c0d..1b8fc32132 100644 --- a/sdk/src/types/block/protocol.rs +++ b/sdk/src/types/block/protocol.rs @@ -21,26 +21,26 @@ use crate::types::block::{helper::network_name_to_id, output::RentStructure, Con pub struct ProtocolParameters { // The version of the protocol running. #[cfg_attr(feature = "serde", serde(rename = "version"))] - protocol_version: u8, + pub(crate) protocol_version: u8, // The human friendly name of the network. #[packable(unpack_error_with = |err| Error::InvalidNetworkName(err.into_item_err()))] #[cfg_attr(feature = "serde", serde(with = "crate::utils::serde::string_prefix"))] - network_name: StringPrefix, + pub(crate) network_name: StringPrefix, // The HRP prefix used for Bech32 addresses in the network. - bech32_hrp: Hrp, + pub(crate) bech32_hrp: Hrp, // The below max depth parameter of the network. - below_max_depth: u8, + pub(crate) below_max_depth: u8, // The rent structure used by given node/network. - rent_structure: RentStructure, + pub(crate) rent_structure: RentStructure, // TokenSupply defines the current token supply on the network. #[cfg_attr(feature = "serde", serde(with = "crate::utils::serde::string"))] - token_supply: u64, + pub(crate) token_supply: u64, // Genesis timestamp at which the slots start to count. #[cfg_attr(feature = "serde", serde(alias = "genesisUnixTimestamp"))] - genesis_unix_timestamp: u32, + pub(crate) genesis_unix_timestamp: u32, // Duration of each slot in seconds. #[cfg_attr(feature = "serde", serde(alias = "slotDurationInSeconds"))] - slot_duration_in_seconds: u8, + pub(crate) slot_duration_in_seconds: u8, } // This implementation is required to make [`ProtocolParameters`] a [`Packable`] visitor. @@ -136,7 +136,11 @@ impl ProtocolParameters { } pub fn slot_index(&self, timestamp: u64) -> SlotIndex { - (1 + (timestamp - self.genesis_unix_timestamp() as u64) / self.slot_duration_in_seconds() as u64).into() + slot_index( + timestamp, + self.genesis_unix_timestamp(), + self.slot_duration_in_seconds(), + ) } pub fn hash(&self) -> ProtocolParametersHash { @@ -144,6 +148,10 @@ impl ProtocolParameters { } } +pub fn slot_index(timestamp: u64, genesis_unix_timestamp: u32, slot_duration_in_seconds: u8) -> SlotIndex { + (1 + (timestamp - genesis_unix_timestamp as u64) / slot_duration_in_seconds as u64).into() +} + /// Returns a [`ProtocolParameters`] for testing purposes. #[cfg(any(feature = "test", feature = "rand"))] pub fn protocol_parameters() -> ProtocolParameters { diff --git a/sdk/src/types/block/slot/index.rs b/sdk/src/types/block/slot/index.rs index 8d92a4f5a1..019c96e106 100644 --- a/sdk/src/types/block/slot/index.rs +++ b/sdk/src/types/block/slot/index.rs @@ -6,7 +6,10 @@ use derive_more::{Deref, Display, From, FromStr}; /// Timeline is divided into slots, and each slot has a corresponding slot index. /// To calculate the slot index of a timestamp, `genesisTimestamp` and the duration of a slot are needed. /// The slot index of timestamp `ts` is `(ts - genesisTimestamp)/duration + 1`. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, From, Deref, Display, FromStr, packable::Packable)] +#[derive( + Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, From, Deref, Display, FromStr, packable::Packable, +)] +#[repr(transparent)] pub struct SlotIndex(u64); impl SlotIndex { From d3f5785506831719af6346c7346f1ebe466053b2 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Tue, 1 Aug 2023 09:16:34 -0400 Subject: [PATCH 24/57] serde with string --- sdk/src/types/api/core/response.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sdk/src/types/api/core/response.rs b/sdk/src/types/api/core/response.rs index cc0eeddfdf..a284dc045b 100644 --- a/sdk/src/types/api/core/response.rs +++ b/sdk/src/types/api/core/response.rs @@ -46,9 +46,13 @@ impl core::fmt::Display for InfoResponse { )] pub struct StatusResponse { pub is_healthy: bool, + #[cfg_attr(feature = "serde", serde(with = "crate::utils::serde::string"))] pub accepted_tangle_time: u64, + #[cfg_attr(feature = "serde", serde(with = "crate::utils::serde::string"))] pub relative_accepted_tangle_time: u64, + #[cfg_attr(feature = "serde", serde(with = "crate::utils::serde::string"))] pub confirmed_tangle_time: u64, + #[cfg_attr(feature = "serde", serde(with = "crate::utils::serde::string"))] pub relative_confirmed_tangle_time: u64, pub latest_committed_slot: SlotIndex, pub latest_finalized_slot: SlotIndex, From 64d70e0168c030651b0ebb417d1bbb03bce44d4a Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Tue, 1 Aug 2023 09:48:10 -0400 Subject: [PATCH 25/57] align dto to spec --- sdk/src/types/block/core.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index b13ffa6378..1dcfd53c02 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -576,8 +576,7 @@ pub(crate) mod dto { pub slot_commitment_id: SlotCommitmentId, pub latest_finalized_slot: SlotIndex, pub issuer_id: IssuerId, - #[serde(flatten)] - pub data: BlockDataDto, + pub block: BlockDataDto, pub signature: Ed25519Signature, } @@ -591,7 +590,7 @@ pub(crate) mod dto { slot_commitment_id: b.slot_commitment_id(), latest_finalized_slot: b.latest_finalized_slot(), issuer_id: b.issuer_id(), - data: (&b.data).into(), + block: (&b.data).into(), signature: *b.signature(), }, Block::Validation(b) => Self { @@ -601,7 +600,7 @@ pub(crate) mod dto { slot_commitment_id: b.slot_commitment_id(), latest_finalized_slot: b.latest_finalized_slot(), issuer_id: b.issuer_id(), - data: (&b.data).into(), + block: (&b.data).into(), signature: *b.signature(), }, } @@ -613,7 +612,7 @@ pub(crate) mod dto { type Error = Error; fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { - match dto.data { + match dto.block { BlockDataDto::Basic(b) => BlockBuilder::from_block_data( dto.network_id, dto.issuing_time, @@ -621,7 +620,7 @@ pub(crate) mod dto { dto.latest_finalized_slot, dto.issuer_id, BasicBlockData::try_from_dto_with_params_inner(b, params)?, - Ed25519Signature::try_from(dto.signature)?, + dto.signature, ) .with_protocol_version(dto.protocol_version) .finish(), @@ -632,7 +631,7 @@ pub(crate) mod dto { dto.latest_finalized_slot, dto.issuer_id, ValidationBlockData::try_from_dto_with_params_inner(b, params)?, - Ed25519Signature::try_from(dto.signature)?, + dto.signature, ) .with_protocol_version(dto.protocol_version) .finish(), From b3f98fc685f82e54436dbf74ea7858cb541122cf Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Tue, 1 Aug 2023 09:54:34 -0400 Subject: [PATCH 26/57] PR suggestions --- sdk/src/client/api/block_builder/mod.rs | 2 +- sdk/src/client/api/high_level.rs | 1 - .../types/api/plugins/participation/mod.rs | 1 - .../types/api/plugins/participation/types.rs | 31 +++++++++++-------- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/sdk/src/client/api/block_builder/mod.rs b/sdk/src/client/api/block_builder/mod.rs index 00381423dd..1331daafbc 100644 --- a/sdk/src/client/api/block_builder/mod.rs +++ b/sdk/src/client/api/block_builder/mod.rs @@ -19,7 +19,7 @@ impl ClientInner { strong_parents: Option, payload: Option, ) -> Result { - // Finish block without doing PoW. + // Use tips as strong parents if none are provided. let strong_parents = match strong_parents { Some(strong_parents) => strong_parents, None => StrongParents::from_vec(self.get_tips().await?)?, diff --git a/sdk/src/client/api/high_level.rs b/sdk/src/client/api/high_level.rs index 338ebb8059..0b6a7c6738 100644 --- a/sdk/src/client/api/high_level.rs +++ b/sdk/src/client/api/high_level.rs @@ -271,7 +271,6 @@ impl Client { *tip = *block_id; } - // Get block if we use remote Pow, because the node will change parents and nonce. let block = self.get_block(block_id).await?; let promote_block = self diff --git a/sdk/src/types/api/plugins/participation/mod.rs b/sdk/src/types/api/plugins/participation/mod.rs index 9a1e83d645..46680582a5 100644 --- a/sdk/src/types/api/plugins/participation/mod.rs +++ b/sdk/src/types/api/plugins/participation/mod.rs @@ -6,5 +6,4 @@ pub mod error; pub mod responses; -#[allow(non_camel_case_types)] pub mod types; diff --git a/sdk/src/types/api/plugins/participation/types.rs b/sdk/src/types/api/plugins/participation/types.rs index 8a589b6e8a..11ab9d79a7 100644 --- a/sdk/src/types/api/plugins/participation/types.rs +++ b/sdk/src/types/api/plugins/participation/types.rs @@ -19,20 +19,25 @@ use crate::types::{api::plugins::participation::error::Error, block::impl_id}; /// Participation tag. pub const PARTICIPATION_TAG: &str = "PARTICIPATE"; -/// Possible participation event types. -#[derive(Debug, Clone, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr), - serde(untagged) -)] -#[repr(u8)] -pub enum ParticipationEventType { - /// Voting event. - Voting = 0, - /// Staking event. - Staking = 1, +// This is needed because of the serde_repr macro generation >:( +#[allow(non_camel_case_types)] +mod participation_event_type { + /// Possible participation event types. + #[derive(Debug, Clone, Eq, PartialEq)] + #[cfg_attr( + feature = "serde", + derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr), + serde(untagged) + )] + #[repr(u8)] + pub enum ParticipationEventType { + /// Voting event. + Voting = 0, + /// Staking event. + Staking = 1, + } } +pub use participation_event_type::*; /// Wrapper interface containing a participation event ID and the corresponding event data. #[derive(Debug, Clone, Eq, PartialEq)] From 5dbdeea2ab9a0f728ed1edd42892439caef7249f Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 2 Aug 2023 08:18:27 -0400 Subject: [PATCH 27/57] PR suggs --- sdk/src/types/block/core.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 1dcfd53c02..60d7a90490 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -208,7 +208,7 @@ pub struct BlockWrapper { pub(crate) issuer_id: IssuerId, /// The inner block data, either [`BasicBlock`] or [`ValidationBlock`]. pub(crate) data: B, - /// + /// The block signature, used to validate issuance capabilities. pub(crate) signature: Ed25519Signature, } @@ -424,8 +424,8 @@ impl Block { matches!(self, Self::Basic(_)) } - /// Gets the block as an actual [`BasicBlock`]. - /// PANIC: do not call on a non-basic block. + /// Gets the block as an actual [`ValidationBlock`]. + /// PANIC: do not call on a non-validation block. pub fn as_validation(&self) -> &ValidationBlock { if let Self::Validation(block) = self { block From 6a0f90a12adb84ce78a8d63770e02ce68c46cd5c Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Thu, 3 Aug 2023 05:52:08 -0400 Subject: [PATCH 28/57] remove pub(crate) protocol params fields --- sdk/src/types/block/protocol.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sdk/src/types/block/protocol.rs b/sdk/src/types/block/protocol.rs index 1b8fc32132..6d96c1e57c 100644 --- a/sdk/src/types/block/protocol.rs +++ b/sdk/src/types/block/protocol.rs @@ -21,26 +21,26 @@ use crate::types::block::{helper::network_name_to_id, output::RentStructure, Con pub struct ProtocolParameters { // The version of the protocol running. #[cfg_attr(feature = "serde", serde(rename = "version"))] - pub(crate) protocol_version: u8, + protocol_version: u8, // The human friendly name of the network. #[packable(unpack_error_with = |err| Error::InvalidNetworkName(err.into_item_err()))] #[cfg_attr(feature = "serde", serde(with = "crate::utils::serde::string_prefix"))] - pub(crate) network_name: StringPrefix, + network_name: StringPrefix, // The HRP prefix used for Bech32 addresses in the network. - pub(crate) bech32_hrp: Hrp, + bech32_hrp: Hrp, // The below max depth parameter of the network. - pub(crate) below_max_depth: u8, + below_max_depth: u8, // The rent structure used by given node/network. - pub(crate) rent_structure: RentStructure, + rent_structure: RentStructure, // TokenSupply defines the current token supply on the network. #[cfg_attr(feature = "serde", serde(with = "crate::utils::serde::string"))] - pub(crate) token_supply: u64, + token_supply: u64, // Genesis timestamp at which the slots start to count. #[cfg_attr(feature = "serde", serde(alias = "genesisUnixTimestamp"))] - pub(crate) genesis_unix_timestamp: u32, + genesis_unix_timestamp: u32, // Duration of each slot in seconds. #[cfg_attr(feature = "serde", serde(alias = "slotDurationInSeconds"))] - pub(crate) slot_duration_in_seconds: u8, + slot_duration_in_seconds: u8, } // This implementation is required to make [`ProtocolParameters`] a [`Packable`] visitor. From 96213ae0cf6f820fbdb56052e2ea0396cec79517 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Thu, 3 Aug 2023 05:55:16 -0400 Subject: [PATCH 29/57] cleanup --- bindings/core/src/method_handler/utils.rs | 4 ++-- sdk/src/types/block/protocol.rs | 4 ++-- sdk/src/wallet/account/operations/retry.rs | 8 +++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/bindings/core/src/method_handler/utils.rs b/bindings/core/src/method_handler/utils.rs index 5c436a7334..f5f7058a74 100644 --- a/bindings/core/src/method_handler/utils.rs +++ b/bindings/core/src/method_handler/utils.rs @@ -10,7 +10,7 @@ use iota_sdk::{ input::UtxoInput, output::{AccountId, FoundryId, InputsCommitment, NftId, Output, OutputId, Rent, TokenId}, payload::{transaction::TransactionEssence, TransactionPayload}, - protocol::slot_index, + protocol::calc_slot_index, Block, }, TryFromDto, @@ -44,7 +44,7 @@ pub(crate) fn call_utils_method_internal(method: UtilsMethod) -> Result { let block = Block::try_from_dto(block)?; - Response::BlockId(block.hash().with_slot_index(slot_index( + Response::BlockId(block.hash().with_slot_index(calc_slot_index( block.issuing_time(), genesis_unix_timestamp, slot_duration_in_seconds, diff --git a/sdk/src/types/block/protocol.rs b/sdk/src/types/block/protocol.rs index 6d96c1e57c..f73c969bae 100644 --- a/sdk/src/types/block/protocol.rs +++ b/sdk/src/types/block/protocol.rs @@ -136,7 +136,7 @@ impl ProtocolParameters { } pub fn slot_index(&self, timestamp: u64) -> SlotIndex { - slot_index( + calc_slot_index( timestamp, self.genesis_unix_timestamp(), self.slot_duration_in_seconds(), @@ -148,7 +148,7 @@ impl ProtocolParameters { } } -pub fn slot_index(timestamp: u64, genesis_unix_timestamp: u32, slot_duration_in_seconds: u8) -> SlotIndex { +pub fn calc_slot_index(timestamp: u64, genesis_unix_timestamp: u32, slot_duration_in_seconds: u8) -> SlotIndex { (1 + (timestamp - genesis_unix_timestamp as u64) / slot_duration_in_seconds as u64).into() } diff --git a/sdk/src/wallet/account/operations/retry.rs b/sdk/src/wallet/account/operations/retry.rs index 18c6fbc270..6885bfa0ca 100644 --- a/sdk/src/wallet/account/operations/retry.rs +++ b/sdk/src/wallet/account/operations/retry.rs @@ -49,6 +49,8 @@ where ) -> crate::wallet::Result { log::debug!("[retry_transaction_until_included]"); + let protocol_params = self.client().get_protocol_parameters().await?; + let transaction = self.details().await.transactions.get(transaction_id).cloned(); if let Some(transaction) = transaction { @@ -78,7 +80,7 @@ where Some(Payload::Transaction(Box::new(transaction.payload.clone()))), ) .await? - .id(&self.client().get_protocol_parameters().await?), + .id(&protocol_params), }; // Attachments of the Block to check inclusion state @@ -124,7 +126,7 @@ where Some(Payload::Transaction(Box::new(transaction.payload.clone()))), ) .await?; - block_ids.push(reattached_block.id(&self.client().get_protocol_parameters().await?)); + block_ids.push(reattached_block.id(&protocol_params)); } } } @@ -139,7 +141,7 @@ where e } })?; - return Ok(included_block.id(&self.client().get_protocol_parameters().await?)); + return Ok(included_block.id(&protocol_params)); } } Err(ClientError::TangleInclusion(block_id.to_string()).into()) From 361c659ae4cd73d08d0f70e795fbbef1aba51ae6 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Fri, 4 Aug 2023 13:35:04 -0400 Subject: [PATCH 30/57] comments --- bindings/core/src/method/client.rs | 2 +- bindings/core/src/method/utils.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/core/src/method/client.rs b/bindings/core/src/method/client.rs index 2e5b9c15a6..e76c680e0d 100644 --- a/bindings/core/src/method/client.rs +++ b/bindings/core/src/method/client.rs @@ -369,7 +369,7 @@ pub enum ClientMethod { /// The address for request funds address: Bech32Address, }, - /// Returns a block ID (Blake2b256 hash of block bytes) from a block + /// Returns a block ID from a block BlockId { /// Block block: BlockDto, diff --git a/bindings/core/src/method/utils.rs b/bindings/core/src/method/utils.rs index f656d539bd..57dc6d4389 100644 --- a/bindings/core/src/method/utils.rs +++ b/bindings/core/src/method/utils.rs @@ -77,7 +77,7 @@ pub enum UtilsMethod { #[derivative(Debug(format_with = "OmittedDebug::omitted_fmt"))] mnemonic: String, }, - /// Returns a block ID (Blake2b256 hash of block bytes) from a block + /// Returns a block ID from a block and slot protocol parameters BlockId { /// Block block: BlockDto, From be166ebbec2f4fad551f4c4512b7ab80a84bb9d2 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Fri, 4 Aug 2023 14:16:59 -0400 Subject: [PATCH 31/57] fix tests --- sdk/src/types/block/block_id.rs | 5 ----- .../client/input_selection/account_outputs.rs | 2 +- .../client/input_selection/nft_outputs.rs | 2 +- sdk/tests/client/input_signing_data.rs | 5 +++-- sdk/tests/types/block_id.rs | 18 ++++++------------ sdk/tests/types/parents.rs | 4 ++-- sdk/tests/utils/serde.rs | 2 +- 7 files changed, 14 insertions(+), 24 deletions(-) diff --git a/sdk/src/types/block/block_id.rs b/sdk/src/types/block/block_id.rs index 815262c75e..ae3a20448d 100644 --- a/sdk/src/types/block/block_id.rs +++ b/sdk/src/types/block/block_id.rs @@ -29,11 +29,6 @@ impl BlockId { unsafe { core::mem::transmute(bytes) } } - /// Creates a null [`BlockId`]. - pub fn null() -> Self { - Self::new([0u8; Self::LENGTH]) - } - /// Checks if the [`BlockId`] is null. pub fn is_null(&self) -> bool { self.as_ref().iter().all(|&b| b == 0) diff --git a/sdk/tests/client/input_selection/account_outputs.rs b/sdk/tests/client/input_selection/account_outputs.rs index e103b6b297..6b25b5aa4e 100644 --- a/sdk/tests/client/input_selection/account_outputs.rs +++ b/sdk/tests/client/input_selection/account_outputs.rs @@ -208,7 +208,7 @@ fn basic_output_with_account_input() { let account_id_2 = AccountId::from_str(ACCOUNT_ID_2).unwrap(); let inputs = build_inputs([Account( - 2_255_500, + 2_259_500, account_id_2, 0, BECH32_ADDRESS_ED25519_0, diff --git a/sdk/tests/client/input_selection/nft_outputs.rs b/sdk/tests/client/input_selection/nft_outputs.rs index 6a4cd33e6f..d7c0033ea4 100644 --- a/sdk/tests/client/input_selection/nft_outputs.rs +++ b/sdk/tests/client/input_selection/nft_outputs.rs @@ -159,7 +159,7 @@ fn basic_output_with_nft_input() { let nft_id_2 = NftId::from_str(NFT_ID_2).unwrap(); let inputs = build_inputs([Nft( - 2_233_500, + 2_237_500, nft_id_2, BECH32_ADDRESS_ED25519_0, None, diff --git a/sdk/tests/client/input_signing_data.rs b/sdk/tests/client/input_signing_data.rs index d97d27be83..6f9630c0fa 100644 --- a/sdk/tests/client/input_signing_data.rs +++ b/sdk/tests/client/input_signing_data.rs @@ -38,7 +38,8 @@ fn input_signing_data_conversion() { let input_signing_data = InputSigningData { output, output_metadata: OutputMetadata::new( - BlockId::from_str("0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda").unwrap(), + BlockId::from_str("0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda0000000000000000") + .unwrap(), OutputId::from_str("0xbce525324af12eda02bf7927e92cea3a8e8322d0f41966271443e6c3b245a4400000").unwrap(), false, Some( @@ -71,7 +72,7 @@ fn input_signing_data_conversion() { InputSigningData::try_from_dto_with_params(input_signing_data_dto.clone(), &protocol_parameters).unwrap(); assert_eq!(input_signing_data, restored_input_signing_data); - let input_signing_data_dto_str = r#"{"output":{"type":3,"amount":"1000000","mana":"0","unlockConditions":[{"type":0,"address":{"type":0,"pubKeyHash":"0x7ffec9e1233204d9c6dce6812b1539ee96af691ca2e4d9065daa85907d33e5d3"}}]},"outputMetadata":{"blockId":"0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda","transactionId":"0xbce525324af12eda02bf7927e92cea3a8e8322d0f41966271443e6c3b245a440","outputIndex":0,"isSpent":false,"commitmentIdSpent":"0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689","transactionIdSpent":"0x24a1f46bdb6b2bf38f1c59f73cdd4ae5b418804bb231d76d06fbf246498d5883","includedCommitmentId":"0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689","latestCommitmentId":"0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689"},"chain":{"coinType":4219,"account":0,"change":0,"addressIndex":0}}"#; + let input_signing_data_dto_str = r#"{"output":{"type":3,"amount":"1000000","mana":"0","unlockConditions":[{"type":0,"address":{"type":0,"pubKeyHash":"0x7ffec9e1233204d9c6dce6812b1539ee96af691ca2e4d9065daa85907d33e5d3"}}]},"outputMetadata":{"blockId":"0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda0000000000000000","transactionId":"0xbce525324af12eda02bf7927e92cea3a8e8322d0f41966271443e6c3b245a440","outputIndex":0,"isSpent":false,"commitmentIdSpent":"0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689","transactionIdSpent":"0x24a1f46bdb6b2bf38f1c59f73cdd4ae5b418804bb231d76d06fbf246498d5883","includedCommitmentId":"0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689","latestCommitmentId":"0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689"},"chain":{"coinType":4219,"account":0,"change":0,"addressIndex":0}}"#; assert_eq!( serde_json::to_string(&input_signing_data_dto).unwrap(), input_signing_data_dto_str diff --git a/sdk/tests/types/block_id.rs b/sdk/tests/types/block_id.rs index 7159730a34..536420e55e 100644 --- a/sdk/tests/types/block_id.rs +++ b/sdk/tests/types/block_id.rs @@ -6,13 +6,15 @@ use core::str::FromStr; use iota_sdk::types::block::BlockId; use packable::PackableExt; -const BLOCK_ID: &str = "0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649"; +const BLOCK_ID: &str = "0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c6490000000000000000"; #[test] fn debug_impl() { assert_eq!( format!("{:?}", BlockId::from_str(BLOCK_ID).unwrap()), - "BlockId(0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649)" + format!( + "BlockId {{ hash: BlockHash(0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649), slot_index: SlotIndex(0) }}" + ) ); } @@ -21,14 +23,6 @@ fn from_str_valid() { BlockId::from_str(BLOCK_ID).unwrap(); } -#[test] -fn null() { - assert_eq!( - format!("{:?}", BlockId::null()), - "BlockId(0x0000000000000000000000000000000000000000000000000000000000000000)" - ); -} - #[test] fn from_to_str() { assert_eq!(BLOCK_ID, BlockId::from_str(BLOCK_ID).unwrap().to_string()); @@ -39,8 +33,8 @@ fn from_to_str() { fn packed_len() { let block_id = BlockId::from_str(BLOCK_ID).unwrap(); - assert_eq!(block_id.packed_len(), 32); - assert_eq!(block_id.pack_to_vec().len(), 32); + assert_eq!(block_id.packed_len(), 40); + assert_eq!(block_id.pack_to_vec().len(), 40); } // Validate that a `unpack` ∘ `pack` round-trip results in the original block id. diff --git a/sdk/tests/types/parents.rs b/sdk/tests/types/parents.rs index 378194abf9..e3c746ccbb 100644 --- a/sdk/tests/types/parents.rs +++ b/sdk/tests/types/parents.rs @@ -88,8 +88,8 @@ fn new_not_unique() { fn packed_len() { let parents = StrongParents::from_vec(rand_block_ids(5)).unwrap(); - assert_eq!(parents.packed_len(), 1 + 5 * 32); - assert_eq!(parents.pack_to_vec().len(), 1 + 5 * 32); + assert_eq!(parents.packed_len(), 1 + 5 * 40); + assert_eq!(parents.pack_to_vec().len(), 1 + 5 * 40); } #[test] diff --git a/sdk/tests/utils/serde.rs b/sdk/tests/utils/serde.rs index 4e6cb66369..a5719bed38 100644 --- a/sdk/tests/utils/serde.rs +++ b/sdk/tests/utils/serde.rs @@ -6,7 +6,7 @@ use core::str::FromStr; use iota_sdk::types::block::BlockId; use serde::{Deserialize, Serialize}; -const BLOCK_ID: &str = "0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649"; +const BLOCK_ID: &str = "0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c6490000000000000000"; #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] #[serde(rename_all = "camelCase")] From a36374f38d94540a33060fdb50e47d79ec34dff3 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 7 Aug 2023 09:35:04 -0400 Subject: [PATCH 32/57] Use Signature for serialized layouts --- sdk/src/types/block/block_id.rs | 2 +- sdk/src/types/block/core.rs | 19 ++++++++++--------- sdk/src/types/block/signature/mod.rs | 12 ++++++++++++ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/sdk/src/types/block/block_id.rs b/sdk/src/types/block/block_id.rs index ae3a20448d..dfe10fdc28 100644 --- a/sdk/src/types/block/block_id.rs +++ b/sdk/src/types/block/block_id.rs @@ -12,7 +12,7 @@ impl BlockHash { } } -/// A block identifier, the BLAKE2b-256 hash of the block bytes. See for more information. +/// A block identifier. #[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Debug, packable::Packable)] #[packable(unpack_error = Error)] #[repr(C)] diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 80aa0e32a1..3f5aefd290 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -16,7 +16,7 @@ use packable::{ use super::{ basic::{BasicBlock, BasicBlockData}, block_id::BlockHash, - signature::Ed25519Signature, + signature::{Ed25519Signature, Signature}, slot::{SlotCommitmentId, SlotIndex}, validation::{ValidationBlock, ValidationBlockData}, IssuerId, @@ -146,7 +146,7 @@ impl Packable for Block { let block = match kind { BasicBlock::KIND => { let data = BasicBlockData::unpack::<_, VERIFY>(unpacker, visitor)?; - let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; + let Signature::Ed25519(signature) = Signature::unpack::<_, VERIFY>(unpacker, &())?; Self::from(BlockWrapper { protocol_version, @@ -161,7 +161,7 @@ impl Packable for Block { } ValidationBlock::KIND => { let data = ValidationBlockData::unpack::<_, VERIFY>(unpacker, visitor)?; - let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; + let Signature::Ed25519(signature) = Signature::unpack::<_, VERIFY>(unpacker, &())?; Self::from(BlockWrapper { protocol_version, @@ -286,7 +286,8 @@ impl Block { + size_of::() + size_of::(); /// The length of the block signature. - pub const SIGNATURE_LENGTH: usize = Ed25519Signature::PUBLIC_KEY_LENGTH + Ed25519Signature::SIGNATURE_LENGTH; + pub const SIGNATURE_LENGTH: usize = + size_of::() + Ed25519Signature::PUBLIC_KEY_LENGTH + Ed25519Signature::SIGNATURE_LENGTH; /// Creates a new [`BlockBuilder`] to construct an instance of a [`BasicBlock`]. #[inline(always)] @@ -635,7 +636,7 @@ pub(crate) mod dto { pub latest_finalized_slot: SlotIndex, pub issuer_id: IssuerId, pub block: BlockDataDto, - pub signature: Ed25519Signature, + pub signature: Signature, } impl From<&Block> for BlockDto { @@ -649,7 +650,7 @@ pub(crate) mod dto { latest_finalized_slot: b.latest_finalized_slot(), issuer_id: b.issuer_id(), block: (&b.data).into(), - signature: *b.signature(), + signature: b.signature.into(), }, Block::Validation(b) => Self { protocol_version: b.protocol_version(), @@ -659,7 +660,7 @@ pub(crate) mod dto { latest_finalized_slot: b.latest_finalized_slot(), issuer_id: b.issuer_id(), block: (&b.data).into(), - signature: *b.signature(), + signature: b.signature.into(), }, } } @@ -678,7 +679,7 @@ pub(crate) mod dto { dto.latest_finalized_slot, dto.issuer_id, BasicBlockData::try_from_dto_with_params_inner(b, params)?, - dto.signature, + *dto.signature.as_ed25519(), ) .with_protocol_version(dto.protocol_version) .finish(), @@ -689,7 +690,7 @@ pub(crate) mod dto { dto.latest_finalized_slot, dto.issuer_id, ValidationBlockData::try_from_dto_with_params_inner(b, params)?, - dto.signature, + *dto.signature.as_ed25519(), ) .with_protocol_version(dto.protocol_version) .finish(), diff --git a/sdk/src/types/block/signature/mod.rs b/sdk/src/types/block/signature/mod.rs index fa7e47add4..c8086fe668 100644 --- a/sdk/src/types/block/signature/mod.rs +++ b/sdk/src/types/block/signature/mod.rs @@ -38,4 +38,16 @@ impl Signature { Self::Ed25519(_) => Ed25519Signature::KIND, } } + + /// Checks whether the signature is an [`Ed25519Signature`]. + pub fn is_ed25519(&self) -> bool { + matches!(self, Self::Ed25519(_)) + } + + /// Gets the signature as an actual [`Ed25519Signature`]. + /// PANIC: do not call on a non-ed25519 signature. + pub fn as_ed25519(&self) -> &Ed25519Signature { + let Self::Ed25519(sig) = self; + sig + } } From b00a99ee292b29be496ecd587c9b0d3a545d43d8 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 7 Aug 2023 09:46:37 -0400 Subject: [PATCH 33/57] more signature fixes --- sdk/src/types/block/basic.rs | 6 +++--- sdk/src/types/block/validation.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sdk/src/types/block/basic.rs b/sdk/src/types/block/basic.rs index 41a0682ede..f7c67a5690 100644 --- a/sdk/src/types/block/basic.rs +++ b/sdk/src/types/block/basic.rs @@ -13,7 +13,7 @@ use super::{ parent::{ShallowLikeParents, StrongParents, WeakParents}, payload::{OptionalPayload, Payload}, protocol::ProtocolParameters, - signature::Ed25519Signature, + signature::{Ed25519Signature, Signature}, slot::{SlotCommitmentId, SlotIndex}, Block, BlockBuilder, Error, IssuerId, PROTOCOL_VERSION, }; @@ -183,7 +183,7 @@ impl Packable for BasicBlock { self.pack_header(packer)?; Self::KIND.pack(packer)?; self.data.pack(packer)?; - self.signature.pack(packer)?; + Signature::Ed25519(self.signature).pack(packer)?; Ok(()) } @@ -221,7 +221,7 @@ impl Packable for BasicBlock { let data = BasicBlockData::unpack::<_, VERIFY>(unpacker, visitor)?; - let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; + let Signature::Ed25519(signature) = Signature::unpack::<_, VERIFY>(unpacker, &())?; let block = Self { protocol_version, diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs index 44f2f53ae1..1929c655f8 100644 --- a/sdk/src/types/block/validation.rs +++ b/sdk/src/types/block/validation.rs @@ -12,7 +12,7 @@ use super::{ core::{verify_parents, BlockWrapper}, parent::{ShallowLikeParents, StrongParents, WeakParents}, protocol::{ProtocolParameters, ProtocolParametersHash}, - signature::Ed25519Signature, + signature::{Ed25519Signature, Signature}, slot::{SlotCommitmentId, SlotIndex}, Block, BlockBuilder, Error, IssuerId, PROTOCOL_VERSION, }; @@ -177,7 +177,7 @@ impl Packable for ValidationBlock { self.issuer_id.pack(packer)?; Self::KIND.pack(packer)?; self.data.pack(packer)?; - self.signature.pack(packer)?; + Signature::Ed25519(self.signature).pack(packer)?; Ok(()) } @@ -215,7 +215,7 @@ impl Packable for ValidationBlock { let data = ValidationBlockData::unpack::<_, VERIFY>(unpacker, visitor)?; - let signature = Ed25519Signature::unpack::<_, VERIFY>(unpacker, &())?; + let Signature::Ed25519(signature) = Signature::unpack::<_, VERIFY>(unpacker, &())?; let block = Self { protocol_version, From 0b93f858b0fabc61f0f66e9f8bff2064e6e3a7ba Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 7 Aug 2023 11:33:37 -0400 Subject: [PATCH 34/57] Refactor block signature --- bindings/core/src/method_handler/client.rs | 37 ++++-- .../client/block/00_block_no_payload.rs | 7 +- .../block/01_block_confirmation_time.rs | 11 +- .../client/block/02_block_custom_parents.rs | 7 +- .../client/block/03_block_custom_payload.rs | 7 +- .../client/block/04_block_tagged_data.rs | 7 +- .../client/node_api_core/04_post_block.rs | 7 +- .../client/node_api_core/05_post_block_raw.rs | 7 +- sdk/src/client/api/block_builder/mod.rs | 27 ++-- sdk/src/client/api/high_level.rs | 81 +++++++++--- sdk/src/types/block/basic.rs | 25 ++-- sdk/src/types/block/core.rs | 117 +++++++++++++----- sdk/src/types/block/rand/block.rs | 21 +++- sdk/src/types/block/rand/signature.rs | 6 +- sdk/src/types/block/validation.rs | 21 +--- sdk/src/wallet/account/operations/balance.rs | 1 + .../account/operations/output_claiming.rs | 1 + .../operations/output_consolidation.rs | 1 + .../account/operations/output_finder.rs | 1 + .../operations/participation/voting.rs | 1 + .../operations/participation/voting_power.rs | 1 + sdk/src/wallet/account/operations/retry.rs | 23 +++- .../wallet/account/operations/syncing/mod.rs | 1 + .../operations/syncing/transactions.rs | 1 + .../burning_melting/melt_native_token.rs | 1 + .../transaction/high_level/create_account.rs | 1 + .../high_level/minting/create_native_token.rs | 1 + .../high_level/minting/mint_native_token.rs | 1 + .../high_level/minting/mint_nfts.rs | 1 + .../operations/transaction/high_level/send.rs | 1 + .../high_level/send_native_tokens.rs | 1 + .../transaction/high_level/send_nft.rs | 1 + .../account/operations/transaction/mod.rs | 1 + .../operations/transaction/prepare_output.rs | 1 + .../transaction/prepare_transaction.rs | 1 + .../transaction/sign_transaction.rs | 1 + .../transaction/submit_transaction.rs | 4 +- sdk/src/wallet/core/mod.rs | 6 + .../core/operations/account_recovery.rs | 1 + .../core/operations/address_generation.rs | 1 + .../core/operations/background_syncing.rs | 1 + sdk/tests/client/node_api/core.rs | 12 +- sdk/tests/client/node_api/mod.rs | 14 ++- sdk/tests/types/block.rs | 8 +- 44 files changed, 346 insertions(+), 132 deletions(-) diff --git a/bindings/core/src/method_handler/client.rs b/bindings/core/src/method_handler/client.rs index 818b7f72a1..88be11d69c 100644 --- a/bindings/core/src/method_handler/client.rs +++ b/bindings/core/src/method_handler/client.rs @@ -4,7 +4,7 @@ #[cfg(feature = "mqtt")] use iota_sdk::client::mqtt::{MqttPayload, Topic}; use iota_sdk::{ - client::{request_funds_from_faucet, Client}, + client::{request_funds_from_faucet, secret::SecretManager, Client}, types::{ api::core::response::OutputWithMetadataResponse, block::{ @@ -174,12 +174,13 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM ClientMethod::PostBlockPayload { payload } => { let protocol_params = client.get_protocol_parameters().await?; let block = client - .finish_basic_block_builder( + .finish_basic_block_builder::( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), None, Some(Payload::try_from_dto_with_params(payload, &protocol_params)?), + todo!("coin type"), + todo!("secret manager"), ) .await?; @@ -272,7 +273,9 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM .collect(), ), ClientMethod::Retry { block_id } => { - let (block_id, block) = client.retry(&block_id).await?; + let (block_id, block) = client + .retry::(&block_id, todo!("coin type"), todo!("secret manager")) + .await?; Response::BlockIdWithBlock(block_id, BlockDto::from(&block)) } ClientMethod::RetryUntilIncluded { @@ -280,7 +283,15 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM interval, max_attempts, } => { - let res = client.retry_until_included(&block_id, interval, max_attempts).await?; + let res = client + .retry_until_included::( + &block_id, + interval, + max_attempts, + todo!("coin type"), + todo!("secret manager"), + ) + .await?; let res = res .into_iter() .map(|(block_id, block)| (block_id, BlockDto::from(&block))) @@ -291,19 +302,27 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM Response::Inputs(client.find_inputs(addresses, amount).await?) } ClientMethod::Reattach { block_id } => { - let (block_id, block) = client.reattach(&block_id).await?; + let (block_id, block) = client + .reattach::(&block_id, todo!("coin type"), todo!("secret manager")) + .await?; Response::Reattached((block_id, BlockDto::from(&block))) } ClientMethod::ReattachUnchecked { block_id } => { - let (block_id, block) = client.reattach_unchecked(&block_id).await?; + let (block_id, block) = client + .reattach_unchecked::(&block_id, todo!("coin type"), todo!("secret manager")) + .await?; Response::Reattached((block_id, BlockDto::from(&block))) } ClientMethod::Promote { block_id } => { - let (block_id, block) = client.promote(&block_id).await?; + let (block_id, block) = client + .promote::(&block_id, todo!("coin type"), todo!("secret manager")) + .await?; Response::Promoted((block_id, BlockDto::from(&block))) } ClientMethod::PromoteUnchecked { block_id } => { - let (block_id, block) = client.promote_unchecked(&block_id).await?; + let (block_id, block) = client + .promote_unchecked::(&block_id, todo!("coin type"), todo!("secret manager")) + .await?; Response::Promoted((block_id, BlockDto::from(&block))) } ClientMethod::HexToBech32 { hex, bech32_hrp } => { diff --git a/sdk/examples/client/block/00_block_no_payload.rs b/sdk/examples/client/block/00_block_no_payload.rs index 27fef95026..6292985ff6 100644 --- a/sdk/examples/client/block/00_block_no_payload.rs +++ b/sdk/examples/client/block/00_block_no_payload.rs @@ -8,7 +8,7 @@ //! cargo run --release --example block_no_payload //! ``` -use iota_sdk::client::{Client, Result}; +use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; #[tokio::main] async fn main() -> Result<()> { @@ -20,16 +20,19 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let secret_manager = SecretManager::try_from_mnemonic(std::env::var("MNEMONIC").unwrap())?; + let protocol_parameters = client.get_protocol_parameters().await?; // Create and send the block. let block = client .finish_basic_block_builder( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), None, None, + IOTA_COIN_TYPE, + &secret_manager, ) .await?; diff --git a/sdk/examples/client/block/01_block_confirmation_time.rs b/sdk/examples/client/block/01_block_confirmation_time.rs index 5e663d88b9..1f23d92bb5 100644 --- a/sdk/examples/client/block/01_block_confirmation_time.rs +++ b/sdk/examples/client/block/01_block_confirmation_time.rs @@ -8,7 +8,7 @@ //! cargo run --release --example block_confirmation_time //! ``` -use iota_sdk::client::{Client, Result}; +use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; #[tokio::main] async fn main() -> Result<()> { @@ -20,16 +20,19 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let secret_manager = SecretManager::try_from_mnemonic(std::env::var("MNEMONIC").unwrap())?; + let protocol_parameters = client.get_protocol_parameters().await?; // Create and send a block. let block = client .finish_basic_block_builder( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), None, None, + IOTA_COIN_TYPE, + &secret_manager, ) .await?; let block_id = block.id(&protocol_parameters); @@ -37,7 +40,9 @@ async fn main() -> Result<()> { println!("{block:#?}"); // Try to check if the block has been confirmed. - client.retry_until_included(&block_id, None, None).await?; + client + .retry_until_included(&block_id, None, None, IOTA_COIN_TYPE, &secret_manager) + .await?; println!( "Block with no payload included: {}/block/{}", std::env::var("EXPLORER_URL").unwrap(), diff --git a/sdk/examples/client/block/02_block_custom_parents.rs b/sdk/examples/client/block/02_block_custom_parents.rs index dc92a93361..674c994509 100644 --- a/sdk/examples/client/block/02_block_custom_parents.rs +++ b/sdk/examples/client/block/02_block_custom_parents.rs @@ -9,7 +9,7 @@ //! ``` use iota_sdk::{ - client::{Client, Result}, + client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}, types::block::parent::StrongParents, }; @@ -23,6 +23,8 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let secret_manager = SecretManager::try_from_mnemonic(std::env::var("MNEMONIC").unwrap())?; + let protocol_parameters = client.get_protocol_parameters().await?; // Use tips as custom parents. @@ -33,10 +35,11 @@ async fn main() -> Result<()> { let block = client .finish_basic_block_builder( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), Some(StrongParents::from_vec(tips)?), None, + IOTA_COIN_TYPE, + &secret_manager, ) .await?; diff --git a/sdk/examples/client/block/03_block_custom_payload.rs b/sdk/examples/client/block/03_block_custom_payload.rs index 6403d4209d..d00ccf5309 100644 --- a/sdk/examples/client/block/03_block_custom_payload.rs +++ b/sdk/examples/client/block/03_block_custom_payload.rs @@ -9,7 +9,7 @@ //! ``` use iota_sdk::{ - client::{Client, Result}, + client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}, types::block::payload::{Payload, TaggedDataPayload}, }; @@ -23,6 +23,8 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let secret_manager = SecretManager::try_from_mnemonic(std::env::var("MNEMONIC").unwrap())?; + let protocol_parameters = client.get_protocol_parameters().await?; // Create a custom payload. @@ -32,10 +34,11 @@ async fn main() -> Result<()> { let block = client .finish_basic_block_builder( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), None, Some(Payload::from(tagged_data_payload)), + IOTA_COIN_TYPE, + &secret_manager, ) .await?; diff --git a/sdk/examples/client/block/04_block_tagged_data.rs b/sdk/examples/client/block/04_block_tagged_data.rs index e0a8e4ded6..c670d1d670 100644 --- a/sdk/examples/client/block/04_block_tagged_data.rs +++ b/sdk/examples/client/block/04_block_tagged_data.rs @@ -9,7 +9,7 @@ //! ``` use iota_sdk::{ - client::{Client, Result}, + client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}, types::block::payload::{Payload, TaggedDataPayload}, }; @@ -23,13 +23,14 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let secret_manager = SecretManager::try_from_mnemonic(std::env::var("MNEMONIC").unwrap())?; + let protocol_parameters = client.get_protocol_parameters().await?; // Create and send the block with tag and data. let block = client .finish_basic_block_builder( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), None, Some(Payload::TaggedData(Box::new( @@ -45,6 +46,8 @@ async fn main() -> Result<()> { ) .unwrap(), ))), + IOTA_COIN_TYPE, + &secret_manager, ) .await?; diff --git a/sdk/examples/client/node_api_core/04_post_block.rs b/sdk/examples/client/node_api_core/04_post_block.rs index 17b277fe9f..b2ecb1d16d 100644 --- a/sdk/examples/client/node_api_core/04_post_block.rs +++ b/sdk/examples/client/node_api_core/04_post_block.rs @@ -8,7 +8,7 @@ //! cargo run --release --example node_api_core_post_block [NODE URL] //! ``` -use iota_sdk::client::{Client, Result}; +use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; #[tokio::main] async fn main() -> Result<()> { @@ -23,14 +23,17 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let secret_manager = SecretManager::try_from_mnemonic(std::env::var("MNEMONIC").unwrap())?; + // Create the block. let block = client .finish_basic_block_builder( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), None, None, + IOTA_COIN_TYPE, + &secret_manager, ) .await?; // Post the block. diff --git a/sdk/examples/client/node_api_core/05_post_block_raw.rs b/sdk/examples/client/node_api_core/05_post_block_raw.rs index c93f8129c8..b7a556c7e5 100644 --- a/sdk/examples/client/node_api_core/05_post_block_raw.rs +++ b/sdk/examples/client/node_api_core/05_post_block_raw.rs @@ -8,7 +8,7 @@ //! cargo run --release --example node_api_core_post_block_raw [NODE URL] //! ``` -use iota_sdk::client::{Client, Result}; +use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; #[tokio::main] async fn main() -> Result<()> { @@ -23,14 +23,17 @@ async fn main() -> Result<()> { // Create a node client. let client = Client::builder().with_node(&node_url)?.finish().await?; + let secret_manager = SecretManager::try_from_mnemonic(std::env::var("MNEMONIC").unwrap())?; + // Create the block. let block = client .finish_basic_block_builder( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), None, None, + IOTA_COIN_TYPE, + &secret_manager, ) .await?; // Post the block as raw bytes. diff --git a/sdk/src/client/api/block_builder/mod.rs b/sdk/src/client/api/block_builder/mod.rs index 1331daafbc..9b3d26ed0b 100644 --- a/sdk/src/client/api/block_builder/mod.rs +++ b/sdk/src/client/api/block_builder/mod.rs @@ -4,21 +4,27 @@ pub mod input_selection; pub mod transaction; +use crypto::keys::bip44::Bip44; + pub use self::transaction::verify_semantic; use crate::{ - client::{ClientInner, Result}, - types::block::{core::Block, parent::StrongParents, payload::Payload, signature::Ed25519Signature, IssuerId}, + client::{secret::SecretManage, ClientInner, Result}, + types::block::{core::Block, parent::StrongParents, payload::Payload, IssuerId}, }; impl ClientInner { - pub async fn finish_basic_block_builder( + pub async fn finish_basic_block_builder( &self, issuer_id: IssuerId, - signature: Ed25519Signature, issuing_time: Option, strong_parents: Option, payload: Option, - ) -> Result { + coin_type: u32, + secret_manager: &S, + ) -> Result + where + crate::client::Error: From, + { // Use tips as strong parents if none are provided. let strong_parents = match strong_parents { Some(strong_parents) => strong_parents, @@ -42,16 +48,19 @@ impl ClientInner { let latest_finalized_slot = node_info.status.latest_finalized_slot; let slot_commitment_id = self.get_slot_commitment_by_index(latest_finalized_slot).await?.id(); - Ok(Block::build_basic( + let builder = Block::build_basic( self.get_network_id().await?, issuing_time, slot_commitment_id, latest_finalized_slot, issuer_id, strong_parents, - signature, ) - .with_payload(payload) - .finish()?) + .with_payload(payload); + let signature = secret_manager + .sign_ed25519(&builder.signing_input(), Bip44::new(coin_type)) + .await?; + + Ok(builder.finish(signature)?) } } diff --git a/sdk/src/client/api/high_level.rs b/sdk/src/client/api/high_level.rs index 922cc4f425..9d6867d470 100644 --- a/sdk/src/client/api/high_level.rs +++ b/sdk/src/client/api/high_level.rs @@ -13,6 +13,7 @@ use crate::{ }, error::{Error, Result}, node_api::indexer::query_parameters::QueryParameter, + secret::SecretManage, Client, }, types::{ @@ -66,13 +67,21 @@ impl Client { /// Retries (promotes or reattaches) a block for provided block id. Block should only be /// retried only if they are valid and haven't been confirmed for a while. - pub async fn retry(&self, block_id: &BlockId) -> Result<(BlockId, Block)> { + pub async fn retry( + &self, + block_id: &BlockId, + coin_type: u32, + secret_manager: &S, + ) -> Result<(BlockId, Block)> + where + crate::client::Error: From, + { // Get the metadata to check if it needs to promote or reattach let block_metadata = self.get_block_metadata(block_id).await?; if block_metadata.should_promote.unwrap_or(false) { - self.promote_unchecked(block_id).await + self.promote_unchecked(block_id, coin_type, secret_manager).await } else if block_metadata.should_reattach.unwrap_or(false) { - self.reattach_unchecked(block_id).await + self.reattach_unchecked(block_id, coin_type, secret_manager).await } else { Err(Error::NoNeedPromoteOrReattach(block_id.to_string())) } @@ -81,12 +90,17 @@ impl Client { /// Retries (promotes or reattaches) a block for provided block id until it's included (referenced by a /// milestone). Default interval is 5 seconds and max attempts is 40. Returns the included block at first position /// and additional reattached blocks - pub async fn retry_until_included( + pub async fn retry_until_included( &self, block_id: &BlockId, interval: Option, max_attempts: Option, - ) -> Result> { + coin_type: u32, + secret_manager: &S, + ) -> Result> + where + crate::client::Error: From, + { log::debug!("[retry_until_included]"); // Attachments of the Block to check inclusion state let mut block_ids = vec![*block_id]; @@ -136,10 +150,13 @@ impl Client { if index == block_ids_len - 1 { if block_metadata.should_promote.unwrap_or(false) { // Safe to unwrap since we iterate over it - self.promote_unchecked(block_ids.last().unwrap()).await?; + self.promote_unchecked(block_ids.last().unwrap(), coin_type, secret_manager) + .await?; } else if block_metadata.should_reattach.unwrap_or(false) { // Safe to unwrap since we iterate over it - let reattached = self.reattach_unchecked(block_ids.last().unwrap()).await?; + let reattached = self + .reattach_unchecked(block_ids.last().unwrap(), coin_type, secret_manager) + .await?; block_ids.push(reattached.0); blocks_with_id.push(reattached); } @@ -226,26 +243,43 @@ impl Client { /// Reattaches blocks for provided block id. Blocks can be reattached only if they are valid and haven't been /// confirmed for a while. - pub async fn reattach(&self, block_id: &BlockId) -> Result<(BlockId, Block)> { + pub async fn reattach( + &self, + block_id: &BlockId, + coin_type: u32, + secret_manager: &S, + ) -> Result<(BlockId, Block)> + where + crate::client::Error: From, + { let metadata = self.get_block_metadata(block_id).await?; if metadata.should_reattach.unwrap_or(false) { - self.reattach_unchecked(block_id).await + self.reattach_unchecked(block_id, coin_type, secret_manager).await } else { Err(Error::NoNeedPromoteOrReattach(block_id.to_string())) } } /// Reattach a block without checking if it should be reattached - pub async fn reattach_unchecked(&self, block_id: &BlockId) -> Result<(BlockId, Block)> { + pub async fn reattach_unchecked( + &self, + block_id: &BlockId, + coin_type: u32, + secret_manager: &S, + ) -> Result<(BlockId, Block)> + where + crate::client::Error: From, + { // Get the Block object by the BlockID. let block = self.get_block(block_id).await?; let reattach_block = self .finish_basic_block_builder( block.issuer_id(), - *block.signature(), None, None, block.payload().cloned(), + coin_type, + secret_manager, ) .await?; @@ -257,17 +291,33 @@ impl Client { /// Promotes a block. The method should validate if a promotion is necessary through get_block. If not, the /// method should error out and should not allow unnecessary promotions. - pub async fn promote(&self, block_id: &BlockId) -> Result<(BlockId, Block)> { + pub async fn promote( + &self, + block_id: &BlockId, + coin_type: u32, + secret_manager: &S, + ) -> Result<(BlockId, Block)> + where + crate::client::Error: From, + { let metadata = self.get_block_metadata(block_id).await?; if metadata.should_promote.unwrap_or(false) { - self.promote_unchecked(block_id).await + self.promote_unchecked(block_id, coin_type, secret_manager).await } else { Err(Error::NoNeedPromoteOrReattach(block_id.to_string())) } } /// Promote a block without checking if it should be promoted - pub async fn promote_unchecked(&self, block_id: &BlockId) -> Result<(BlockId, Block)> { + pub async fn promote_unchecked( + &self, + block_id: &BlockId, + coin_type: u32, + secret_manager: &S, + ) -> Result<(BlockId, Block)> + where + crate::client::Error: From, + { // Create a new block (zero value block) for which one tip would be the actual block. let mut tips = self.get_tips().await?; if let Some(tip) = tips.first_mut() { @@ -279,10 +329,11 @@ impl Client { let promote_block = self .finish_basic_block_builder( block.issuer_id(), - *block.signature(), None, Some(Parents::from_vec(tips)?), None, + coin_type, + secret_manager, ) .await?; diff --git a/sdk/src/types/block/basic.rs b/sdk/src/types/block/basic.rs index f7c67a5690..1dc5c25e1a 100644 --- a/sdk/src/types/block/basic.rs +++ b/sdk/src/types/block/basic.rs @@ -13,14 +13,14 @@ use super::{ parent::{ShallowLikeParents, StrongParents, WeakParents}, payload::{OptionalPayload, Payload}, protocol::ProtocolParameters, - signature::{Ed25519Signature, Signature}, + signature::Signature, slot::{SlotCommitmentId, SlotIndex}, Block, BlockBuilder, Error, IssuerId, PROTOCOL_VERSION, }; pub type BasicBlock = BlockWrapper; -impl BlockBuilder { +impl BlockBuilder { /// Creates a new [`BlockBuilder`] for a [`BasicBlock`]. #[inline(always)] pub fn new( @@ -30,9 +30,8 @@ impl BlockBuilder { latest_finalized_slot: SlotIndex, issuer_id: IssuerId, strong_parents: StrongParents, - signature: Ed25519Signature, ) -> Self { - Self(BlockWrapper { + Self { protocol_version: PROTOCOL_VERSION, network_id, issuing_time, @@ -46,42 +45,34 @@ impl BlockBuilder { payload: OptionalPayload::default(), burned_mana: Default::default(), }, - signature, - }) - } - - /// Adds a protocol version to a [`BlockBuilder`]. - #[inline(always)] - pub fn with_protocol_version(mut self, protocol_version: u8) -> Self { - self.0.protocol_version = protocol_version; - self + } } /// Adds weak parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { - self.0.data.weak_parents = weak_parents.into(); + self.data.weak_parents = weak_parents.into(); self } /// Adds shallow like parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { - self.0.data.shallow_like_parents = shallow_like_parents.into(); + self.data.shallow_like_parents = shallow_like_parents.into(); self } /// Adds a payload to a [`BlockBuilder`]. #[inline(always)] pub fn with_payload(mut self, payload: impl Into) -> Self { - self.0.data.payload = payload.into(); + self.data.payload = payload.into(); self } /// Adds burned mana to a [`BlockBuilder`]. #[inline(always)] pub fn with_burned_mana(mut self, burned_mana: u64) -> Self { - self.0.data.burned_mana = burned_mana; + self.data.burned_mana = burned_mana; self } } diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 3f5aefd290..a80b5edfbe 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -25,44 +25,75 @@ use crate::types::block::{ parent::{ShallowLikeParents, StrongParents, WeakParents}, payload::Payload, protocol::ProtocolParameters, - BlockId, Error, PROTOCOL_VERSION, + BlockId, Error, }; /// A builder to build a [`Block`]. #[derive(Clone)] #[must_use] -pub struct BlockBuilder(pub(crate) B); +pub struct BlockBuilder { + /// Protocol version of the block. + pub(crate) protocol_version: u8, + /// Network identifier. + pub(crate) network_id: u64, + /// The time at which the block was issued. It is a Unix timestamp in nanoseconds. + pub(crate) issuing_time: u64, + /// The identifier of the slot to which this block commits. + pub(crate) slot_commitment_id: SlotCommitmentId, + /// The slot index of the latest finalized slot. + pub(crate) latest_finalized_slot: SlotIndex, + /// The identifier of the account that issued this block. + pub(crate) issuer_id: IssuerId, + /// The inner block data, either [`BasicBlock`] or [`ValidationBlock`]. + pub(crate) data: B, +} -impl BlockBuilder> { +impl BlockBuilder { pub fn from_block_data( + protocol_version: u8, network_id: u64, issuing_time: u64, slot_commitment_id: SlotCommitmentId, latest_finalized_slot: SlotIndex, issuer_id: IssuerId, data: B, - signature: Ed25519Signature, ) -> Self { - Self(BlockWrapper { - protocol_version: PROTOCOL_VERSION, + Self { + protocol_version, network_id, issuing_time, slot_commitment_id, latest_finalized_slot, issuer_id, data, - signature, - }) + } + } + + /// Adds a protocol version to a [`BlockBuilder`]. + #[inline(always)] + pub fn with_protocol_version(mut self, protocol_version: u8) -> Self { + self.protocol_version = protocol_version; + self } } impl BlockBuilder where B: Packable, - Block: From, + Block: From>, { - fn _finish(self) -> Result<(Block, Vec), Error> { - let block = Block::from(self.0); + fn _finish(self, signature: Ed25519Signature) -> Result<(Block, Vec), Error> { + let wrapper = BlockWrapper { + protocol_version: self.protocol_version, + network_id: self.network_id, + issuing_time: self.issuing_time, + slot_commitment_id: self.slot_commitment_id, + latest_finalized_slot: self.latest_finalized_slot, + issuer_id: self.issuer_id, + data: self.data, + signature, + }; + let block = Block::from(wrapper); verify_parents( block.strong_parents(), @@ -80,8 +111,36 @@ where } /// Finishes the [`BlockBuilder`] into a [`Block`]. - pub fn finish(self) -> Result { - self._finish().map(|res| res.0) + pub fn finish(self, signature: Ed25519Signature) -> Result { + self._finish(signature).map(|res| res.0) + } +} + +impl BlockBuilder { + pub(crate) fn pack_header(&self, packer: &mut P) -> Result<(), P::Error> { + self.protocol_version.pack(packer)?; + self.network_id.pack(packer)?; + self.issuing_time.pack(packer)?; + self.slot_commitment_id.pack(packer)?; + self.latest_finalized_slot.pack(packer)?; + self.issuer_id.pack(packer)?; + Ok(()) + } + + pub(crate) fn header_hash(&self) -> [u8; 32] { + let mut bytes = [0u8; Block::HEADER_LENGTH]; + self.pack_header(&mut SlicePacker::new(&mut bytes)).unwrap(); + Blake2b256::digest(bytes).into() + } + + pub(crate) fn block_hash(&self) -> [u8; 32] { + let bytes = self.data.pack_to_vec(); + Blake2b256::digest(bytes).into() + } + + /// Get the signing input that can be used to generate an [`Ed25519Signature`] for the resulting block; + pub fn signing_input(&self) -> Vec { + [self.header_hash(), self.block_hash()].concat() } } @@ -256,7 +315,9 @@ impl BlockWrapper { pub fn signature(&self) -> &Ed25519Signature { &self.signature } +} +impl BlockWrapper { pub(crate) fn pack_header(&self, packer: &mut P) -> Result<(), P::Error> { self.protocol_version.pack(packer)?; self.network_id.pack(packer)?; @@ -272,6 +333,11 @@ impl BlockWrapper { self.pack_header(&mut SlicePacker::new(&mut bytes)).unwrap(); Blake2b256::digest(bytes).into() } + + pub(crate) fn block_hash(&self) -> [u8; 32] { + let bytes = self.data.pack_to_vec(); + Blake2b256::digest(bytes).into() + } } impl Block { @@ -298,16 +364,14 @@ impl Block { latest_finalized_slot: SlotIndex, issuer_id: IssuerId, strong_parents: StrongParents, - signature: Ed25519Signature, - ) -> BlockBuilder { - BlockBuilder::::new( + ) -> BlockBuilder { + BlockBuilder::::new( network_id, issuing_time, slot_commitment_id, latest_finalized_slot, issuer_id, strong_parents, - signature, ) } @@ -323,8 +387,8 @@ impl Block { highest_supported_version: u8, protocol_parameters: &ProtocolParameters, signature: Ed25519Signature, - ) -> BlockBuilder { - BlockBuilder::::new( + ) -> BlockBuilder { + BlockBuilder::::new( network_id, issuing_time, slot_commitment_id, @@ -333,7 +397,6 @@ impl Block { strong_parents, highest_supported_version, protocol_parameters, - signature, ) } @@ -509,8 +572,8 @@ impl Block { pub(crate) fn block_hash(&self) -> [u8; 32] { let bytes = match self { - Block::Basic(b) => b.data.pack_to_vec(), - Block::Validation(b) => b.data.pack_to_vec(), + Block::Basic(b) => b.block_hash(), + Block::Validation(b) => b.block_hash(), }; Blake2b256::digest(bytes).into() } @@ -673,27 +736,25 @@ pub(crate) mod dto { fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result { match dto.block { BlockDataDto::Basic(b) => BlockBuilder::from_block_data( + dto.protocol_version, dto.network_id, dto.issuing_time, dto.slot_commitment_id, dto.latest_finalized_slot, dto.issuer_id, BasicBlockData::try_from_dto_with_params_inner(b, params)?, - *dto.signature.as_ed25519(), ) - .with_protocol_version(dto.protocol_version) - .finish(), + .finish(*dto.signature.as_ed25519()), BlockDataDto::Validation(b) => BlockBuilder::from_block_data( + dto.protocol_version, dto.network_id, dto.issuing_time, dto.slot_commitment_id, dto.latest_finalized_slot, dto.issuer_id, ValidationBlockData::try_from_dto_with_params_inner(b, params)?, - *dto.signature.as_ed25519(), ) - .with_protocol_version(dto.protocol_version) - .finish(), + .finish(*dto.signature.as_ed25519()), } } } diff --git a/sdk/src/types/block/rand/block.rs b/sdk/src/types/block/rand/block.rs index 187dafc370..5c7cb5cbfa 100644 --- a/sdk/src/types/block/rand/block.rs +++ b/sdk/src/types/block/rand/block.rs @@ -3,9 +3,9 @@ use alloc::vec::Vec; -use super::signature::rand_ed25519_signature; +use super::signature::rand_sign_ed25519; use crate::types::block::{ - basic::BasicBlock, + basic::BasicBlockData, core::Block, parent::StrongParents, rand::{ @@ -30,12 +30,11 @@ pub fn rand_block_ids(len: usize) -> Vec { pub fn rand_basic_block_with_strong_parents(strong_parents: StrongParents) -> Block { rand_basic_block_builder_with_strong_parents(strong_parents) .with_payload(rand_payload_for_block()) - .finish() - .unwrap() + .sign_random() } /// Generates a random basic block builder with given parents. -pub fn rand_basic_block_builder_with_strong_parents(strong_parents: StrongParents) -> BlockBuilder { +pub fn rand_basic_block_builder_with_strong_parents(strong_parents: StrongParents) -> BlockBuilder { Block::build_basic( rand_number(), rand_number(), @@ -43,7 +42,6 @@ pub fn rand_basic_block_builder_with_strong_parents(strong_parents: StrongParent rand_number::().into(), rand_bytes_array().into(), strong_parents, - rand_ed25519_signature(), ) } @@ -51,3 +49,14 @@ pub fn rand_basic_block_builder_with_strong_parents(strong_parents: StrongParent pub fn rand_block() -> Block { rand_basic_block_with_strong_parents(rand_strong_parents()) } + +pub trait SignBlockRandom { + fn sign_random(self) -> Block; +} + +impl SignBlockRandom for BlockBuilder { + fn sign_random(self) -> Block { + let signing_input = self.signing_input(); + self.finish(rand_sign_ed25519(&signing_input)).unwrap() + } +} diff --git a/sdk/src/types/block/rand/signature.rs b/sdk/src/types/block/rand/signature.rs index 9fe679ebc4..07504c4c8a 100644 --- a/sdk/src/types/block/rand/signature.rs +++ b/sdk/src/types/block/rand/signature.rs @@ -13,6 +13,10 @@ use super::bytes::{rand_bytes, rand_bytes_array}; use crate::types::block::signature::{Ed25519Signature, Signature}; pub fn rand_ed25519_signature() -> Ed25519Signature { + rand_sign_ed25519(&rand_bytes(64)) +} + +pub fn rand_sign_ed25519(msg: &[u8]) -> Ed25519Signature { let mnemonic = wordlist::encode(&rand_bytes_array::<32>(), &wordlist::ENGLISH).unwrap(); let seed = Seed::from(mnemonic_to_seed(&mnemonic, &Passphrase::default())); let chain = [0; 5]; @@ -20,7 +24,7 @@ pub fn rand_ed25519_signature() -> Ed25519Signature { .derive::(chain.into_iter().map(Segment::harden)) .secret_key(); let public_key = private_key.public_key(); - let signature = private_key.sign(&rand_bytes(64)); + let signature = private_key.sign(msg); Ed25519Signature::new(public_key.into(), signature) } diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs index 1929c655f8..24a16e69a3 100644 --- a/sdk/src/types/block/validation.rs +++ b/sdk/src/types/block/validation.rs @@ -12,14 +12,14 @@ use super::{ core::{verify_parents, BlockWrapper}, parent::{ShallowLikeParents, StrongParents, WeakParents}, protocol::{ProtocolParameters, ProtocolParametersHash}, - signature::{Ed25519Signature, Signature}, + signature::Signature, slot::{SlotCommitmentId, SlotIndex}, Block, BlockBuilder, Error, IssuerId, PROTOCOL_VERSION, }; pub type ValidationBlock = BlockWrapper; -impl BlockBuilder { +impl BlockBuilder { /// Creates a new [`BlockBuilder`] for a [`ValidationBlock`]. #[inline(always)] pub fn new( @@ -31,9 +31,8 @@ impl BlockBuilder { strong_parents: StrongParents, highest_supported_version: u8, protocol_parameters: &ProtocolParameters, - signature: Ed25519Signature, ) -> Self { - Self(BlockWrapper { + Self { protocol_version: PROTOCOL_VERSION, network_id, issuing_time, @@ -47,28 +46,20 @@ impl BlockBuilder { highest_supported_version, protocol_parameters_hash: protocol_parameters.hash(), }, - signature, - }) - } - - /// Adds a protocol version to a [`BlockBuilder`]. - #[inline(always)] - pub fn with_protocol_version(mut self, protocol_version: u8) -> Self { - self.0.protocol_version = protocol_version; - self + } } /// Adds weak parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { - self.0.data.weak_parents = weak_parents.into(); + self.data.weak_parents = weak_parents.into(); self } /// Adds shallow like parents to a [`BlockBuilder`]. #[inline(always)] pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { - self.0.data.shallow_like_parents = shallow_like_parents.into(); + self.data.shallow_like_parents = shallow_like_parents.into(); self } } diff --git a/sdk/src/wallet/account/operations/balance.rs b/sdk/src/wallet/account/operations/balance.rs index 09df04f29a..ed2e6b2114 100644 --- a/sdk/src/wallet/account/operations/balance.rs +++ b/sdk/src/wallet/account/operations/balance.rs @@ -23,6 +23,7 @@ use crate::{ impl Account where Error: From, + crate::client::Error: From, { /// Get the balance of the account. pub async fn balance(&self) -> Result { diff --git a/sdk/src/wallet/account/operations/output_claiming.rs b/sdk/src/wallet/account/operations/output_claiming.rs index b2f3d30a5b..01ab1b85a4 100644 --- a/sdk/src/wallet/account/operations/output_claiming.rs +++ b/sdk/src/wallet/account/operations/output_claiming.rs @@ -35,6 +35,7 @@ pub enum OutputsToClaim { impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Get basic and nft outputs that have /// [`ExpirationUnlockCondition`](crate::types::block::output::unlock_condition::ExpirationUnlockCondition), diff --git a/sdk/src/wallet/account/operations/output_consolidation.rs b/sdk/src/wallet/account/operations/output_consolidation.rs index 35ba99479e..6ebc6ec97c 100644 --- a/sdk/src/wallet/account/operations/output_consolidation.rs +++ b/sdk/src/wallet/account/operations/output_consolidation.rs @@ -72,6 +72,7 @@ impl ConsolidationParams { impl Account where crate::wallet::Error: From, + crate::client::Error: From, { fn should_consolidate_output( &self, diff --git a/sdk/src/wallet/account/operations/output_finder.rs b/sdk/src/wallet/account/operations/output_finder.rs index eab49bdb0d..e15c6cf683 100644 --- a/sdk/src/wallet/account/operations/output_finder.rs +++ b/sdk/src/wallet/account/operations/output_finder.rs @@ -11,6 +11,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Search addresses with unspent outputs /// `address_gap_limit`: The number of addresses to search for, after the last address with unspent outputs diff --git a/sdk/src/wallet/account/operations/participation/voting.rs b/sdk/src/wallet/account/operations/participation/voting.rs index 26b1c541dd..dda76cbf49 100644 --- a/sdk/src/wallet/account/operations/participation/voting.rs +++ b/sdk/src/wallet/account/operations/participation/voting.rs @@ -22,6 +22,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Casts a given number of votes for a given (voting) event. /// diff --git a/sdk/src/wallet/account/operations/participation/voting_power.rs b/sdk/src/wallet/account/operations/participation/voting_power.rs index 7abe682f60..bc14c01f80 100644 --- a/sdk/src/wallet/account/operations/participation/voting_power.rs +++ b/sdk/src/wallet/account/operations/participation/voting_power.rs @@ -23,6 +23,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Returns an account's total voting power (voting or NOT voting). pub async fn get_voting_power(&self) -> Result { diff --git a/sdk/src/wallet/account/operations/retry.rs b/sdk/src/wallet/account/operations/retry.rs index 6885bfa0ca..23a6adb890 100644 --- a/sdk/src/wallet/account/operations/retry.rs +++ b/sdk/src/wallet/account/operations/retry.rs @@ -23,6 +23,7 @@ const DEFAULT_RETRY_UNTIL_INCLUDED_MAX_AMOUNT: u64 = 40; impl Account where Error: From, + crate::client::Error: From, { /// Retries (promotes or reattaches) a block for provided block id until it's included (referenced by a /// milestone). This function is re-exported from the client library and default interval is as defined there. @@ -35,7 +36,13 @@ where ) -> crate::wallet::Result> { Ok(self .client() - .retry_until_included(block_id, interval, max_attempts) + .retry_until_included( + block_id, + interval, + max_attempts, + self.wallet.coin_type(), + &*self.get_secret_manager().read().await, + ) .await?) } @@ -74,10 +81,11 @@ where .client() .finish_basic_block_builder( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), None, Some(Payload::Transaction(Box::new(transaction.payload.clone()))), + self.wallet.coin_type(), + &*self.get_secret_manager().read().await, ) .await? .id(&protocol_params), @@ -114,16 +122,23 @@ where if index == block_ids_len - 1 { if block_metadata.should_promote.unwrap_or(false) { // Safe to unwrap since we iterate over it - self.client().promote_unchecked(block_ids.last().unwrap()).await?; + self.client() + .promote_unchecked( + block_ids.last().unwrap(), + self.wallet.coin_type(), + &*self.get_secret_manager().read().await, + ) + .await?; } else if block_metadata.should_reattach.unwrap_or(false) { let reattached_block = self .client() .finish_basic_block_builder( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), None, Some(Payload::Transaction(Box::new(transaction.payload.clone()))), + self.wallet.coin_type(), + &*self.get_secret_manager().read().await, ) .await?; block_ids.push(reattached_block.id(&protocol_params)); diff --git a/sdk/src/wallet/account/operations/syncing/mod.rs b/sdk/src/wallet/account/operations/syncing/mod.rs index 1f6eba60b5..b99fa3999e 100644 --- a/sdk/src/wallet/account/operations/syncing/mod.rs +++ b/sdk/src/wallet/account/operations/syncing/mod.rs @@ -26,6 +26,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Set the fallback SyncOptions for account syncing. /// If storage is enabled, will persist during restarts. diff --git a/sdk/src/wallet/account/operations/syncing/transactions.rs b/sdk/src/wallet/account/operations/syncing/transactions.rs index 9df9f07566..8c6d70ba15 100644 --- a/sdk/src/wallet/account/operations/syncing/transactions.rs +++ b/sdk/src/wallet/account/operations/syncing/transactions.rs @@ -22,6 +22,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Sync transactions and reattach them if unconfirmed. Returns the transaction with updated metadata and spent /// output ids that don't need to be locked anymore diff --git a/sdk/src/wallet/account/operations/transaction/high_level/burning_melting/melt_native_token.rs b/sdk/src/wallet/account/operations/transaction/high_level/burning_melting/melt_native_token.rs index 242e329164..759879ce96 100644 --- a/sdk/src/wallet/account/operations/transaction/high_level/burning_melting/melt_native_token.rs +++ b/sdk/src/wallet/account/operations/transaction/high_level/burning_melting/melt_native_token.rs @@ -18,6 +18,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Melts native tokens. /// diff --git a/sdk/src/wallet/account/operations/transaction/high_level/create_account.rs b/sdk/src/wallet/account/operations/transaction/high_level/create_account.rs index 6a5a4b2310..4259eb6b63 100644 --- a/sdk/src/wallet/account/operations/transaction/high_level/create_account.rs +++ b/sdk/src/wallet/account/operations/transaction/high_level/create_account.rs @@ -38,6 +38,7 @@ pub struct CreateAccountParams { impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Creates an account output. /// ```ignore diff --git a/sdk/src/wallet/account/operations/transaction/high_level/minting/create_native_token.rs b/sdk/src/wallet/account/operations/transaction/high_level/minting/create_native_token.rs index 8e7c71997e..4d07f59381 100644 --- a/sdk/src/wallet/account/operations/transaction/high_level/minting/create_native_token.rs +++ b/sdk/src/wallet/account/operations/transaction/high_level/minting/create_native_token.rs @@ -88,6 +88,7 @@ impl From<&PreparedCreateNativeTokenTransaction> for PreparedCreateNativeTokenTr impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Creates a new foundry output with minted native tokens. /// diff --git a/sdk/src/wallet/account/operations/transaction/high_level/minting/mint_native_token.rs b/sdk/src/wallet/account/operations/transaction/high_level/minting/mint_native_token.rs index 6fa5103052..219ad5867f 100644 --- a/sdk/src/wallet/account/operations/transaction/high_level/minting/mint_native_token.rs +++ b/sdk/src/wallet/account/operations/transaction/high_level/minting/mint_native_token.rs @@ -17,6 +17,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Mints additional native tokens. /// diff --git a/sdk/src/wallet/account/operations/transaction/high_level/minting/mint_nfts.rs b/sdk/src/wallet/account/operations/transaction/high_level/minting/mint_nfts.rs index 18996d33ee..7bbdd202d5 100644 --- a/sdk/src/wallet/account/operations/transaction/high_level/minting/mint_nfts.rs +++ b/sdk/src/wallet/account/operations/transaction/high_level/minting/mint_nfts.rs @@ -112,6 +112,7 @@ impl MintNftParams { impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Mints NFTs. /// diff --git a/sdk/src/wallet/account/operations/transaction/high_level/send.rs b/sdk/src/wallet/account/operations/transaction/high_level/send.rs index c1ca3514a6..23af2b1ee5 100644 --- a/sdk/src/wallet/account/operations/transaction/high_level/send.rs +++ b/sdk/src/wallet/account/operations/transaction/high_level/send.rs @@ -79,6 +79,7 @@ impl SendParams { impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Sends a certain amount of base coins to a single address. /// diff --git a/sdk/src/wallet/account/operations/transaction/high_level/send_native_tokens.rs b/sdk/src/wallet/account/operations/transaction/high_level/send_native_tokens.rs index 7ff54cd4bd..408d60a9e2 100644 --- a/sdk/src/wallet/account/operations/transaction/high_level/send_native_tokens.rs +++ b/sdk/src/wallet/account/operations/transaction/high_level/send_native_tokens.rs @@ -81,6 +81,7 @@ impl SendNativeTokensParams { impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Sends native tokens in basic outputs with a [`StorageDepositReturnUnlockCondition`] and an /// [`ExpirationUnlockCondition`], so that the storage deposit is returned to the sender and the sender gets access diff --git a/sdk/src/wallet/account/operations/transaction/high_level/send_nft.rs b/sdk/src/wallet/account/operations/transaction/high_level/send_nft.rs index 32e56d3676..eb371cd421 100644 --- a/sdk/src/wallet/account/operations/transaction/high_level/send_nft.rs +++ b/sdk/src/wallet/account/operations/transaction/high_level/send_nft.rs @@ -42,6 +42,7 @@ impl SendNftParams { impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Sends native tokens in basic outputs with a /// [`StorageDepositReturnUnlockCondition`](crate::types::block::output::unlock_condition::StorageDepositReturnUnlockCondition) and an diff --git a/sdk/src/wallet/account/operations/transaction/mod.rs b/sdk/src/wallet/account/operations/transaction/mod.rs index 10a51ffdb8..70f642aef4 100644 --- a/sdk/src/wallet/account/operations/transaction/mod.rs +++ b/sdk/src/wallet/account/operations/transaction/mod.rs @@ -34,6 +34,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Sends a transaction by specifying its outputs. /// diff --git a/sdk/src/wallet/account/operations/transaction/prepare_output.rs b/sdk/src/wallet/account/operations/transaction/prepare_output.rs index b622ea54e7..0c5f779c7a 100644 --- a/sdk/src/wallet/account/operations/transaction/prepare_output.rs +++ b/sdk/src/wallet/account/operations/transaction/prepare_output.rs @@ -27,6 +27,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Prepare a basic or NFT output for sending /// If the amount is below the minimum required storage deposit, by default the remaining amount will automatically diff --git a/sdk/src/wallet/account/operations/transaction/prepare_transaction.rs b/sdk/src/wallet/account/operations/transaction/prepare_transaction.rs index de9f8518f6..1fd828f818 100644 --- a/sdk/src/wallet/account/operations/transaction/prepare_transaction.rs +++ b/sdk/src/wallet/account/operations/transaction/prepare_transaction.rs @@ -23,6 +23,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Get inputs and build the transaction essence pub async fn prepare_transaction( diff --git a/sdk/src/wallet/account/operations/transaction/sign_transaction.rs b/sdk/src/wallet/account/operations/transaction/sign_transaction.rs index 1f29282b8a..e3a2bbce93 100644 --- a/sdk/src/wallet/account/operations/transaction/sign_transaction.rs +++ b/sdk/src/wallet/account/operations/transaction/sign_transaction.rs @@ -23,6 +23,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Signs a transaction essence. pub async fn sign_transaction_essence( diff --git a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs index 916f21a875..3b226290b5 100644 --- a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs +++ b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs @@ -12,6 +12,7 @@ use crate::{ impl Account where crate::wallet::Error: From, + crate::client::Error: From, { /// Submits a payload in a block pub(crate) async fn submit_transaction_payload( @@ -26,10 +27,11 @@ where .client() .finish_basic_block_builder( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), None, Some(Payload::from(transaction_payload)), + self.wallet.coin_type(), + &*self.get_secret_manager().read().await, ) .await?; diff --git a/sdk/src/wallet/core/mod.rs b/sdk/src/wallet/core/mod.rs index f007ac896a..69d5d9c2f9 100644 --- a/sdk/src/wallet/core/mod.rs +++ b/sdk/src/wallet/core/mod.rs @@ -4,6 +4,7 @@ pub(crate) mod builder; pub(crate) mod operations; +use core::sync::atomic::Ordering; use std::sync::{ atomic::{AtomicU32, AtomicUsize}, Arc, @@ -88,6 +89,7 @@ pub struct WalletInner { impl Wallet where crate::wallet::Error: From, + crate::client::Error: From, { /// Get all accounts pub async fn get_accounts(&self) -> crate::wallet::Result>> { @@ -167,6 +169,10 @@ where } impl WalletInner { + pub fn coin_type(&self) -> u32 { + self.coin_type.load(Ordering::Relaxed) + } + /// Get the [SecretManager] pub fn get_secret_manager(&self) -> &Arc> { &self.secret_manager diff --git a/sdk/src/wallet/core/operations/account_recovery.rs b/sdk/src/wallet/core/operations/account_recovery.rs index f72ea75da8..743639080d 100644 --- a/sdk/src/wallet/core/operations/account_recovery.rs +++ b/sdk/src/wallet/core/operations/account_recovery.rs @@ -11,6 +11,7 @@ use crate::{ impl Wallet where crate::wallet::Error: From, + crate::client::Error: From, { /// Find accounts with unspent outputs. /// diff --git a/sdk/src/wallet/core/operations/address_generation.rs b/sdk/src/wallet/core/operations/address_generation.rs index 494894fddd..c1255529a8 100644 --- a/sdk/src/wallet/core/operations/address_generation.rs +++ b/sdk/src/wallet/core/operations/address_generation.rs @@ -121,6 +121,7 @@ impl Wallet { impl Wallet where crate::wallet::Error: From, + crate::client::Error: From, { /// Get the bech32 hrp from the first account address or if not existent, from the client pub async fn get_bech32_hrp(&self) -> crate::wallet::Result { diff --git a/sdk/src/wallet/core/operations/background_syncing.rs b/sdk/src/wallet/core/operations/background_syncing.rs index f7f59fa24d..174317c9c2 100644 --- a/sdk/src/wallet/core/operations/background_syncing.rs +++ b/sdk/src/wallet/core/operations/background_syncing.rs @@ -16,6 +16,7 @@ pub(crate) const DEFAULT_BACKGROUNDSYNCING_INTERVAL: Duration = Duration::from_s impl Wallet where crate::wallet::Error: From, + crate::client::Error: From, { /// Start the background syncing process for all accounts, default interval is 7 seconds pub async fn start_background_syncing( diff --git a/sdk/tests/client/node_api/core.rs b/sdk/tests/client/node_api/core.rs index e0338f113d..cebe4cae65 100644 --- a/sdk/tests/client/node_api/core.rs +++ b/sdk/tests/client/node_api/core.rs @@ -43,7 +43,8 @@ async fn test_get_tips() { #[ignore] #[tokio::test] async fn test_post_block_with_tagged_data() { - let block_id = setup_tagged_data_block().await; + let secret_manager = setup_secret_manager(); + let block_id = setup_tagged_data_block(&secret_manager).await; println!("{block_id}"); } @@ -59,8 +60,9 @@ async fn test_post_block_with_transaction() { #[tokio::test] async fn test_get_block_data() { let client = setup_client_with_node_health_ignored().await; + let secret_manager = setup_secret_manager(); - let block_id = setup_tagged_data_block().await; + let block_id = setup_tagged_data_block(&secret_manager).await; let r = client.get_block(&block_id).await.unwrap(); println!("{r:#?}"); @@ -69,7 +71,8 @@ async fn test_get_block_data() { #[ignore] #[tokio::test] async fn test_get_block_metadata() { - let block_id = setup_tagged_data_block().await; + let secret_manager = setup_secret_manager(); + let block_id = setup_tagged_data_block(&secret_manager).await; let r = setup_client_with_node_health_ignored() .await @@ -83,7 +86,8 @@ async fn test_get_block_metadata() { #[ignore] #[tokio::test] async fn test_get_block_raw() { - let block_id = setup_tagged_data_block().await; + let secret_manager = setup_secret_manager(); + let block_id = setup_tagged_data_block(&secret_manager).await; let r = setup_client_with_node_health_ignored() .await diff --git a/sdk/tests/client/node_api/mod.rs b/sdk/tests/client/node_api/mod.rs index ac07da0913..6de5da9ca2 100644 --- a/sdk/tests/client/node_api/mod.rs +++ b/sdk/tests/client/node_api/mod.rs @@ -8,8 +8,8 @@ mod mqtt; use iota_sdk::{ client::{ - api::GetAddressesOptions, node_api::indexer::query_parameters::QueryParameter, request_funds_from_faucet, - secret::SecretManager, Client, + api::GetAddressesOptions, constants::IOTA_COIN_TYPE, node_api::indexer::query_parameters::QueryParameter, + request_funds_from_faucet, secret::SecretManager, Client, }, types::block::{ payload::{tagged_data::TaggedDataPayload, transaction::TransactionId, Payload}, @@ -23,7 +23,7 @@ use crate::client::common::{setup_client_with_node_health_ignored, FAUCET_URL}; const DEFAULT_DEVELOPMENT_SEED: &str = "0x256a818b2aac458941f7274985a410e57fb750f3a3a67969ece5bd9ae7eef5b2"; // Sends a tagged data block to the node to test against it. -async fn setup_tagged_data_block() -> BlockId { +async fn setup_tagged_data_block(secret_manager: &SecretManager) -> BlockId { let client = setup_client_with_node_health_ignored().await; let protocol_parameters = client.get_protocol_parameters().await.unwrap(); @@ -31,12 +31,13 @@ async fn setup_tagged_data_block() -> BlockId { client .finish_basic_block_builder( todo!("issuer id"), - todo!("block signature"), todo!("issuing time"), None, Some(Payload::TaggedData(Box::new( TaggedDataPayload::new(b"Hello".to_vec(), b"Tangle".to_vec()).unwrap(), ))), + IOTA_COIN_TYPE, + secret_manager, ) .await .unwrap() @@ -92,7 +93,10 @@ pub async fn setup_transaction_block(client: &Client) -> (BlockId, TransactionId _ => unreachable!(), }; - let _ = client.retry_until_included(&block_id, None, None).await.unwrap(); + let _ = client + .retry_until_included(&block_id, None, None, IOTA_COIN_TYPE, &secret_manager) + .await + .unwrap(); (block_id, transaction_id) } diff --git a/sdk/tests/types/block.rs b/sdk/tests/types/block.rs index ecd84658fa..aea33fd17a 100644 --- a/sdk/tests/types/block.rs +++ b/sdk/tests/types/block.rs @@ -5,7 +5,10 @@ use iota_sdk::types::block::{ payload::Payload, protocol::protocol_parameters, rand::{ - block::{rand_basic_block_builder_with_strong_parents, rand_basic_block_with_strong_parents, rand_block}, + block::{ + rand_basic_block_builder_with_strong_parents, rand_basic_block_with_strong_parents, rand_block, + SignBlockRandom, + }, parents::rand_strong_parents, payload::rand_tagged_data_payload, }, @@ -105,8 +108,7 @@ fn getters() { let block = rand_basic_block_builder_with_strong_parents(parents.clone()) .with_payload(payload.clone()) - .finish() - .unwrap(); + .sign_random(); assert_eq!(block.protocol_version(), protocol_parameters.protocol_version()); assert_eq!(*block.strong_parents(), parents); From 581570e603eb853f67c7b07a2a8c9b47e2a91a16 Mon Sep 17 00:00:00 2001 From: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Date: Tue, 8 Aug 2023 16:43:08 +0200 Subject: [PATCH 35/57] Fix block id computation, fix return type, reexport BlockHash, clippy (#998) --- sdk/src/client/node_manager/syncing.rs | 2 +- sdk/src/types/block/block_id.rs | 2 +- sdk/src/types/block/core.rs | 26 ++++++++++++++------------ sdk/src/types/block/mod.rs | 2 +- sdk/tests/types/block_id.rs | 19 ++++++++++++++++++- 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/sdk/src/client/node_manager/syncing.rs b/sdk/src/client/node_manager/syncing.rs index 7c78a25be9..2399526b7b 100644 --- a/sdk/src/client/node_manager/syncing.rs +++ b/sdk/src/client/node_manager/syncing.rs @@ -130,7 +130,7 @@ impl ClientInner { impl Client { #[cfg(not(target_family = "wasm"))] - pub async fn update_node_manager(&self, node_manager: NodeManager) -> crate::wallet::Result<()> { + pub async fn update_node_manager(&self, node_manager: NodeManager) -> crate::client::Result<()> { let node_sync_interval = node_manager.node_sync_interval; let ignore_node_health = node_manager.ignore_node_health; let nodes = node_manager diff --git a/sdk/src/types/block/block_id.rs b/sdk/src/types/block/block_id.rs index dfe10fdc28..87ecc64026 100644 --- a/sdk/src/types/block/block_id.rs +++ b/sdk/src/types/block/block_id.rs @@ -50,7 +50,7 @@ impl core::str::FromStr for BlockId { type Err = Error; fn from_str(s: &str) -> Result { - Ok(BlockId::new(prefix_hex::decode(s).map_err(Error::Hex)?)) + Ok(Self::new(prefix_hex::decode(s).map_err(Error::Hex)?)) } } diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 3f5aefd290..358ac5e36e 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -502,22 +502,24 @@ impl Block { pub(crate) fn header_hash(&self) -> [u8; 32] { match self { - Block::Basic(b) => b.header_hash(), - Block::Validation(b) => b.header_hash(), + Self::Basic(b) => b.header_hash(), + Self::Validation(b) => b.header_hash(), } } pub(crate) fn block_hash(&self) -> [u8; 32] { let bytes = match self { - Block::Basic(b) => b.data.pack_to_vec(), - Block::Validation(b) => b.data.pack_to_vec(), + Self::Basic(b) => [vec![BasicBlock::KIND], b.data.pack_to_vec()].concat(), + Self::Validation(b) => [vec![ValidationBlock::KIND], b.data.pack_to_vec()].concat(), }; Blake2b256::digest(bytes).into() } - pub(crate) fn signature_bytes(&self) -> [u8; Block::SIGNATURE_LENGTH] { - let mut bytes = [0u8; Block::SIGNATURE_LENGTH]; - self.signature().pack(&mut SlicePacker::new(&mut bytes)).unwrap(); + pub(crate) fn signature_bytes(&self) -> [u8; Self::SIGNATURE_LENGTH] { + let mut bytes = [0u8; Self::SIGNATURE_LENGTH]; + let mut packer = SlicePacker::new(&mut bytes); + Ed25519Signature::KIND.pack(&mut packer).unwrap(); + self.signature().pack(&mut packer).unwrap(); bytes } } @@ -632,7 +634,7 @@ pub(crate) mod dto { pub network_id: u64, #[serde(with = "string")] pub issuing_time: u64, - pub slot_commitment_id: SlotCommitmentId, + pub slot_commitment: SlotCommitmentId, pub latest_finalized_slot: SlotIndex, pub issuer_id: IssuerId, pub block: BlockDataDto, @@ -646,7 +648,7 @@ pub(crate) mod dto { protocol_version: b.protocol_version(), network_id: b.network_id(), issuing_time: b.issuing_time(), - slot_commitment_id: b.slot_commitment_id(), + slot_commitment: b.slot_commitment_id(), latest_finalized_slot: b.latest_finalized_slot(), issuer_id: b.issuer_id(), block: (&b.data).into(), @@ -656,7 +658,7 @@ pub(crate) mod dto { protocol_version: b.protocol_version(), network_id: b.network_id(), issuing_time: b.issuing_time(), - slot_commitment_id: b.slot_commitment_id(), + slot_commitment: b.slot_commitment_id(), latest_finalized_slot: b.latest_finalized_slot(), issuer_id: b.issuer_id(), block: (&b.data).into(), @@ -675,7 +677,7 @@ pub(crate) mod dto { BlockDataDto::Basic(b) => BlockBuilder::from_block_data( dto.network_id, dto.issuing_time, - dto.slot_commitment_id, + dto.slot_commitment, dto.latest_finalized_slot, dto.issuer_id, BasicBlockData::try_from_dto_with_params_inner(b, params)?, @@ -686,7 +688,7 @@ pub(crate) mod dto { BlockDataDto::Validation(b) => BlockBuilder::from_block_data( dto.network_id, dto.issuing_time, - dto.slot_commitment_id, + dto.slot_commitment, dto.latest_finalized_slot, dto.issuer_id, ValidationBlockData::try_from_dto_with_params_inner(b, params)?, diff --git a/sdk/src/types/block/mod.rs b/sdk/src/types/block/mod.rs index b1af43cf8a..5991ef513d 100644 --- a/sdk/src/types/block/mod.rs +++ b/sdk/src/types/block/mod.rs @@ -53,7 +53,7 @@ pub(crate) use r#macro::string_serde_impl; pub(crate) use r#macro::{create_bitflags, impl_id}; pub use self::{ - block_id::BlockId, + block_id::{BlockHash, BlockId}, convert::ConvertTo, core::{dto::BlockDto, Block, BlockBuilder}, error::Error, diff --git a/sdk/tests/types/block_id.rs b/sdk/tests/types/block_id.rs index 536420e55e..7031d42635 100644 --- a/sdk/tests/types/block_id.rs +++ b/sdk/tests/types/block_id.rs @@ -3,7 +3,10 @@ use core::str::FromStr; -use iota_sdk::types::block::BlockId; +use iota_sdk::types::{ + block::{slot::SlotIndex, Block, BlockDto, BlockId}, + TryFromDto, +}; use packable::PackableExt; const BLOCK_ID: &str = "0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c6490000000000000000"; @@ -49,3 +52,17 @@ fn pack_unpack_valid() { PackableExt::unpack_verified(packed_block_id.as_slice(), &()).unwrap() ); } + +#[test] +fn compute() { + let block_dto_json = r#"{"protocolVersion":3,"networkId":"0","issuingTime":"0","slotCommitment":"0x8633b2eb1845fdecf12ee6c5e789c3cf1f0d0bbb3cee65cb5fb2757e995b5cd70000000000000000","latestFinalizedSlot":"0","issuerId":"0x0000000000000000000000000000000000000000000000000000000000000000","block":{"type":1,"strongParents":["0x417c5700320912627b604d4c376a5a1663634b09703538570b1d52440b3e474639490b100a6f3608"],"weakParents":[],"shallowLikeParents":[],"highestSupportedVersion":3,"protocolParametersHash":"0x0000000000000000000000000000000000000000000000000000000000000000"},"signature":{"type":0,"publicKey":"0x714f5f07067012267c21426d382a52752f0b3208443e0e3c49183e0110494148","signature":"0x3e4a492924302b3b093f1e4266757a1d2041480a3861271d4c2e646d4e3d08360a3e765e1a385a784f6753276c233123475867370a184573195d530b41643a1d"}}"#; + let block_dto = serde_json::from_str::(block_dto_json).unwrap(); + let block = Block::try_from_dto(block_dto).unwrap(); + let block_hash = block.hash(); + let block_id = block_hash.with_slot_index(SlotIndex::new(0)); + + assert_eq!( + block_id.to_string(), + "0x836b8e132a331263f3da03735d22f1cb99e42d86dab09447d3bec113005c82490000000000000000" + ); +} From e5302189e5f5912891127e542c264faa437fedaa Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Tue, 8 Aug 2023 10:56:01 -0400 Subject: [PATCH 36/57] no_std --- sdk/src/types/block/core.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 358ac5e36e..dbb23c8350 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -508,10 +508,17 @@ impl Block { } pub(crate) fn block_hash(&self) -> [u8; 32] { - let bytes = match self { - Self::Basic(b) => [vec![BasicBlock::KIND], b.data.pack_to_vec()].concat(), - Self::Validation(b) => [vec![ValidationBlock::KIND], b.data.pack_to_vec()].concat(), - }; + let mut bytes = Vec::new(); + match self { + Self::Basic(b) => { + bytes.push(BasicBlock::KIND); + bytes.extend(b.data.pack_to_vec()); + } + Self::Validation(b) => { + bytes.push(ValidationBlock::KIND); + bytes.extend(b.data.pack_to_vec()); + } + } Blake2b256::digest(bytes).into() } From 0b3ea143b46429697ba9b5151d068b50d538a8b4 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 9 Aug 2023 10:00:17 -0400 Subject: [PATCH 37/57] fix block ID slot index on big endian systems and clippy --- sdk/src/client/api/high_level.rs | 12 +++++----- sdk/src/types/block/block_id.rs | 14 +++++++----- sdk/src/types/block/macro.rs | 1 + sdk/src/wallet/account/operations/retry.rs | 26 ++++++++++------------ 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/sdk/src/client/api/high_level.rs b/sdk/src/client/api/high_level.rs index 2dbfcfadc1..88484874ba 100644 --- a/sdk/src/client/api/high_level.rs +++ b/sdk/src/client/api/high_level.rs @@ -130,13 +130,11 @@ impl Client { }; } // Only reattach latest attachment of the block - if index == block_ids_len - 1 { - if block_metadata.should_reattach.unwrap_or(false) { - // Safe to unwrap since we iterate over it - let reattached = self.reattach_unchecked(block_ids.last().unwrap()).await?; - block_ids.push(reattached.0); - blocks_with_id.push(reattached); - } + if index == block_ids_len - 1 && block_metadata.should_reattach.unwrap_or(false) { + // Safe to unwrap since we iterate over it + let reattached = self.reattach_unchecked(block_ids.last().unwrap()).await?; + block_ids.push(reattached.0); + blocks_with_id.push(reattached); } } // After we checked all our reattached blocks, check if the transaction got reattached in another block diff --git a/sdk/src/types/block/block_id.rs b/sdk/src/types/block/block_id.rs index 87ecc64026..10f6170b61 100644 --- a/sdk/src/types/block/block_id.rs +++ b/sdk/src/types/block/block_id.rs @@ -18,7 +18,9 @@ impl BlockHash { #[repr(C)] pub struct BlockId { pub(crate) hash: BlockHash, - pub(crate) slot_index: SlotIndex, + // INPORTANT: On big-endian systems this value is misrepresented because it is transmuted directly + // from bytes, so the getter below handles that conversion. Do not access it directly. + slot_index: SlotIndex, } impl BlockId { @@ -29,14 +31,16 @@ impl BlockId { unsafe { core::mem::transmute(bytes) } } - /// Checks if the [`BlockId`] is null. - pub fn is_null(&self) -> bool { - self.as_ref().iter().all(|&b| b == 0) + /// Returns the [`BlockId`]'s slot index part. + #[cfg(target_endian = "little")] + pub fn slot_index(&self) -> SlotIndex { + self.slot_index } /// Returns the [`BlockId`]'s slot index part. + #[cfg(target_endian = "big")] pub fn slot_index(&self) -> SlotIndex { - self.slot_index + self.slot_index.to_le().into() } } diff --git a/sdk/src/types/block/macro.rs b/sdk/src/types/block/macro.rs index 1c1ffe85b2..6db74914be 100644 --- a/sdk/src/types/block/macro.rs +++ b/sdk/src/types/block/macro.rs @@ -19,6 +19,7 @@ macro_rules! impl_id { packable::Packable, )] #[as_ref(forward)] + #[repr(transparent)] $vis struct $name([u8; $name::LENGTH]); impl $name { diff --git a/sdk/src/wallet/account/operations/retry.rs b/sdk/src/wallet/account/operations/retry.rs index a7a6045cbc..283c926f38 100644 --- a/sdk/src/wallet/account/operations/retry.rs +++ b/sdk/src/wallet/account/operations/retry.rs @@ -111,20 +111,18 @@ where }; } // Only reattach latest attachment of the block - if index == block_ids_len - 1 { - if block_metadata.should_reattach.unwrap_or(false) { - let reattached_block = self - .client() - .finish_basic_block_builder( - todo!("issuer id"), - todo!("block signature"), - todo!("issuing time"), - None, - Some(Payload::Transaction(Box::new(transaction.payload.clone()))), - ) - .await?; - block_ids.push(reattached_block.id(&protocol_params)); - } + if index == block_ids_len - 1 && block_metadata.should_reattach.unwrap_or(false) { + let reattached_block = self + .client() + .finish_basic_block_builder( + todo!("issuer id"), + todo!("block signature"), + todo!("issuing time"), + None, + Some(Payload::Transaction(Box::new(transaction.payload.clone()))), + ) + .await?; + block_ids.push(reattached_block.id(&protocol_params)); } } // After we checked all our reattached blocks, check if the transaction got reattached in another block From de5908587418a2b24ff305478c9582a8b13c89c0 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 9 Aug 2023 10:17:45 -0400 Subject: [PATCH 38/57] fix with_slot_index too --- sdk/src/types/block/block_id.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sdk/src/types/block/block_id.rs b/sdk/src/types/block/block_id.rs index 10f6170b61..488bd5ac36 100644 --- a/sdk/src/types/block/block_id.rs +++ b/sdk/src/types/block/block_id.rs @@ -7,9 +7,18 @@ use crate::types::block::Error; impl_id!(pub BlockHash, 32, "The hash of a [`Block`]."); impl BlockHash { + #[cfg(target_endian = "little")] pub fn with_slot_index(self, slot_index: SlotIndex) -> BlockId { BlockId { hash: self, slot_index } } + + #[cfg(target_endian = "big")] + pub fn with_slot_index(self, slot_index: SlotIndex) -> BlockId { + BlockId { + hash: self, + slot_index: slot_index.to_le().into(), + } + } } /// A block identifier. From ece2c5274cca6b88631a059e8dfb40ab732b0e48 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 9 Aug 2023 12:40:01 -0400 Subject: [PATCH 39/57] PR suggestion --- sdk/src/wallet/account/operations/syncing/transactions.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/src/wallet/account/operations/syncing/transactions.rs b/sdk/src/wallet/account/operations/syncing/transactions.rs index 9df9f07566..f529128dc2 100644 --- a/sdk/src/wallet/account/operations/syncing/transactions.rs +++ b/sdk/src/wallet/account/operations/syncing/transactions.rs @@ -47,6 +47,7 @@ where // are available again let mut output_ids_to_unlock = Vec::new(); let mut transactions_to_reattach = Vec::new(); + let protocol_params = self.client().get_protocol_parameters().await?; for transaction_id in &account_details.pending_transactions { log::debug!("[SYNC] sync pending transaction {transaction_id}"); @@ -126,7 +127,7 @@ where confirmed_unknown_output = true; updated_transaction_and_outputs( transaction, - Some(included_block.id(&self.client().get_protocol_parameters().await?)), + Some(included_block.id(&protocol_params)), // block metadata was Conflicting, but it's confirmed in another attachment InclusionState::Confirmed, &mut updated_transactions, From 3a08211f68eb7f89890157f72086a0b3f0fb61c1 Mon Sep 17 00:00:00 2001 From: Alexandcoats Date: Thu, 10 Aug 2023 08:20:12 -0400 Subject: [PATCH 40/57] oof Co-authored-by: Abdulrahim Al Methiab <31316147+abdulmth@users.noreply.github.com> --- sdk/src/types/block/block_id.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/block_id.rs b/sdk/src/types/block/block_id.rs index 488bd5ac36..e617d0b68f 100644 --- a/sdk/src/types/block/block_id.rs +++ b/sdk/src/types/block/block_id.rs @@ -27,7 +27,7 @@ impl BlockHash { #[repr(C)] pub struct BlockId { pub(crate) hash: BlockHash, - // INPORTANT: On big-endian systems this value is misrepresented because it is transmuted directly + // IMPORTANT: On big-endian systems this value is misrepresented because it is transmuted directly // from bytes, so the getter below handles that conversion. Do not access it directly. slot_index: SlotIndex, } From d461c5ee8293dcfcf0287a5809d124d32f91b70a Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Thu, 10 Aug 2023 08:33:54 -0400 Subject: [PATCH 41/57] add memory layout test --- sdk/tests/types/block_id.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sdk/tests/types/block_id.rs b/sdk/tests/types/block_id.rs index 7031d42635..17284b8f2b 100644 --- a/sdk/tests/types/block_id.rs +++ b/sdk/tests/types/block_id.rs @@ -4,7 +4,7 @@ use core::str::FromStr; use iota_sdk::types::{ - block::{slot::SlotIndex, Block, BlockDto, BlockId}, + block::{rand::bytes::rand_bytes_array, slot::SlotIndex, Block, BlockDto, BlockHash, BlockId}, TryFromDto, }; use packable::PackableExt; @@ -53,6 +53,17 @@ fn pack_unpack_valid() { ); } +#[test] +fn memory_layout() { + let block_hash = BlockHash::new(rand_bytes_array()); + let slot_index = 12345.into(); + let block_id = block_hash.with_slot_index(slot_index); + assert_eq!(slot_index, block_id.slot_index()); + let memory_layout = + <[u8; BlockId::LENGTH]>::try_from([block_hash.as_ref(), &slot_index.to_le_bytes()].concat()).unwrap(); + assert_eq!(block_id.as_ref(), memory_layout); +} + #[test] fn compute() { let block_dto_json = r#"{"protocolVersion":3,"networkId":"0","issuingTime":"0","slotCommitment":"0x8633b2eb1845fdecf12ee6c5e789c3cf1f0d0bbb3cee65cb5fb2757e995b5cd70000000000000000","latestFinalizedSlot":"0","issuerId":"0x0000000000000000000000000000000000000000000000000000000000000000","block":{"type":1,"strongParents":["0x417c5700320912627b604d4c376a5a1663634b09703538570b1d52440b3e474639490b100a6f3608"],"weakParents":[],"shallowLikeParents":[],"highestSupportedVersion":3,"protocolParametersHash":"0x0000000000000000000000000000000000000000000000000000000000000000"},"signature":{"type":0,"publicKey":"0x714f5f07067012267c21426d382a52752f0b3208443e0e3c49183e0110494148","signature":"0x3e4a492924302b3b093f1e4266757a1d2041480a3861271d4c2e646d4e3d08360a3e765e1a385a784f6753276c233123475867370a184573195d530b41643a1d"}}"#; From 04cecee994d8161d91696998deb8bfca70d2eb4e Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 14 Aug 2023 09:01:35 -0400 Subject: [PATCH 42/57] no_std --- sdk/src/types/block/basic.rs | 2 ++ sdk/src/types/block/validation.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sdk/src/types/block/basic.rs b/sdk/src/types/block/basic.rs index d1e1573d4c..fd7c3adc01 100644 --- a/sdk/src/types/block/basic.rs +++ b/sdk/src/types/block/basic.rs @@ -1,6 +1,8 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use alloc::vec::Vec; + use crypto::hashes::{blake2b::Blake2b256, Digest}; use packable::{ error::{UnpackError, UnpackErrorExt}, diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs index aff21edf67..e92015a462 100644 --- a/sdk/src/types/block/validation.rs +++ b/sdk/src/types/block/validation.rs @@ -1,6 +1,8 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use alloc::vec::Vec; + use crypto::hashes::{blake2b::Blake2b256, Digest}; use packable::{ error::{UnpackError, UnpackErrorExt}, From be5c004c6f0430596fd2911062aaca05837d1273 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 14 Aug 2023 09:18:50 -0400 Subject: [PATCH 43/57] Merge branch 2.0 --- bindings/core/src/method/account.rs | 6 +- bindings/core/src/method/client.rs | 32 ---- bindings/core/src/method_handler/account.rs | 4 +- bindings/core/src/method_handler/client.rs | 38 ---- bindings/core/src/response.rs | 12 +- .../consolidate-outputs.ts | 2 +- .../advanced_transaction.ts | 2 +- .../claim_transaction.ts | 2 +- .../send_micro_transaction.ts | 2 +- .../nodejs/examples/how_tos/alias/create.ts | 2 +- .../nodejs/examples/how_tos/alias/destroy.ts | 2 +- .../how_tos/alias_wallet/transaction.ts | 4 +- .../examples/how_tos/native_tokens/burn.ts | 2 +- .../examples/how_tos/native_tokens/create.ts | 4 +- .../how_tos/native_tokens/destroy-foundry.ts | 2 +- .../examples/how_tos/native_tokens/melt.ts | 2 +- .../examples/how_tos/native_tokens/mint.ts | 2 +- .../examples/how_tos/native_tokens/send.ts | 2 +- .../nft_collection/00_mint_issuer_nft.ts | 2 +- .../nft_collection/01_mint_collection_nft.ts | 2 +- .../nodejs/examples/how_tos/nfts/burn_nft.ts | 2 +- .../nodejs/examples/how_tos/nfts/mint_nft.ts | 4 +- .../nodejs/examples/how_tos/nfts/send_nft.ts | 2 +- .../wallet/06-send-micro-transaction.ts | 2 +- bindings/nodejs/lib/client/client.ts | 74 ------- .../nodejs/lib/types/client/bridge/client.ts | 30 --- .../nodejs/lib/types/client/bridge/index.ts | 8 - bindings/nodejs/lib/types/wallet/account.ts | 2 +- .../nodejs/lib/types/wallet/bridge/account.ts | 4 +- .../nodejs/lib/types/wallet/bridge/index.ts | 4 +- bindings/nodejs/lib/wallet/account.ts | 8 +- .../tests/client/messageMethods.spec.ts | 37 ---- .../consolidate_outputs.py | 3 +- .../advanced_transaction.py | 3 +- .../claim_transaction.py | 3 +- .../send_micro_transaction.py | 3 +- .../how_tos/alias_wallet/transaction.py | 3 +- .../examples/how_tos/native_tokens/burn.py | 2 +- .../examples/how_tos/native_tokens/create.py | 4 +- .../how_tos/native_tokens/destroy_foundry.py | 2 +- .../examples/how_tos/native_tokens/melt.py | 2 +- .../examples/how_tos/native_tokens/mint.py | 2 +- .../examples/how_tos/native_tokens/send.py | 2 +- .../nft_collection/00_mint_issuer_nft.py | 3 +- .../nft_collection/01_mint_collection_nft.py | 2 +- .../offline_signing/3_send_transaction.py | 3 +- .../python/iota_sdk/client/_high_level_api.py | 65 ------- bindings/python/iota_sdk/wallet/account.py | 8 +- .../python/iota_sdk/wallet/sync_options.py | 2 +- cli/src/command/account.rs | 2 +- .../block/01_block_confirmation_time.rs | 13 +- sdk/examples/client/send_all.rs | 2 - sdk/examples/how_tos/account/create.rs | 2 +- sdk/examples/how_tos/account/destroy.rs | 2 +- .../how_tos/account_wallet/transaction.rs | 2 +- .../consolidate_outputs.rs | 2 +- .../advanced_transaction.rs | 2 +- .../claim_transaction.rs | 2 +- .../send_micro_transaction.rs | 2 +- sdk/examples/how_tos/native_tokens/burn.rs | 2 +- sdk/examples/how_tos/native_tokens/create.rs | 4 +- .../how_tos/native_tokens/destroy_foundry.rs | 2 +- sdk/examples/how_tos/native_tokens/melt.rs | 2 +- sdk/examples/how_tos/native_tokens/mint.rs | 2 +- sdk/examples/how_tos/native_tokens/send.rs | 2 +- .../nft_collection/00_mint_issuer_nft.rs | 2 +- .../nft_collection/01_mint_collection_nft.rs | 2 +- sdk/examples/how_tos/nfts/burn_nft.rs | 2 +- sdk/examples/how_tos/nfts/mint_nft.rs | 4 +- sdk/examples/how_tos/nfts/send_nft.rs | 2 +- .../simple_transaction/simple_transaction.rs | 2 +- sdk/examples/wallet/events.rs | 2 +- sdk/examples/wallet/ledger_nano.rs | 2 +- .../offline_signing/3_send_transaction.rs | 2 +- sdk/examples/wallet/participation.rs | 10 +- sdk/examples/wallet/spammer.rs | 2 +- sdk/examples/wallet/split_funds.rs | 2 +- sdk/examples/wallet/update_account_output.rs | 2 +- sdk/examples/wallet/wallet.rs | 2 +- sdk/src/client/api/high_level.rs | 180 +----------------- sdk/src/client/constants.rs | 2 - sdk/src/client/error.rs | 3 - sdk/src/wallet/account/operations/mod.rs | 4 +- .../operations/{retry.rs => reissue.rs} | 48 ++--- .../wallet/account/operations/syncing/mod.rs | 2 +- .../account/operations/syncing/options.rs | 2 +- .../operations/syncing/transactions.rs | 36 ++-- .../account/operations/transaction/mod.rs | 2 +- sdk/tests/client/node_api/indexer.rs | 8 - sdk/tests/client/node_api/mod.rs | 5 - sdk/tests/wallet/balance.rs | 10 +- sdk/tests/wallet/burn_outputs.rs | 32 ++-- sdk/tests/wallet/claim_outputs.rs | 42 ++-- sdk/tests/wallet/consolidation.rs | 4 +- sdk/tests/wallet/native_tokens.rs | 10 +- sdk/tests/wallet/output_preparation.rs | 8 +- sdk/tests/wallet/syncing.rs | 4 +- sdk/tests/wallet/transactions.rs | 14 +- 98 files changed, 217 insertions(+), 697 deletions(-) rename sdk/src/wallet/account/operations/{retry.rs => reissue.rs} (75%) diff --git a/bindings/core/src/method/account.rs b/bindings/core/src/method/account.rs index b5e4e90e8f..2831e08e54 100644 --- a/bindings/core/src/method/account.rs +++ b/bindings/core/src/method/account.rs @@ -258,11 +258,11 @@ pub enum AccountMethod { RegisterParticipationEvents { options: ParticipationEventRegistrationOptions, }, - /// Retries (promotes or reattaches) a transaction sent from the account for a provided transaction id until it's + /// Reissues a transaction sent from the account for a provided transaction id until it's /// included (referenced by a milestone). Returns the included block id. /// Expected response: [`BlockId`](crate::Response::BlockId) #[serde(rename_all = "camelCase")] - RetryTransactionUntilIncluded { + ReissueTransactionUntilIncluded { /// Transaction id transaction_id: TransactionId, /// Interval @@ -315,7 +315,7 @@ pub enum AccountMethod { SubmitAndStoreTransaction { signed_transaction_data: SignedTransactionDataDto, }, - /// Sync the account by fetching new information from the nodes. Will also retry pending transactions + /// Sync the account by fetching new information from the nodes. Will also reissue pending transactions /// if necessary. A custom default can be set using SetDefaultSyncOptions. /// Expected response: [`Balance`](crate::Response::Balance) Sync { diff --git a/bindings/core/src/method/client.rs b/bindings/core/src/method/client.rs index 72708d84ce..e029f376af 100644 --- a/bindings/core/src/method/client.rs +++ b/bindings/core/src/method/client.rs @@ -270,25 +270,6 @@ pub enum ClientMethod { /// BlockIDs block_ids: Vec, }, - /// Retries (promotes or reattaches) a block for provided block id. Block should only be - /// retried only if they are valid and haven't been confirmed for a while. - #[serde(rename_all = "camelCase")] - Retry { - /// Block ID - block_id: BlockId, - }, - /// Retries (promotes or reattaches) a block for provided block id until it's included (referenced by a - /// milestone). Default interval is 5 seconds and max attempts is 40. Returns the included block at first - /// position and additional reattached blocks - #[serde(rename_all = "camelCase")] - RetryUntilIncluded { - /// Block ID - block_id: BlockId, - /// Interval - interval: Option, - /// Maximum attempts - max_attempts: Option, - }, /// Function to find inputs from addresses for a provided amount (useful for offline signing) FindInputs { /// Addresses @@ -296,19 +277,6 @@ pub enum ClientMethod { /// Amount amount: u64, }, - /// Reattaches blocks for provided block id. Blocks can be reattached only if they are valid and haven't been - /// confirmed for a while. - #[serde(rename_all = "camelCase")] - Reattach { - /// Block ID - block_id: BlockId, - }, - /// Reattach a block without checking if it should be reattached - #[serde(rename_all = "camelCase")] - ReattachUnchecked { - /// Block ID - block_id: BlockId, - }, ////////////////////////////////////////////////////////////////////// // Utils diff --git a/bindings/core/src/method_handler/account.rs b/bindings/core/src/method_handler/account.rs index 2ac7447d9b..804a0c20cb 100644 --- a/bindings/core/src/method_handler/account.rs +++ b/bindings/core/src/method_handler/account.rs @@ -201,13 +201,13 @@ pub(crate) async fn call_account_method_internal(account: &Account, method: Acco let events = account.register_participation_events(&options).await?; Response::ParticipationEvents(events) } - AccountMethod::RetryTransactionUntilIncluded { + AccountMethod::ReissueTransactionUntilIncluded { transaction_id, interval, max_attempts, } => { let block_id = account - .retry_transaction_until_included(&transaction_id, interval, max_attempts) + .reissue_transaction_until_included(&transaction_id, interval, max_attempts) .await?; Response::BlockId(block_id) } diff --git a/bindings/core/src/method_handler/client.rs b/bindings/core/src/method_handler/client.rs index 35809bc994..227c35c189 100644 --- a/bindings/core/src/method_handler/client.rs +++ b/bindings/core/src/method_handler/client.rs @@ -272,47 +272,9 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM .map(BlockDto::from) .collect(), ), - ClientMethod::Retry { block_id } => { - let (block_id, block) = client - .retry::(&block_id, todo!("coin type"), todo!("secret manager")) - .await?; - Response::BlockIdWithBlock(block_id, BlockDto::from(&block)) - } - ClientMethod::RetryUntilIncluded { - block_id, - interval, - max_attempts, - } => { - let res = client - .retry_until_included::( - &block_id, - interval, - max_attempts, - todo!("coin type"), - todo!("secret manager"), - ) - .await?; - let res = res - .into_iter() - .map(|(block_id, block)| (block_id, BlockDto::from(&block))) - .collect(); - Response::RetryUntilIncludedSuccessful(res) - } ClientMethod::FindInputs { addresses, amount } => { Response::Inputs(client.find_inputs(addresses, amount).await?) } - ClientMethod::Reattach { block_id } => { - let (block_id, block) = client - .reattach::(&block_id, todo!("coin type"), todo!("secret manager")) - .await?; - Response::Reattached((block_id, BlockDto::from(&block))) - } - ClientMethod::ReattachUnchecked { block_id } => { - let (block_id, block) = client - .reattach_unchecked::(&block_id, todo!("coin type"), todo!("secret manager")) - .await?; - Response::Reattached((block_id, BlockDto::from(&block))) - } ClientMethod::HexToBech32 { hex, bech32_hrp } => { Response::Bech32Address(client.hex_to_bech32(&hex, bech32_hrp).await?) } diff --git a/bindings/core/src/response.rs b/bindings/core/src/response.rs index 70c24bf5f6..21a266820c 100644 --- a/bindings/core/src/response.rs +++ b/bindings/core/src/response.rs @@ -108,15 +108,12 @@ pub enum Response { Block(BlockDto), /// Response for: /// - [`PostBlockPayload`](crate::method::ClientMethod::PostBlockPayload) - /// - [`Retry`](crate::method::ClientMethod::Retry) BlockIdWithBlock(BlockId, BlockDto), /// Response for: /// - [`GetBlockMetadata`](crate::method::ClientMethod::GetBlockMetadata) BlockMetadata(BlockMetadataResponse), /// Response for: /// - [`GetBlockRaw`](crate::method::ClientMethod::GetBlockRaw) - /// - [`GetMilestoneByIdRaw`](crate::method::ClientMethod::GetMilestoneByIdRaw) - /// - [`GetMilestoneByIndexRaw`](crate::method::ClientMethod::GetMilestoneByIndexRaw) Raw(Vec), /// Response for: /// - [`GetOutput`](crate::method::ClientMethod::GetOutput) @@ -143,19 +140,12 @@ pub enum Response { /// - [`FindBlocks`](crate::method::ClientMethod::FindBlocks) Blocks(Vec), /// Response for: - /// - [`RetryUntilIncluded`](crate::method::ClientMethod::RetryUntilIncluded) - RetryUntilIncludedSuccessful(Vec<(BlockId, BlockDto)>), - /// Response for: /// - [`FindInputs`](crate::method::ClientMethod::FindInputs) Inputs(Vec), /// Response for: /// [`OutputIdToUtxoInput`](crate::method::UtilsMethod::OutputIdToUtxoInput) Input(UtxoInput), /// Response for: - /// - [`Reattach`](crate::method::ClientMethod::Reattach) - /// - [`ReattachUnchecked`](crate::method::ClientMethod::ReattachUnchecked) - Reattached((BlockId, BlockDto)), - /// Response for: /// - [`Bech32ToHex`](crate::method::UtilsMethod::Bech32ToHex) Bech32ToHex(String), /// Response for: @@ -219,7 +209,7 @@ pub enum Response { /// - [`BlockId`](crate::method::UtilsMethod::BlockId) /// - [`PostBlock`](crate::method::ClientMethod::PostBlock) /// - [`PostBlockRaw`](crate::method::ClientMethod::PostBlockRaw) - /// - [`RetryTransactionUntilIncluded`](crate::method::AccountMethod::RetryTransactionUntilIncluded) + /// - [`ReissueTransactionUntilIncluded`](crate::method::AccountMethod::ReissueTransactionUntilIncluded) BlockId(BlockId), /// Response for: /// - [`GetHealth`](crate::method::ClientMethod::GetHealth) diff --git a/bindings/nodejs/examples/how_tos/accounts_and_addresses/consolidate-outputs.ts b/bindings/nodejs/examples/how_tos/accounts_and_addresses/consolidate-outputs.ts index 0d033560d3..1a5f91cc22 100644 --- a/bindings/nodejs/examples/how_tos/accounts_and_addresses/consolidate-outputs.ts +++ b/bindings/nodejs/examples/how_tos/accounts_and_addresses/consolidate-outputs.ts @@ -74,7 +74,7 @@ async function run() { console.log('Transaction sent: %s', transaction.transactionId); // Wait for the consolidation transaction to get confirmed - const blockId = account.retryTransactionUntilIncluded( + const blockId = account.reissueTransactionUntilIncluded( transaction.transactionId, ); diff --git a/bindings/nodejs/examples/how_tos/advanced_transactions/advanced_transaction.ts b/bindings/nodejs/examples/how_tos/advanced_transactions/advanced_transaction.ts index 2659d4f04d..c3239e6e2d 100644 --- a/bindings/nodejs/examples/how_tos/advanced_transactions/advanced_transaction.ts +++ b/bindings/nodejs/examples/how_tos/advanced_transactions/advanced_transaction.ts @@ -55,7 +55,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); console.log('Waiting until included in block...'); - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); console.log(`Block sent: ${process.env.EXPLORER_URL}/block/${blockId}`); diff --git a/bindings/nodejs/examples/how_tos/advanced_transactions/claim_transaction.ts b/bindings/nodejs/examples/how_tos/advanced_transactions/claim_transaction.ts index 0a37b082c5..5d586875ed 100644 --- a/bindings/nodejs/examples/how_tos/advanced_transactions/claim_transaction.ts +++ b/bindings/nodejs/examples/how_tos/advanced_transactions/claim_transaction.ts @@ -38,7 +38,7 @@ async function run() { const transaction = await account.claimOutputs(output_ids); console.log(`Transaction sent: ${transaction.transactionId}`); - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); console.log(`Block sent: ${process.env.EXPLORER_URL}/block/${blockId}`); diff --git a/bindings/nodejs/examples/how_tos/advanced_transactions/send_micro_transaction.ts b/bindings/nodejs/examples/how_tos/advanced_transactions/send_micro_transaction.ts index 090ab1a8b4..22da16ac31 100644 --- a/bindings/nodejs/examples/how_tos/advanced_transactions/send_micro_transaction.ts +++ b/bindings/nodejs/examples/how_tos/advanced_transactions/send_micro_transaction.ts @@ -39,7 +39,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); diff --git a/bindings/nodejs/examples/how_tos/alias/create.ts b/bindings/nodejs/examples/how_tos/alias/create.ts index 799027c7b0..571f162f9a 100644 --- a/bindings/nodejs/examples/how_tos/alias/create.ts +++ b/bindings/nodejs/examples/how_tos/alias/create.ts @@ -57,7 +57,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); console.log( diff --git a/bindings/nodejs/examples/how_tos/alias/destroy.ts b/bindings/nodejs/examples/how_tos/alias/destroy.ts index daf06145a4..99917aed61 100644 --- a/bindings/nodejs/examples/how_tos/alias/destroy.ts +++ b/bindings/nodejs/examples/how_tos/alias/destroy.ts @@ -60,7 +60,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); console.log( diff --git a/bindings/nodejs/examples/how_tos/alias_wallet/transaction.ts b/bindings/nodejs/examples/how_tos/alias_wallet/transaction.ts index 0ffe4ef766..9e7fb0cc9e 100644 --- a/bindings/nodejs/examples/how_tos/alias_wallet/transaction.ts +++ b/bindings/nodejs/examples/how_tos/alias_wallet/transaction.ts @@ -75,7 +75,9 @@ async function run() { allowMicroAmount: false, }; const transaction = await account.sendWithParams(params, options); - await account.retryTransactionUntilIncluded(transaction.transactionId); + await account.reissueTransactionUntilIncluded( + transaction.transactionId, + ); console.log( `Transaction with custom input: https://explorer.iota.org/testnet/transaction/${transaction.transactionId}`, ); diff --git a/bindings/nodejs/examples/how_tos/native_tokens/burn.ts b/bindings/nodejs/examples/how_tos/native_tokens/burn.ts index 1d4ba6e527..5f68f0fa76 100644 --- a/bindings/nodejs/examples/how_tos/native_tokens/burn.ts +++ b/bindings/nodejs/examples/how_tos/native_tokens/burn.ts @@ -56,7 +56,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); diff --git a/bindings/nodejs/examples/how_tos/native_tokens/create.ts b/bindings/nodejs/examples/how_tos/native_tokens/create.ts index 3c2ae2d643..0c97eb3ad0 100644 --- a/bindings/nodejs/examples/how_tos/native_tokens/create.ts +++ b/bindings/nodejs/examples/how_tos/native_tokens/create.ts @@ -37,7 +37,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); @@ -64,7 +64,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); diff --git a/bindings/nodejs/examples/how_tos/native_tokens/destroy-foundry.ts b/bindings/nodejs/examples/how_tos/native_tokens/destroy-foundry.ts index 2e7040cd31..50ac1e83fe 100644 --- a/bindings/nodejs/examples/how_tos/native_tokens/destroy-foundry.ts +++ b/bindings/nodejs/examples/how_tos/native_tokens/destroy-foundry.ts @@ -39,7 +39,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); console.log( diff --git a/bindings/nodejs/examples/how_tos/native_tokens/melt.ts b/bindings/nodejs/examples/how_tos/native_tokens/melt.ts index f4e0ec8e6d..fa21e00752 100644 --- a/bindings/nodejs/examples/how_tos/native_tokens/melt.ts +++ b/bindings/nodejs/examples/how_tos/native_tokens/melt.ts @@ -50,7 +50,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); diff --git a/bindings/nodejs/examples/how_tos/native_tokens/mint.ts b/bindings/nodejs/examples/how_tos/native_tokens/mint.ts index 241b5c19c9..6fa0aead4b 100644 --- a/bindings/nodejs/examples/how_tos/native_tokens/mint.ts +++ b/bindings/nodejs/examples/how_tos/native_tokens/mint.ts @@ -49,7 +49,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); diff --git a/bindings/nodejs/examples/how_tos/native_tokens/send.ts b/bindings/nodejs/examples/how_tos/native_tokens/send.ts index b8a17e6b8a..fd3f546c98 100644 --- a/bindings/nodejs/examples/how_tos/native_tokens/send.ts +++ b/bindings/nodejs/examples/how_tos/native_tokens/send.ts @@ -59,7 +59,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); diff --git a/bindings/nodejs/examples/how_tos/nft_collection/00_mint_issuer_nft.ts b/bindings/nodejs/examples/how_tos/nft_collection/00_mint_issuer_nft.ts index 38fa699adc..495a873434 100644 --- a/bindings/nodejs/examples/how_tos/nft_collection/00_mint_issuer_nft.ts +++ b/bindings/nodejs/examples/how_tos/nft_collection/00_mint_issuer_nft.ts @@ -54,7 +54,7 @@ async function run() { const transaction = await prepared.send(); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); console.log( diff --git a/bindings/nodejs/examples/how_tos/nft_collection/01_mint_collection_nft.ts b/bindings/nodejs/examples/how_tos/nft_collection/01_mint_collection_nft.ts index 2a294b0f3c..2dc45d4c80 100644 --- a/bindings/nodejs/examples/how_tos/nft_collection/01_mint_collection_nft.ts +++ b/bindings/nodejs/examples/how_tos/nft_collection/01_mint_collection_nft.ts @@ -76,7 +76,7 @@ async function run() { const transaction = await prepared.send(); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); console.log( diff --git a/bindings/nodejs/examples/how_tos/nfts/burn_nft.ts b/bindings/nodejs/examples/how_tos/nfts/burn_nft.ts index 52f0e0eff0..c9ac0ef987 100644 --- a/bindings/nodejs/examples/how_tos/nfts/burn_nft.ts +++ b/bindings/nodejs/examples/how_tos/nfts/burn_nft.ts @@ -51,7 +51,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); console.log( diff --git a/bindings/nodejs/examples/how_tos/nfts/mint_nft.ts b/bindings/nodejs/examples/how_tos/nfts/mint_nft.ts index 5ce684ca48..c19065955e 100644 --- a/bindings/nodejs/examples/how_tos/nfts/mint_nft.ts +++ b/bindings/nodejs/examples/how_tos/nfts/mint_nft.ts @@ -66,7 +66,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - let blockId = await account.retryTransactionUntilIncluded( + let blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); @@ -97,7 +97,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - blockId = await account.retryTransactionUntilIncluded( + blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); diff --git a/bindings/nodejs/examples/how_tos/nfts/send_nft.ts b/bindings/nodejs/examples/how_tos/nfts/send_nft.ts index 4bd4b1386b..3cba7cdfc4 100644 --- a/bindings/nodejs/examples/how_tos/nfts/send_nft.ts +++ b/bindings/nodejs/examples/how_tos/nfts/send_nft.ts @@ -57,7 +57,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); diff --git a/bindings/nodejs/examples/wallet/06-send-micro-transaction.ts b/bindings/nodejs/examples/wallet/06-send-micro-transaction.ts index 0a69fab288..d466cd282e 100644 --- a/bindings/nodejs/examples/wallet/06-send-micro-transaction.ts +++ b/bindings/nodejs/examples/wallet/06-send-micro-transaction.ts @@ -42,7 +42,7 @@ async function run() { console.log(`Transaction sent: ${transaction.transactionId}`); // Wait for transaction to get included - const blockId = await account.retryTransactionUntilIncluded( + const blockId = await account.reissueTransactionUntilIncluded( transaction.transactionId, ); diff --git a/bindings/nodejs/lib/client/client.ts b/bindings/nodejs/lib/client/client.ts index 77c9ccfadc..a7a9588d93 100644 --- a/bindings/nodejs/lib/client/client.ts +++ b/bindings/nodejs/lib/client/client.ts @@ -585,80 +585,6 @@ export class Client { return plainToInstance(Block, parsed.payload); } - /** - * Retries (promotes or reattaches) a block for provided block id. Block should be - * retried only if they are valid and haven't been confirmed for a while. - */ - async retry(blockId: BlockId): Promise<[BlockId, Block]> { - const response = await this.methodHandler.callMethod({ - name: 'retry', - data: { - blockId, - }, - }); - const parsed = JSON.parse(response) as Response<[BlockId, Block]>; - const block = plainToInstance(Block, parsed.payload[1]); - return [parsed.payload[0], block]; - } - - /** - * Retries (promotes or reattaches) a block for provided block id until it's included (referenced by a - * milestone). Default interval is 5 seconds and max attempts is 40. Returns the included block at first - * position and additional reattached blocks - */ - async retryUntilIncluded( - blockId: BlockId, - interval?: number, - maxAttempts?: number, - ): Promise<[BlockId, Block][]> { - const response = await this.methodHandler.callMethod({ - name: 'retryUntilIncluded', - data: { - blockId, - interval, - maxAttempts, - }, - }); - const parsed = JSON.parse(response) as Response<[BlockId, Block][]>; - const arr: [BlockId, Block][] = []; - parsed.payload.forEach((payload) => { - arr.push([payload[0], plainToInstance(Block, payload[1])]); - }); - - return arr; - } - - /** - * Reattaches blocks for provided block id. Blocks can be reattached only if they are valid and haven't been - * confirmed for a while. - */ - async reattach(blockId: BlockId): Promise<[BlockId, Block]> { - const response = await this.methodHandler.callMethod({ - name: 'reattach', - data: { - blockId, - }, - }); - const parsed = JSON.parse(response) as Response<[BlockId, Block]>; - const block = plainToInstance(Block, parsed.payload[1]); - return [parsed.payload[0], block]; - } - - /** - * Reattach a block without checking if it should be reattached - */ - async reattachUnchecked(blockId: BlockId): Promise<[BlockId, Block]> { - const response = await this.methodHandler.callMethod({ - name: 'reattachUnchecked', - data: { - blockId, - }, - }); - const parsed = JSON.parse(response) as Response<[BlockId, Block]>; - const block = plainToInstance(Block, parsed.payload[1]); - return [parsed.payload[0], block]; - } - /** * Returns the unhealthy nodes. */ diff --git a/bindings/nodejs/lib/types/client/bridge/client.ts b/bindings/nodejs/lib/types/client/bridge/client.ts index 543688217a..c16c9d1884 100644 --- a/bindings/nodejs/lib/types/client/bridge/client.ts +++ b/bindings/nodejs/lib/types/client/bridge/client.ts @@ -257,36 +257,6 @@ export interface __FindBlocksMethod__ { }; } -export interface __RetryMethod__ { - name: 'retry'; - data: { - blockId: string; - }; -} - -export interface __RetryUntilIncludedMethod__ { - name: 'retryUntilIncluded'; - data: { - blockId: string; - interval?: number; - maxAttempts?: number; - }; -} - -export interface __ReattachMethod__ { - name: 'reattach'; - data: { - blockId: BlockId; - }; -} - -export interface __ReattachUncheckedMethod__ { - name: 'reattachUnchecked'; - data: { - blockId: BlockId; - }; -} - export interface __UnhealthyNodesMethod__ { name: 'unhealthyNodes'; } diff --git a/bindings/nodejs/lib/types/client/bridge/index.ts b/bindings/nodejs/lib/types/client/bridge/index.ts index 70f6472eb1..858baa2e96 100644 --- a/bindings/nodejs/lib/types/client/bridge/index.ts +++ b/bindings/nodejs/lib/types/client/bridge/index.ts @@ -37,10 +37,6 @@ import type { __FoundryOutputIdMethod__, __GetOutputsIgnoreErrorsMethod__, __FindBlocksMethod__, - __RetryMethod__, - __RetryUntilIncludedMethod__, - __ReattachMethod__, - __ReattachUncheckedMethod__, __UnhealthyNodesMethod__, __BuildBasicOutputMethod__, __BuildAliasOutputMethod__, @@ -90,10 +86,6 @@ export type __ClientMethods__ = | __FoundryOutputIdMethod__ | __GetOutputsIgnoreErrorsMethod__ | __FindBlocksMethod__ - | __RetryMethod__ - | __RetryUntilIncludedMethod__ - | __ReattachMethod__ - | __ReattachUncheckedMethod__ | __UnhealthyNodesMethod__ | __BuildBasicOutputMethod__ | __BuildAliasOutputMethod__ diff --git a/bindings/nodejs/lib/types/wallet/account.ts b/bindings/nodejs/lib/types/wallet/account.ts index f7d1382b24..2625c4c123 100644 --- a/bindings/nodejs/lib/types/wallet/account.ts +++ b/bindings/nodejs/lib/types/wallet/account.ts @@ -87,7 +87,7 @@ export interface SyncOptions { /// Try to sync transactions from incoming outputs with their inputs. Some data may not be obtained if it has been /// pruned. syncIncomingTransactions?: boolean; - /** Checks pending transactions and promotes/reattaches them if necessary. Default: true. */ + /** Checks pending transactions and reissues them if necessary. Default: true. */ syncPendingTransactions?: boolean; /** Specifies what outputs should be synced for the ed25519 addresses from the account. */ account?: AccountSyncOptions; diff --git a/bindings/nodejs/lib/types/wallet/bridge/account.ts b/bindings/nodejs/lib/types/wallet/bridge/account.ts index e4fd110c5d..421bffd2a7 100644 --- a/bindings/nodejs/lib/types/wallet/bridge/account.ts +++ b/bindings/nodejs/lib/types/wallet/bridge/account.ts @@ -235,8 +235,8 @@ export type __RegisterParticipationEventsMethod__ = { }; }; -export type __RetryTransactionUntilIncludedMethod__ = { - name: 'retryTransactionUntilIncluded'; +export type __ReissueTransactionUntilIncludedMethod__ = { + name: 'reissueTransactionUntilIncluded'; data: { transactionId: string; interval?: number; diff --git a/bindings/nodejs/lib/types/wallet/bridge/index.ts b/bindings/nodejs/lib/types/wallet/bridge/index.ts index a62d11a796..d747a00eb8 100644 --- a/bindings/nodejs/lib/types/wallet/bridge/index.ts +++ b/bindings/nodejs/lib/types/wallet/bridge/index.ts @@ -30,7 +30,7 @@ import type { __PrepareSendMethod__, __PrepareTransactionMethod__, __RegisterParticipationEventsMethod__, - __RetryTransactionUntilIncludedMethod__, + __ReissueTransactionUntilIncludedMethod__, __SendMethod__, __SendWithParamsMethod__, __PrepareSendNativeTokensMethod__, @@ -115,7 +115,7 @@ export type __AccountMethod__ = | __PrepareSendMethod__ | __PrepareTransactionMethod__ | __RegisterParticipationEventsMethod__ - | __RetryTransactionUntilIncludedMethod__ + | __ReissueTransactionUntilIncludedMethod__ | __SendMethod__ | __SendWithParamsMethod__ | __PrepareSendNativeTokensMethod__ diff --git a/bindings/nodejs/lib/wallet/account.ts b/bindings/nodejs/lib/wallet/account.ts index 2ef3d9cf37..5f8c14b711 100644 --- a/bindings/nodejs/lib/wallet/account.ts +++ b/bindings/nodejs/lib/wallet/account.ts @@ -978,10 +978,10 @@ export class Account { } /** - * Retries (promotes or reattaches) a transaction sent from the account for a provided transaction id until it's + * Reissues a transaction sent from the account for a provided transaction id until it's * included (referenced by a milestone). Returns the included block id. */ - async retryTransactionUntilIncluded( + async reissueTransactionUntilIncluded( transactionId: string, interval?: number, maxAttempts?: number, @@ -989,7 +989,7 @@ export class Account { const response = await this.methodHandler.callAccountMethod( this.meta.index, { - name: 'retryTransactionUntilIncluded', + name: 'reissueTransactionUntilIncluded', data: { transactionId, interval, @@ -1241,7 +1241,7 @@ export class Account { /** * Sync the account by fetching new information from the nodes. - * Will also retry pending transactions if necessary. + * Will also reissue pending transactions if necessary. * A custom default can be set using setDefaultSyncOptions. * * @param options Optional synchronization options. diff --git a/bindings/nodejs/tests/client/messageMethods.spec.ts b/bindings/nodejs/tests/client/messageMethods.spec.ts index 86444f1bae..45d276d579 100644 --- a/bindings/nodejs/tests/client/messageMethods.spec.ts +++ b/bindings/nodejs/tests/client/messageMethods.spec.ts @@ -40,41 +40,4 @@ describe.skip('Block methods', () => { expect(blockRaw).toBeDefined(); }); - - it('reattaches a block', async () => { - const tips = await client.getTips(); - - // Reattach a block without checking if it should be reattached - const reattachUnchecked = await client.reattachUnchecked( - tips[0], - ); - - expect(reattachUnchecked[0]).toBeValidBlockId(); - expect(reattachUnchecked[1]).toBeDefined(); - - // Returns expected error: no need to promote or reattach. - await expect(client.reattach(tips[0])).rejects.toMatch( - 'NoNeedPromoteOrReattach', - ); - }); - - // Skip by default, retryUntilIncluded can be slow - it.skip('retries a block', async () => { - const tips = await client.getTips(); - - // Retries (promotes or reattaches) a block for provided block id until it's included - // (referenced by a milestone). Default interval is 5 seconds and max attempts is 40. - const retryUntilIncluded = await client.retryUntilIncluded( - tips[0], - 2, - 5, - ); - //Returns the included block at first position and additional reattached blocks - expect(retryUntilIncluded[0][0]).toBe(tips[0]); - - // Returns expected error: no need to promote or reattach. - await expect(client.retry(tips[0])).rejects.toMatch( - 'NoNeedPromoteOrReattach', - ); - }); }); diff --git a/bindings/python/examples/how_tos/accounts_and_addresses/consolidate_outputs.py b/bindings/python/examples/how_tos/accounts_and_addresses/consolidate_outputs.py index 33e2252392..a02bb4e67b 100644 --- a/bindings/python/examples/how_tos/accounts_and_addresses/consolidate_outputs.py +++ b/bindings/python/examples/how_tos/accounts_and_addresses/consolidate_outputs.py @@ -50,7 +50,8 @@ print('Transaction sent: ', transaction.transactionId) # Wait for the consolidation transaction to get confirmed -block_id = account.retry_transaction_until_included(transaction.transactionId) +block_id = account.reissue_transaction_until_included( + transaction.transactionId) print( 'Transaction included: {}/block/{}'.format( diff --git a/bindings/python/examples/how_tos/advanced_transactions/advanced_transaction.py b/bindings/python/examples/how_tos/advanced_transactions/advanced_transaction.py index 8a9e95e25a..047a7236cb 100644 --- a/bindings/python/examples/how_tos/advanced_transactions/advanced_transaction.py +++ b/bindings/python/examples/how_tos/advanced_transactions/advanced_transaction.py @@ -39,7 +39,8 @@ transaction = account.send_outputs([basic_output]) print(f'Transaction sent: {transaction.transactionId}') -block_id = account.retry_transaction_until_included(transaction.transactionId) +block_id = account.reissue_transaction_until_included( + transaction.transactionId) print( f'Block sent: {os.environ["EXPLORER_URL"]}/block/{block_id}') diff --git a/bindings/python/examples/how_tos/advanced_transactions/claim_transaction.py b/bindings/python/examples/how_tos/advanced_transactions/claim_transaction.py index f2956745f6..c6265db4ce 100644 --- a/bindings/python/examples/how_tos/advanced_transactions/claim_transaction.py +++ b/bindings/python/examples/how_tos/advanced_transactions/claim_transaction.py @@ -29,5 +29,6 @@ transaction = account.claim_outputs(output_ids) print(f'Transaction sent: {transaction.transactionId}') -block_id = account.retry_transaction_until_included(transaction) +block_id = account.reissue_transaction_until_included( + transaction.transactionId) print(f'Block sent: {os.environ["EXPLORER_URL"]}/block/{block_id}') diff --git a/bindings/python/examples/how_tos/advanced_transactions/send_micro_transaction.py b/bindings/python/examples/how_tos/advanced_transactions/send_micro_transaction.py index 9d58fd6d9b..bfa021cf4a 100644 --- a/bindings/python/examples/how_tos/advanced_transactions/send_micro_transaction.py +++ b/bindings/python/examples/how_tos/advanced_transactions/send_micro_transaction.py @@ -26,7 +26,8 @@ transaction = account.send_with_params(params, {"allowMicroAmount": True}) print(f'Transaction sent: {transaction.transactionId}') -block_id = account.retry_transaction_until_included(transaction.transactionId) +block_id = account.reissue_transaction_until_included( + transaction.transactionId) print( f'Block sent: {os.environ["EXPLORER_URL"]}/block/{block_id}') diff --git a/bindings/python/examples/how_tos/alias_wallet/transaction.py b/bindings/python/examples/how_tos/alias_wallet/transaction.py index 93c24344ae..57c9c9423f 100644 --- a/bindings/python/examples/how_tos/alias_wallet/transaction.py +++ b/bindings/python/examples/how_tos/alias_wallet/transaction.py @@ -41,7 +41,8 @@ 'mandatoryInputs': [input], } transaction = account.send_with_params(params, options) -account.retry_transaction_until_included(transaction.transactionId, None, None) +account.reissue_transaction_until_included( + transaction.transactionId) print( f'Transaction with custom input: https://explorer.shimmer.network/testnet/transaction/{transaction.transactionId}') diff --git a/bindings/python/examples/how_tos/native_tokens/burn.py b/bindings/python/examples/how_tos/native_tokens/burn.py index cf48b79f88..e5d411d707 100644 --- a/bindings/python/examples/how_tos/native_tokens/burn.py +++ b/bindings/python/examples/how_tos/native_tokens/burn.py @@ -33,7 +33,7 @@ print(f'Transaction sent: {transaction.transactionId}') # Wait for transaction to get included -blockId = account.retry_transaction_until_included(transaction.transactionId) +blockId = account.reissue_transaction_until_included(transaction.transactionId) print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{blockId}') balance = account.sync() diff --git a/bindings/python/examples/how_tos/native_tokens/create.py b/bindings/python/examples/how_tos/native_tokens/create.py index e35bbeecb9..24b991ee89 100644 --- a/bindings/python/examples/how_tos/native_tokens/create.py +++ b/bindings/python/examples/how_tos/native_tokens/create.py @@ -27,7 +27,7 @@ print(f'Transaction sent: {transaction.transactionId}') # Wait for transaction to get included - blockId = account.retry_transaction_until_included( + blockId = account.reissue_transaction_until_included( transaction.transactionId) print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{blockId}') @@ -47,7 +47,7 @@ print(f'Transaction sent: {transaction.transactionId}') # Wait for transaction to get included -blockId = account.retry_transaction_until_included(transaction.transactionId) +blockId = account.reissue_transaction_until_included(transaction.transactionId) print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{blockId}') print(f'Created token: {prepared_transaction.token_id()}') diff --git a/bindings/python/examples/how_tos/native_tokens/destroy_foundry.py b/bindings/python/examples/how_tos/native_tokens/destroy_foundry.py index f8eba3785b..eea91740f6 100644 --- a/bindings/python/examples/how_tos/native_tokens/destroy_foundry.py +++ b/bindings/python/examples/how_tos/native_tokens/destroy_foundry.py @@ -27,7 +27,7 @@ print(f'Transaction sent: {transaction.transactionId}') # Wait for transaction to get included -blockId = account.retry_transaction_until_included(transaction.transactionId) +blockId = account.reissue_transaction_until_included(transaction.transactionId) print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{blockId}') balance = account.sync() diff --git a/bindings/python/examples/how_tos/native_tokens/melt.py b/bindings/python/examples/how_tos/native_tokens/melt.py index 18992f6782..b8ee497032 100644 --- a/bindings/python/examples/how_tos/native_tokens/melt.py +++ b/bindings/python/examples/how_tos/native_tokens/melt.py @@ -32,7 +32,7 @@ print(f'Transaction sent: {transaction.transactionId}') # Wait for transaction to get included -blockId = account.retry_transaction_until_included( +blockId = account.reissue_transaction_until_included( transaction.transactionId) print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{blockId}') diff --git a/bindings/python/examples/how_tos/native_tokens/mint.py b/bindings/python/examples/how_tos/native_tokens/mint.py index 7f08492e74..666659409a 100644 --- a/bindings/python/examples/how_tos/native_tokens/mint.py +++ b/bindings/python/examples/how_tos/native_tokens/mint.py @@ -32,7 +32,7 @@ print(f'Transaction sent: {transaction.transactionId}') # Wait for transaction to get included -blockId = account.retry_transaction_until_included( +blockId = account.reissue_transaction_until_included( transaction.transactionId) print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{blockId}') diff --git a/bindings/python/examples/how_tos/native_tokens/send.py b/bindings/python/examples/how_tos/native_tokens/send.py index 7aabebfd27..a39accc5f7 100644 --- a/bindings/python/examples/how_tos/native_tokens/send.py +++ b/bindings/python/examples/how_tos/native_tokens/send.py @@ -34,7 +34,7 @@ print(f'Transaction sent: {transaction.transactionId}') # Wait for transaction to get included -blockId = account.retry_transaction_until_included(transaction.transactionId) +blockId = account.reissue_transaction_until_included(transaction.transactionId) print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{blockId}') balance = account.sync() diff --git a/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py b/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py index cc1ed0cc09..35e42d1fb0 100644 --- a/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py +++ b/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py @@ -30,7 +30,8 @@ transaction = prepared.send() # Wait for transaction to get included -block_id = account.retry_transaction_until_included(transaction.transactionId) +block_id = account.reissue_transaction_until_included( + transaction.transactionId) print( f'Block sent: {os.environ["EXPLORER_URL"]}/block/{block_id}') diff --git a/bindings/python/examples/how_tos/nft_collection/01_mint_collection_nft.py b/bindings/python/examples/how_tos/nft_collection/01_mint_collection_nft.py index e8774d900a..68b1bef968 100644 --- a/bindings/python/examples/how_tos/nft_collection/01_mint_collection_nft.py +++ b/bindings/python/examples/how_tos/nft_collection/01_mint_collection_nft.py @@ -64,7 +64,7 @@ def get_immutable_metadata(index: int, issuer_nft_id: str) -> str: transaction = prepared.send() # Wait for transaction to get included - block_id = account.retry_transaction_until_included( + block_id = account.reissue_transaction_until_included( transaction.transactionId) print( diff --git a/bindings/python/examples/wallet/offline_signing/3_send_transaction.py b/bindings/python/examples/wallet/offline_signing/3_send_transaction.py index 2ad5e6e760..6240a3fd1f 100644 --- a/bindings/python/examples/wallet/offline_signing/3_send_transaction.py +++ b/bindings/python/examples/wallet/offline_signing/3_send_transaction.py @@ -30,5 +30,6 @@ transaction = account.submit_and_store_transaction(signed_transaction_data) print( f'Transaction sent: {os.environ["EXPLORER_URL"]}/transaction/{transaction.transactionId}') -block_id = account.retry_transaction_until_included(transaction.transactionId) +block_id = account.reissue_transaction_until_included( + transaction.transactionId) print(f'Block included: {os.environ["EXPLORER_URL"]}/block/{block_id}') diff --git a/bindings/python/iota_sdk/client/_high_level_api.py b/bindings/python/iota_sdk/client/_high_level_api.py index 4a580c8355..926748dde2 100644 --- a/bindings/python/iota_sdk/client/_high_level_api.py +++ b/bindings/python/iota_sdk/client/_high_level_api.py @@ -126,40 +126,6 @@ def find_blocks(self, block_ids: List[HexStr]) -> List[Block]: }) return [Block.from_dict(block) for block in blocks] - def retry(self, block_id: HexStr) -> List[HexStr | Block]: - """Retries (promotes or reattaches) a block for provided block id. Block should only be - retried only if they are valid and haven't been confirmed for a while. - - Args: - block_id: A block id. - - Returns: - A list where the first element is the block id and the second one the block. - """ - result = self._call_method('retry', {'blockId': block_id}) - result[1] = Block.from_dict(result[1]) - return result - - def retry_until_included( - self, block_id: HexStr, interval: Optional[int] = None, max_attempts: Optional[int] = None) -> List[List[HexStr | Block]]: - """Retries (promotes or reattaches) a block for provided block id until it's included (referenced by a - milestone). Default interval is 5 seconds and max attempts is 40. Returns the included block at first - position and additional reattached blocks. - - Args: - block_id: A block id. - interval: A retry interval in seconds. Defaults to 5. - max_attempts: A maximum number of retries. Defaults to 40. - - Returns: - A list of lists where the first element is the block id and the second one the block. - """ - result = self._call_method('retryUntilIncluded', { - 'blockId': block_id, - 'interval': interval, - 'maxAttempts': max_attempts - }) - def find_inputs(self, addresses: List[str], amount: int): """Function to find inputs from addresses for a provided amount(useful for offline signing). @@ -171,34 +137,3 @@ def find_inputs(self, addresses: List[str], amount: int): 'addresses': addresses, 'amount': amount }) - - def reattach(self, block_id: HexStr) -> List[HexStr | Block]: - """Reattaches blocks for a provided block id. Blocks can be reattached only if they are valid and - haven't been confirmed for a while . - - Args: - block_id: A block id of a block that should be reattached. - - Returns: - The reattached block id and block. - """ - result = self._call_method('reattach', { - 'blockId': block_id - }) - result[1] = Block.from_dict(result[1]) - return result - - def reattach_unchecked(self, block_id: HexStr) -> List[HexStr | Block]: - """Reattach a block without checking if it should be reattached. - - Args: - block_id: A block id of a block that should be reattached. - - Returns: - The reattached block id and block. - """ - result = self._call_method('reattachUnchecked', { - 'blockId': block_id - }) - result[1] = Block.from_dict(result[1]) - return result diff --git a/bindings/python/iota_sdk/wallet/account.py b/bindings/python/iota_sdk/wallet/account.py index e68b5797a5..7183c5580a 100644 --- a/bindings/python/iota_sdk/wallet/account.py +++ b/bindings/python/iota_sdk/wallet/account.py @@ -373,13 +373,13 @@ def prepare_transaction( ) return PreparedTransaction(self, prepared) - def retry_transaction_until_included( + def reissue_transaction_until_included( self, transaction_id: HexStr, interval=None, max_attempts=None) -> HexStr: - """Retries (promotes or reattaches) a transaction sent from the account for a provided transaction id until it's + """Reissues a transaction sent from the account for a provided transaction id until it's included (referenced by a milestone). Returns the included block id. """ return self._call_account_method( - 'retryTransactionUntilIncluded', { + 'reissueTransactionUntilIncluded', { 'transactionId': transaction_id, 'interval': interval, 'maxAttempts': max_attempts @@ -388,7 +388,7 @@ def retry_transaction_until_included( def sync(self, options: Optional[SyncOptions] = None) -> Balance: """Sync the account by fetching new information from the nodes. - Will also retry pending transactions and consolidate outputs if necessary. + Will also reissue pending transactions and consolidate outputs if necessary. A custom default can be set using set_default_sync_options. """ return from_dict(Balance, self._call_account_method( diff --git a/bindings/python/iota_sdk/wallet/sync_options.py b/bindings/python/iota_sdk/wallet/sync_options.py index 6671048f70..8f4ad050f2 100644 --- a/bindings/python/iota_sdk/wallet/sync_options.py +++ b/bindings/python/iota_sdk/wallet/sync_options.py @@ -88,7 +88,7 @@ class SyncOptions(): Try to sync transactions from incoming outputs with their inputs. Some data may not be obtained if it has been pruned. sync_pending_transactions : - Checks pending transactions and promotes/reattaches them if necessary. + Checks pending transactions and reissues them if necessary. account : Specifies what outputs should be synced for the Ed25519 addresses from the account. alias : diff --git a/cli/src/command/account.rs b/cli/src/command/account.rs index 34ec439c90..62adf5bf70 100644 --- a/cli/src/command/account.rs +++ b/cli/src/command/account.rs @@ -440,7 +440,7 @@ pub async fn create_native_token_command( transaction.block_id ); account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; // Sync account after the transaction got confirmed, so the account output is available account.sync(None).await?; diff --git a/sdk/examples/client/block/01_block_confirmation_time.rs b/sdk/examples/client/block/01_block_confirmation_time.rs index 1f23d92bb5..c79f1b2574 100644 --- a/sdk/examples/client/block/01_block_confirmation_time.rs +++ b/sdk/examples/client/block/01_block_confirmation_time.rs @@ -39,10 +39,15 @@ async fn main() -> Result<()> { println!("{block:#?}"); - // Try to check if the block has been confirmed. - client - .retry_until_included(&block_id, None, None, IOTA_COIN_TYPE, &secret_manager) - .await?; + // Wait for the block to get included + for _ in 0..30 { + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + let metadata = client.get_block_metadata(&block_id).await?; + if metadata.ledger_inclusion_state.is_some() { + break; + } + } + println!( "Block with no payload included: {}/block/{}", std::env::var("EXPLORER_URL").unwrap(), diff --git a/sdk/examples/client/send_all.rs b/sdk/examples/client/send_all.rs index 5a8591bc11..59d99627ae 100644 --- a/sdk/examples/client/send_all.rs +++ b/sdk/examples/client/send_all.rs @@ -92,7 +92,5 @@ async fn main() -> Result<()> { block.id() ); - let _ = client.retry_until_included(&block.id(), None, None).await?; - Ok(()) } diff --git a/sdk/examples/how_tos/account/create.rs b/sdk/examples/how_tos/account/create.rs index 2f1e3007bb..a0b2263b7b 100644 --- a/sdk/examples/how_tos/account/create.rs +++ b/sdk/examples/how_tos/account/create.rs @@ -41,7 +41,7 @@ async fn main() -> Result<()> { println!("Transaction sent: {}", transaction.transaction_id); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/how_tos/account/destroy.rs b/sdk/examples/how_tos/account/destroy.rs index 5a8a689659..1c9388e361 100644 --- a/sdk/examples/how_tos/account/destroy.rs +++ b/sdk/examples/how_tos/account/destroy.rs @@ -44,7 +44,7 @@ async fn main() -> Result<()> { println!("Transaction sent: {}", transaction.transaction_id); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( diff --git a/sdk/examples/how_tos/account_wallet/transaction.rs b/sdk/examples/how_tos/account_wallet/transaction.rs index a561c7495c..ec146dfe4d 100644 --- a/sdk/examples/how_tos/account_wallet/transaction.rs +++ b/sdk/examples/how_tos/account_wallet/transaction.rs @@ -71,7 +71,7 @@ async fn main() -> Result<()> { ) .await?; account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Transaction with custom input: https://explorer.shimmer.network/testnet/transaction/{}", diff --git a/sdk/examples/how_tos/accounts_and_addresses/consolidate_outputs.rs b/sdk/examples/how_tos/accounts_and_addresses/consolidate_outputs.rs index 60e10b771f..919022d4ad 100644 --- a/sdk/examples/how_tos/accounts_and_addresses/consolidate_outputs.rs +++ b/sdk/examples/how_tos/accounts_and_addresses/consolidate_outputs.rs @@ -66,7 +66,7 @@ async fn main() -> Result<()> { // Wait for the consolidation transaction to get confirmed let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/how_tos/advanced_transactions/advanced_transaction.rs b/sdk/examples/how_tos/advanced_transactions/advanced_transaction.rs index 39bd9ccd1b..34f7825112 100644 --- a/sdk/examples/how_tos/advanced_transactions/advanced_transaction.rs +++ b/sdk/examples/how_tos/advanced_transactions/advanced_transaction.rs @@ -56,7 +56,7 @@ async fn main() -> Result<()> { // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block sent: {}/block/{}", diff --git a/sdk/examples/how_tos/advanced_transactions/claim_transaction.rs b/sdk/examples/how_tos/advanced_transactions/claim_transaction.rs index 4bd018ee05..723d12d877 100644 --- a/sdk/examples/how_tos/advanced_transactions/claim_transaction.rs +++ b/sdk/examples/how_tos/advanced_transactions/claim_transaction.rs @@ -41,7 +41,7 @@ async fn main() -> Result<()> { // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block sent: {}/block/{}", diff --git a/sdk/examples/how_tos/advanced_transactions/send_micro_transaction.rs b/sdk/examples/how_tos/advanced_transactions/send_micro_transaction.rs index da955a04a0..5203d187dc 100644 --- a/sdk/examples/how_tos/advanced_transactions/send_micro_transaction.rs +++ b/sdk/examples/how_tos/advanced_transactions/send_micro_transaction.rs @@ -57,7 +57,7 @@ async fn main() -> Result<()> { // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( diff --git a/sdk/examples/how_tos/native_tokens/burn.rs b/sdk/examples/how_tos/native_tokens/burn.rs index 95d25f061d..887c47a8ce 100644 --- a/sdk/examples/how_tos/native_tokens/burn.rs +++ b/sdk/examples/how_tos/native_tokens/burn.rs @@ -63,7 +63,7 @@ async fn main() -> Result<()> { println!("Transaction sent: {}", transaction.transaction_id); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/how_tos/native_tokens/create.rs b/sdk/examples/how_tos/native_tokens/create.rs index 9a81ed0765..9050003bdf 100644 --- a/sdk/examples/how_tos/native_tokens/create.rs +++ b/sdk/examples/how_tos/native_tokens/create.rs @@ -47,7 +47,7 @@ async fn main() -> Result<()> { // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", @@ -73,7 +73,7 @@ async fn main() -> Result<()> { // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/how_tos/native_tokens/destroy_foundry.rs b/sdk/examples/how_tos/native_tokens/destroy_foundry.rs index ef51b7d795..3d4a2d662e 100644 --- a/sdk/examples/how_tos/native_tokens/destroy_foundry.rs +++ b/sdk/examples/how_tos/native_tokens/destroy_foundry.rs @@ -43,7 +43,7 @@ async fn main() -> Result<()> { println!("Transaction sent: {}", transaction.transaction_id); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/how_tos/native_tokens/melt.rs b/sdk/examples/how_tos/native_tokens/melt.rs index 67198a48e3..8abab66817 100644 --- a/sdk/examples/how_tos/native_tokens/melt.rs +++ b/sdk/examples/how_tos/native_tokens/melt.rs @@ -64,7 +64,7 @@ async fn main() -> Result<()> { println!("Transaction sent: {}", transaction.transaction_id); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( diff --git a/sdk/examples/how_tos/native_tokens/mint.rs b/sdk/examples/how_tos/native_tokens/mint.rs index 0280f55676..4aba7d2ea4 100644 --- a/sdk/examples/how_tos/native_tokens/mint.rs +++ b/sdk/examples/how_tos/native_tokens/mint.rs @@ -63,7 +63,7 @@ async fn main() -> Result<()> { println!("Transaction sent: {}", transaction.transaction_id); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( diff --git a/sdk/examples/how_tos/native_tokens/send.rs b/sdk/examples/how_tos/native_tokens/send.rs index 778c9c1159..c513374920 100644 --- a/sdk/examples/how_tos/native_tokens/send.rs +++ b/sdk/examples/how_tos/native_tokens/send.rs @@ -69,7 +69,7 @@ async fn main() -> Result<()> { // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/how_tos/nft_collection/00_mint_issuer_nft.rs b/sdk/examples/how_tos/nft_collection/00_mint_issuer_nft.rs index 1efc6f0398..98f4ca5757 100644 --- a/sdk/examples/how_tos/nft_collection/00_mint_issuer_nft.rs +++ b/sdk/examples/how_tos/nft_collection/00_mint_issuer_nft.rs @@ -72,7 +72,7 @@ async fn wait_for_inclusion(transaction_id: &TransactionId, account: &Account) - ); // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(transaction_id, None, None) + .reissue_transaction_until_included(transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/how_tos/nft_collection/01_mint_collection_nft.rs b/sdk/examples/how_tos/nft_collection/01_mint_collection_nft.rs index 42c291a804..f3b20b9ba4 100644 --- a/sdk/examples/how_tos/nft_collection/01_mint_collection_nft.rs +++ b/sdk/examples/how_tos/nft_collection/01_mint_collection_nft.rs @@ -114,7 +114,7 @@ async fn wait_for_inclusion(transaction_id: &TransactionId, account: &Account) - ); // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(transaction_id, None, None) + .reissue_transaction_until_included(transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/how_tos/nfts/burn_nft.rs b/sdk/examples/how_tos/nfts/burn_nft.rs index 37182618d2..d6f55adce4 100644 --- a/sdk/examples/how_tos/nfts/burn_nft.rs +++ b/sdk/examples/how_tos/nfts/burn_nft.rs @@ -43,7 +43,7 @@ async fn main() -> Result<()> { println!("Transaction sent: {}", transaction.transaction_id); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( diff --git a/sdk/examples/how_tos/nfts/mint_nft.rs b/sdk/examples/how_tos/nfts/mint_nft.rs index bb116da5fe..16ba504eae 100644 --- a/sdk/examples/how_tos/nfts/mint_nft.rs +++ b/sdk/examples/how_tos/nfts/mint_nft.rs @@ -70,7 +70,7 @@ async fn main() -> Result<()> { // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", @@ -95,7 +95,7 @@ async fn main() -> Result<()> { // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/how_tos/nfts/send_nft.rs b/sdk/examples/how_tos/nfts/send_nft.rs index 2b5df323a9..070c24731a 100644 --- a/sdk/examples/how_tos/nfts/send_nft.rs +++ b/sdk/examples/how_tos/nfts/send_nft.rs @@ -50,7 +50,7 @@ async fn main() -> Result<()> { // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( diff --git a/sdk/examples/how_tos/simple_transaction/simple_transaction.rs b/sdk/examples/how_tos/simple_transaction/simple_transaction.rs index 5e4698ba8e..f1024a5bd6 100644 --- a/sdk/examples/how_tos/simple_transaction/simple_transaction.rs +++ b/sdk/examples/how_tos/simple_transaction/simple_transaction.rs @@ -42,7 +42,7 @@ async fn main() -> Result<()> { // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( diff --git a/sdk/examples/wallet/events.rs b/sdk/examples/wallet/events.rs index ceedf02433..476584829f 100644 --- a/sdk/examples/wallet/events.rs +++ b/sdk/examples/wallet/events.rs @@ -70,7 +70,7 @@ async fn main() -> Result<()> { println!("Transaction sent: {}", transaction.transaction_id); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( diff --git a/sdk/examples/wallet/ledger_nano.rs b/sdk/examples/wallet/ledger_nano.rs index 820dfbdfd5..a96c79e295 100644 --- a/sdk/examples/wallet/ledger_nano.rs +++ b/sdk/examples/wallet/ledger_nano.rs @@ -76,7 +76,7 @@ async fn main() -> Result<()> { println!("Transaction sent: {}", transaction.transaction_id); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/wallet/offline_signing/3_send_transaction.rs b/sdk/examples/wallet/offline_signing/3_send_transaction.rs index 974bfcbcd1..39478bd63d 100644 --- a/sdk/examples/wallet/offline_signing/3_send_transaction.rs +++ b/sdk/examples/wallet/offline_signing/3_send_transaction.rs @@ -71,7 +71,7 @@ async fn wait_for_inclusion(transaction_id: &TransactionId, account: &Account) - ); // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(transaction_id, None, None) + .reissue_transaction_until_included(transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/wallet/participation.rs b/sdk/examples/wallet/participation.rs index 2b19927aa6..9e63fbad8e 100644 --- a/sdk/examples/wallet/participation.rs +++ b/sdk/examples/wallet/participation.rs @@ -133,7 +133,7 @@ async fn main() -> Result<()> { println!("Waiting for `increase voting power` transaction to be included..."); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", @@ -158,7 +158,7 @@ async fn main() -> Result<()> { println!("Waiting for `decrease voting power` transaction to be included..."); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", @@ -183,7 +183,7 @@ async fn main() -> Result<()> { println!("Waiting for `vote` transaction to be included..."); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", @@ -210,7 +210,7 @@ async fn main() -> Result<()> { println!("Waiting for `stop participating` transaction to be included..."); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", @@ -234,7 +234,7 @@ async fn main() -> Result<()> { println!("Waiting for `decrease voting power` transaction to be included..."); let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/wallet/spammer.rs b/sdk/examples/wallet/spammer.rs index a83058c888..0cde91efe9 100644 --- a/sdk/examples/wallet/spammer.rs +++ b/sdk/examples/wallet/spammer.rs @@ -199,7 +199,7 @@ async fn wait_for_inclusion(transaction_id: &TransactionId, account: &Account) - ); // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(transaction_id, None, None) + .reissue_transaction_until_included(transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/wallet/split_funds.rs b/sdk/examples/wallet/split_funds.rs index 262d418426..bbabe1feb1 100644 --- a/sdk/examples/wallet/split_funds.rs +++ b/sdk/examples/wallet/split_funds.rs @@ -86,7 +86,7 @@ async fn main() -> Result<()> { // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( diff --git a/sdk/examples/wallet/update_account_output.rs b/sdk/examples/wallet/update_account_output.rs index 967c80fca0..370b492a56 100644 --- a/sdk/examples/wallet/update_account_output.rs +++ b/sdk/examples/wallet/update_account_output.rs @@ -91,7 +91,7 @@ async fn send_and_wait_for_inclusion(account: &Account, outputs: Vec) -> ); // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/examples/wallet/wallet.rs b/sdk/examples/wallet/wallet.rs index 3e4adf1c77..3c5fe3b802 100644 --- a/sdk/examples/wallet/wallet.rs +++ b/sdk/examples/wallet/wallet.rs @@ -152,7 +152,7 @@ async fn wait_for_inclusion(transaction_id: &TransactionId, account: &Account) - ); // Wait for transaction to get included let block_id = account - .retry_transaction_until_included(transaction_id, None, None) + .reissue_transaction_until_included(transaction_id, None, None) .await?; println!( "Block included: {}/block/{}", diff --git a/sdk/src/client/api/high_level.rs b/sdk/src/client/api/high_level.rs index b15d3f9988..5fb53c0ab7 100644 --- a/sdk/src/client/api/high_level.rs +++ b/sdk/src/client/api/high_level.rs @@ -8,27 +8,22 @@ use futures::{StreamExt, TryStreamExt}; use crate::{ client::{ api::input_selection::Error as InputSelectionError, - constants::{ - DEFAULT_RETRY_UNTIL_INCLUDED_INTERVAL, DEFAULT_RETRY_UNTIL_INCLUDED_MAX_AMOUNT, FIVE_MINUTES_IN_SECONDS, - }, + constants::FIVE_MINUTES_IN_SECONDS, error::{Error, Result}, node_api::indexer::query_parameters::QueryParameter, secret::SecretManage, Client, }, - types::{ - api::core::response::LedgerInclusionState, - block::{ - address::Bech32Address, - core::Block, - input::{Input, UtxoInput, INPUT_COUNT_MAX}, - output::OutputWithMetadata, - payload::{ - transaction::{TransactionEssence, TransactionId}, - Payload, - }, - BlockId, + types::block::{ + address::Bech32Address, + core::Block, + input::{Input, UtxoInput, INPUT_COUNT_MAX}, + output::OutputWithMetadata, + payload::{ + transaction::{TransactionEssence, TransactionId}, + Payload, }, + BlockId, }, utils::unix_timestamp_now, }; @@ -64,113 +59,6 @@ impl Client { futures::future::try_join_all(block_ids.iter().map(|block_id| self.get_block(block_id))).await } - /// Retries (promotes or reattaches) a block for provided block id. Block should only be - /// retried only if they are valid and haven't been confirmed for a while. - pub async fn retry( - &self, - block_id: &BlockId, - coin_type: u32, - secret_manager: &S, - ) -> Result<(BlockId, Block)> - where - crate::client::Error: From, - { - // Get the metadata to check if it needs to reattach - let block_metadata = self.get_block_metadata(block_id).await?; - if block_metadata.should_reattach.unwrap_or(false) { - self.reattach_unchecked(block_id, coin_type, secret_manager).await - } else { - Err(Error::NoNeedPromoteOrReattach(block_id.to_string())) - } - } - - /// Retries (promotes or reattaches) a block for provided block id until it's included (referenced by a - /// milestone). Default interval is 5 seconds and max attempts is 40. Returns the included block at first position - /// and additional reattached blocks - pub async fn retry_until_included( - &self, - block_id: &BlockId, - interval: Option, - max_attempts: Option, - coin_type: u32, - secret_manager: &S, - ) -> Result> - where - crate::client::Error: From, - { - log::debug!("[retry_until_included]"); - // Attachments of the Block to check inclusion state - let mut block_ids = vec![*block_id]; - // Reattached Blocks that get returned - let mut blocks_with_id = Vec::new(); - for _ in 0..max_attempts.unwrap_or(DEFAULT_RETRY_UNTIL_INCLUDED_MAX_AMOUNT) { - #[cfg(target_family = "wasm")] - gloo_timers::future::TimeoutFuture::new( - (interval.unwrap_or(DEFAULT_RETRY_UNTIL_INCLUDED_INTERVAL) * 1000) - .try_into() - .unwrap(), - ) - .await; - - #[cfg(not(target_family = "wasm"))] - tokio::time::sleep(std::time::Duration::from_secs( - interval.unwrap_or(DEFAULT_RETRY_UNTIL_INCLUDED_INTERVAL), - )) - .await; - - // Check inclusion state for each attachment - let block_ids_len = block_ids.len(); - let mut conflicting = false; - for (index, id) in block_ids.clone().iter().enumerate() { - let block_metadata = self.get_block_metadata(id).await?; - if let Some(inclusion_state) = block_metadata.ledger_inclusion_state { - match inclusion_state { - LedgerInclusionState::Included | LedgerInclusionState::NoTransaction => { - // if original block, request it so we can return it on first position - if id == block_id { - let mut included_and_reattached_blocks = - vec![(*block_id, self.get_block(block_id).await?)]; - included_and_reattached_blocks.extend(blocks_with_id); - return Ok(included_and_reattached_blocks); - } else { - // Move included block to first position - blocks_with_id.rotate_left(index); - return Ok(blocks_with_id); - } - } - // only set it as conflicting here and don't return, because another reattached block could - // have the included transaction - LedgerInclusionState::Conflicting => conflicting = true, - }; - } - // Only reattach latest attachment of the block - if index == block_ids_len - 1 && block_metadata.should_reattach.unwrap_or(false) { - // Safe to unwrap since we iterate over it - let reattached = self - .reattach_unchecked(block_ids.last().unwrap(), coin_type, secret_manager) - .await?; - block_ids.push(reattached.0); - blocks_with_id.push(reattached); - } - } - // After we checked all our reattached blocks, check if the transaction got reattached in another block - // and confirmed - if conflicting { - let block = self.get_block(block_id).await?; - if let Some(Payload::Transaction(transaction_payload)) = block.payload() { - let included_block = self.get_included_block(&transaction_payload.id()).await?; - let mut included_and_reattached_blocks = vec![( - included_block.id(&self.get_protocol_parameters().await?), - included_block, - )]; - included_and_reattached_blocks.extend(blocks_with_id); - return Ok(included_and_reattached_blocks); - } - } - } - Err(Error::TangleInclusion(block_id.to_string())) - } - /// Function to find inputs from addresses for a provided amount (useful for offline signing), ignoring outputs with /// additional unlock conditions pub async fn find_inputs(&self, addresses: Vec, amount: u64) -> Result> { @@ -232,54 +120,6 @@ impl Client { Ok(selected_inputs) } - /// Reattaches blocks for provided block id. Blocks can be reattached only if they are valid and haven't been - /// confirmed for a while. - pub async fn reattach( - &self, - block_id: &BlockId, - coin_type: u32, - secret_manager: &S, - ) -> Result<(BlockId, Block)> - where - crate::client::Error: From, - { - let metadata = self.get_block_metadata(block_id).await?; - if metadata.should_reattach.unwrap_or(false) { - self.reattach_unchecked(block_id, coin_type, secret_manager).await - } else { - Err(Error::NoNeedPromoteOrReattach(block_id.to_string())) - } - } - - /// Reattach a block without checking if it should be reattached - pub async fn reattach_unchecked( - &self, - block_id: &BlockId, - coin_type: u32, - secret_manager: &S, - ) -> Result<(BlockId, Block)> - where - crate::client::Error: From, - { - // Get the Block object by the BlockID. - let block = self.get_block(block_id).await?; - let reattach_block = self - .finish_basic_block_builder( - block.issuer_id(), - None, - None, - block.payload().cloned(), - coin_type, - secret_manager, - ) - .await?; - - // Post the modified - let block_id = self.post_block_raw(&reattach_block).await?; - - Ok((block_id, reattach_block)) - } - /// Returns the local time checked with the timestamp of the latest milestone, if the difference is larger than 5 /// minutes an error is returned to prevent locking outputs by accident for a wrong time. pub async fn get_time_checked(&self) -> Result { diff --git a/sdk/src/client/constants.rs b/sdk/src/client/constants.rs index e09b381916..53b03821a1 100644 --- a/sdk/src/client/constants.rs +++ b/sdk/src/client/constants.rs @@ -9,8 +9,6 @@ use crate::types::block::address::Hrp; /// Default timeout for all API requests pub(crate) const DEFAULT_API_TIMEOUT: Duration = Duration::from_secs(15); -pub(crate) const DEFAULT_RETRY_UNTIL_INCLUDED_INTERVAL: u64 = 1; -pub(crate) const DEFAULT_RETRY_UNTIL_INCLUDED_MAX_AMOUNT: u64 = 40; /// Interval in which the node info will be requested and healthy nodes will be added to the healthy node pool pub(crate) const NODE_SYNC_INTERVAL: Duration = Duration::from_secs(60); pub(crate) const DEFAULT_MIN_QUORUM_SIZE: usize = 3; diff --git a/sdk/src/client/error.rs b/sdk/src/client/error.rs index b18b13e599..19c5fbf5e4 100644 --- a/sdk/src/client/error.rs +++ b/sdk/src/client/error.rs @@ -84,9 +84,6 @@ pub enum Error { /// Error on API request #[error("node error: {0}")] Node(#[from] crate::client::node_api::error::Error), - /// The block doesn't need to be promoted or reattached - #[error("block ID `{0}` doesn't need to be promoted or reattached")] - NoNeedPromoteOrReattach(String), /// Requested output id not found for this type #[error("No output found for {0}")] NoOutput(String), diff --git a/sdk/src/wallet/account/operations/mod.rs b/sdk/src/wallet/account/operations/mod.rs index 0d8df27bd1..7df08edf2e 100644 --- a/sdk/src/wallet/account/operations/mod.rs +++ b/sdk/src/wallet/account/operations/mod.rs @@ -18,8 +18,8 @@ pub(crate) mod output_finder; /// The module for participation #[cfg(feature = "participation")] pub(crate) mod participation; -/// The module for retrying blocks or transactions -pub(crate) mod retry; +/// The module for reissuing blocks or transactions +pub(crate) mod reissue; /// The module for synchronization of an account pub(crate) mod syncing; /// The module for transactions diff --git a/sdk/src/wallet/account/operations/retry.rs b/sdk/src/wallet/account/operations/reissue.rs similarity index 75% rename from sdk/src/wallet/account/operations/retry.rs rename to sdk/src/wallet/account/operations/reissue.rs index c9b1e83a13..aedbfc0cc3 100644 --- a/sdk/src/wallet/account/operations/retry.rs +++ b/sdk/src/wallet/account/operations/reissue.rs @@ -6,7 +6,6 @@ use crate::{ types::{ api::core::response::LedgerInclusionState, block::{ - core::Block, payload::{transaction::TransactionId, Payload}, BlockId, }, @@ -17,44 +16,23 @@ use crate::{ }, }; -const DEFAULT_RETRY_UNTIL_INCLUDED_INTERVAL: u64 = 1; -const DEFAULT_RETRY_UNTIL_INCLUDED_MAX_AMOUNT: u64 = 40; +const DEFAULT_REISSUE_UNTIL_INCLUDED_INTERVAL: u64 = 1; +const DEFAULT_REISSUE_UNTIL_INCLUDED_MAX_AMOUNT: u64 = 40; impl Account where Error: From, crate::client::Error: From, { - /// Retries (promotes or reattaches) a block for provided block id until it's included (referenced by a - /// milestone). This function is re-exported from the client library and default interval is as defined there. - /// Returns the included block at first position and additional reattached blocks - pub async fn retry_until_included( - &self, - block_id: &BlockId, - interval: Option, - max_attempts: Option, - ) -> crate::wallet::Result> { - Ok(self - .client() - .retry_until_included( - block_id, - interval, - max_attempts, - self.wallet.coin_type(), - &*self.get_secret_manager().read().await, - ) - .await?) - } - - /// Retries (promotes or reattaches) a transaction sent from the account for a provided transaction id until it's + /// Reissues a transaction sent from the account for a provided transaction id until it's /// included (referenced by a milestone). Returns the included block id. - pub async fn retry_transaction_until_included( + pub async fn reissue_transaction_until_included( &self, transaction_id: &TransactionId, interval: Option, max_attempts: Option, ) -> crate::wallet::Result { - log::debug!("[retry_transaction_until_included]"); + log::debug!("[reissue_transaction_until_included]"); let protocol_params = self.client().get_protocol_parameters().await?; @@ -92,10 +70,12 @@ where }; // Attachments of the Block to check inclusion state + // TODO: remove when todos in `finish_basic_block_builder()` are removed + #[allow(unused_mut)] let mut block_ids = vec![block_id]; - for _ in 0..max_attempts.unwrap_or(DEFAULT_RETRY_UNTIL_INCLUDED_MAX_AMOUNT) { + for _ in 0..max_attempts.unwrap_or(DEFAULT_REISSUE_UNTIL_INCLUDED_MAX_AMOUNT) { let duration = - std::time::Duration::from_secs(interval.unwrap_or(DEFAULT_RETRY_UNTIL_INCLUDED_INTERVAL)); + std::time::Duration::from_secs(interval.unwrap_or(DEFAULT_REISSUE_UNTIL_INCLUDED_INTERVAL)); #[cfg(target_family = "wasm")] gloo_timers::future::TimeoutFuture::new(duration.as_millis() as u32).await; @@ -113,14 +93,14 @@ where LedgerInclusionState::Included | LedgerInclusionState::NoTransaction => { return Ok(*block_id_); } - // only set it as conflicting here and don't return, because another reattached block could + // only set it as conflicting here and don't return, because another reissued block could // have the included transaction LedgerInclusionState::Conflicting => conflicting = true, }; } - // Only reattach latest attachment of the block + // Only reissue latest attachment of the block if index == block_ids_len - 1 && block_metadata.should_reattach.unwrap_or(false) { - let reattached_block = self + let reissued_block = self .client() .finish_basic_block_builder( todo!("issuer id"), @@ -131,10 +111,10 @@ where &*self.get_secret_manager().read().await, ) .await?; - block_ids.push(reattached_block.id(&protocol_params)); + block_ids.push(reissued_block.id(&protocol_params)); } } - // After we checked all our reattached blocks, check if the transaction got reattached in another block + // After we checked all our reissued blocks, check if the transaction got reissued in another block // and confirmed if conflicting { let included_block = self.client().get_included_block(transaction_id).await.map_err(|e| { diff --git a/sdk/src/wallet/account/operations/syncing/mod.rs b/sdk/src/wallet/account/operations/syncing/mod.rs index b99fa3999e..8861ab240d 100644 --- a/sdk/src/wallet/account/operations/syncing/mod.rs +++ b/sdk/src/wallet/account/operations/syncing/mod.rs @@ -47,7 +47,7 @@ where self.default_sync_options.lock().await.clone() } - /// Sync the account by fetching new information from the nodes. Will also retry pending transactions + /// Sync the account by fetching new information from the nodes. Will also reissue pending transactions /// if necessary. A custom default can be set using set_default_sync_options. pub async fn sync(&self, options: Option) -> crate::wallet::Result { let options = match options { diff --git a/sdk/src/wallet/account/operations/syncing/options.rs b/sdk/src/wallet/account/operations/syncing/options.rs index 7fe3ec73b1..b1c1256069 100644 --- a/sdk/src/wallet/account/operations/syncing/options.rs +++ b/sdk/src/wallet/account/operations/syncing/options.rs @@ -37,7 +37,7 @@ pub struct SyncOptions { /// pruned. #[serde(default = "default_sync_incoming_transactions")] pub sync_incoming_transactions: bool, - /// Checks pending transactions and promotes/reattaches them if necessary. + /// Checks pending transactions and reissues them if necessary. #[serde(default = "default_sync_pending_transactions")] pub sync_pending_transactions: bool, /// Specifies what outputs should be synced for the ed25519 addresses from the account. diff --git a/sdk/src/wallet/account/operations/syncing/transactions.rs b/sdk/src/wallet/account/operations/syncing/transactions.rs index e040a5b027..9b592c3243 100644 --- a/sdk/src/wallet/account/operations/syncing/transactions.rs +++ b/sdk/src/wallet/account/operations/syncing/transactions.rs @@ -15,7 +15,7 @@ use crate::{ }; // ignore outputs and transactions from other networks -// check if outputs are unspent, rebroadcast, reattach... +// check if outputs are unspent, rebroadcast, reissue... // also revalidate that the locked outputs needs to be there, maybe there was a conflict or the transaction got // confirmed, then they should get removed @@ -24,7 +24,7 @@ where crate::wallet::Error: From, crate::client::Error: From, { - /// Sync transactions and reattach them if unconfirmed. Returns the transaction with updated metadata and spent + /// Sync transactions and reissue them if unconfirmed. Returns the transaction with updated metadata and spent /// output ids that don't need to be locked anymore /// Return true if a transaction got confirmed for which we don't have an output already, based on this outputs will /// be synced again @@ -47,7 +47,7 @@ where // Inputs from conflicting transactions that are unspent, but should be removed from the locked outputs so they // are available again let mut output_ids_to_unlock = Vec::new(); - let mut transactions_to_reattach = Vec::new(); + let mut transactions_to_reissue = Vec::new(); let protocol_params = self.client().get_protocol_parameters().await?; for transaction_id in &account_details.pending_transactions { @@ -152,7 +152,7 @@ where } } } else { - // no need to reattach if one input got spent + // no need to reissue if one input got spent if input_got_spent { process_transaction_with_unknown_state( &account_details, @@ -162,16 +162,16 @@ where )?; } else { let time_now = unix_timestamp_now().as_millis(); - // Reattach if older than 30 seconds + // Reissue if older than 30 seconds if transaction.timestamp + 30000 < time_now { - // only reattach if inputs are still unspent - transactions_to_reattach.push(transaction); + // only reissue if inputs are still unspent + transactions_to_reissue.push(transaction); } } } } Err(crate::client::Error::Node(crate::client::node_api::error::Error::NotFound(_))) => { - // no need to reattach if one input got spent + // no need to reissue if one input got spent if input_got_spent { process_transaction_with_unknown_state( &account_details, @@ -181,10 +181,10 @@ where )?; } else { let time_now = unix_timestamp_now().as_millis(); - // Reattach if older than 30 seconds + // Reissue if older than 30 seconds if transaction.timestamp + 30000 < time_now { - // only reattach if inputs are still unspent - transactions_to_reattach.push(transaction); + // only reissue if inputs are still unspent + transactions_to_reissue.push(transaction); } } } @@ -192,20 +192,20 @@ where } } else { // transaction wasn't submitted yet, so we have to send it again - // no need to reattach if one input got spent + // no need to reissue if one input got spent if input_got_spent { } else { - // only reattach if inputs are still unspent - transactions_to_reattach.push(transaction); + // only reissue if inputs are still unspent + transactions_to_reissue.push(transaction); } } } drop(account_details); - for mut transaction in transactions_to_reattach { - log::debug!("[SYNC] reattach transaction"); - let reattached_block = self.submit_transaction_payload(transaction.payload.clone()).await?; - transaction.block_id.replace(reattached_block); + for mut transaction in transactions_to_reissue { + log::debug!("[SYNC] reissue transaction"); + let reissued_block = self.submit_transaction_payload(transaction.payload.clone()).await?; + transaction.block_id.replace(reissued_block); updated_transactions.push(transaction); } diff --git a/sdk/src/wallet/account/operations/transaction/mod.rs b/sdk/src/wallet/account/operations/transaction/mod.rs index 70f642aef4..a3d620cb3c 100644 --- a/sdk/src/wallet/account/operations/transaction/mod.rs +++ b/sdk/src/wallet/account/operations/transaction/mod.rs @@ -39,7 +39,7 @@ where /// Sends a transaction by specifying its outputs. /// /// Note that, if sending a block fails, the method will return `None` for the block id, but the wallet - /// will retry sending the transaction during syncing. + /// will reissue the transaction during syncing. /// ```ignore /// let outputs = [ /// BasicOutputBuilder::new_with_amount(1_000_000)? diff --git a/sdk/tests/client/node_api/indexer.rs b/sdk/tests/client/node_api/indexer.rs index f95e6848ea..c1c221e625 100644 --- a/sdk/tests/client/node_api/indexer.rs +++ b/sdk/tests/client/node_api/indexer.rs @@ -45,8 +45,6 @@ // .finish() // .await?; -// client.retry_until_included(&block.id(), None, None).await?; - // let output_id_0 = get_alias_output_id(block.payload().unwrap())?; // let output_id_1 = client.alias_output_id(AliasId::from(&output_id_0)).await?; @@ -77,8 +75,6 @@ // .finish() // .await?; -// client.retry_until_included(&block.id(), None, None).await?; - // let output_id_0 = get_nft_output_id(block.payload().unwrap())?; // let output_id_1 = client.nft_output_id(NftId::from(&output_id_0)).await?; @@ -111,8 +107,6 @@ // .finish() // .await?; -// client.retry_until_included(&block.id(), None, None).await?; - // let alias_id = AliasId::from(&get_alias_output_id(block.payload().unwrap())?); // let alias_output_1 = AliasOutputBuilder::from(alias_output_0.as_alias()) @@ -142,8 +136,6 @@ // .finish() // .await?; -// client.retry_until_included(&block.id(), None, None).await?; - // let output_id_0 = get_foundry_output_id(block.payload().unwrap())?; // let output_id_1 = client.foundry_output_id(foundry_id).await?; diff --git a/sdk/tests/client/node_api/mod.rs b/sdk/tests/client/node_api/mod.rs index 6de5da9ca2..02a2112f45 100644 --- a/sdk/tests/client/node_api/mod.rs +++ b/sdk/tests/client/node_api/mod.rs @@ -93,11 +93,6 @@ pub async fn setup_transaction_block(client: &Client) -> (BlockId, TransactionId _ => unreachable!(), }; - let _ = client - .retry_until_included(&block_id, None, None, IOTA_COIN_TYPE, &secret_manager) - .await - .unwrap(); - (block_id, transaction_id) } diff --git a/sdk/tests/wallet/balance.rs b/sdk/tests/wallet/balance.rs index 2f260c60d3..d83949261a 100644 --- a/sdk/tests/wallet/balance.rs +++ b/sdk/tests/wallet/balance.rs @@ -126,7 +126,7 @@ async fn balance_expiration() -> Result<()> { assert_eq!(balance_after_tx.base_coin().available(), 0); account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // Account 1 balance before expiration @@ -206,7 +206,7 @@ async fn addresses_balance() -> Result<()> { assert_eq!(balance_0, balance_0_sync); account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; account_1.sync(None).await?; @@ -221,7 +221,7 @@ async fn addresses_balance() -> Result<()> { let tx = account_1.send(to_send / 2, acc_1_addr_2.address(), None).await?; account_1 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance_1_sync = account_1.sync(None).await?; @@ -259,7 +259,7 @@ async fn balance_voting_power() -> Result<()> { // Only use a part as voting power let tx = account.increase_voting_power(voting_power).await?; account - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account.sync(None).await?; assert_eq!(balance.base_coin().total(), faucet_amount); @@ -270,7 +270,7 @@ async fn balance_voting_power() -> Result<()> { // Increase voting power to total amount let tx = account.increase_voting_power(faucet_amount - voting_power).await?; account - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account.sync(None).await?; assert_eq!(balance.base_coin().total(), faucet_amount); diff --git a/sdk/tests/wallet/burn_outputs.rs b/sdk/tests/wallet/burn_outputs.rs index ceabc2732c..2d364aada0 100644 --- a/sdk/tests/wallet/burn_outputs.rs +++ b/sdk/tests/wallet/burn_outputs.rs @@ -29,7 +29,7 @@ async fn mint_and_burn_nft() -> Result<()> { let transaction = account.mint_nfts(nft_options, None).await.unwrap(); account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let balance = account.sync(None).await.unwrap(); @@ -43,7 +43,7 @@ async fn mint_and_burn_nft() -> Result<()> { let transaction = account.burn(nft_id, None).await.unwrap(); account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let balance = account.sync(None).await.unwrap(); let search = balance.nfts().iter().find(|&balance_nft_id| *balance_nft_id == nft_id); @@ -81,7 +81,7 @@ async fn mint_and_burn_expired_nft() -> Result<()> { let transaction = account_0.send_outputs(outputs, None).await?; account_0 - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let output_id = OutputId::new(transaction.transaction_id, 0u16)?; @@ -90,7 +90,7 @@ async fn mint_and_burn_expired_nft() -> Result<()> { account_1.sync(None).await?; let transaction = account_1.burn(nft_id, None).await?; account_1 - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let balance = account_1.sync(None).await?; // After burning the amount is available on account_1 @@ -113,7 +113,7 @@ async fn create_and_melt_native_token() -> Result<()> { // Wait for transaction to get included account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; account.sync(None).await?; @@ -128,7 +128,7 @@ async fn create_and_melt_native_token() -> Result<()> { let create_transaction = account.create_native_token(params, None).await.unwrap(); account - .retry_transaction_until_included(&create_transaction.transaction.transaction_id, None, None) + .reissue_transaction_until_included(&create_transaction.transaction.transaction_id, None, None) .await?; let balance = account.sync(None).await.unwrap(); @@ -147,7 +147,7 @@ async fn create_and_melt_native_token() -> Result<()> { .unwrap(); account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let balance = account.sync(None).await.unwrap(); println!("account balance -> {}", serde_json::to_string(&balance).unwrap()); @@ -165,7 +165,7 @@ async fn create_and_melt_native_token() -> Result<()> { .unwrap(); account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let balance = account.sync(None).await.unwrap(); println!("account balance -> {}", serde_json::to_string(&balance).unwrap()); @@ -193,7 +193,7 @@ async fn destroy_foundry(account: &Account) -> Result<()> { let transaction = account.burn(foundry_id, None).await.unwrap(); account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let balance = account.sync(None).await.unwrap(); let search = balance @@ -215,7 +215,7 @@ async fn destroy_account(account: &Account) -> Result<()> { println!("account_id -> {account_id}"); let transaction = account.burn(account_id, None).await.unwrap(); account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let balance = account.sync(None).await.unwrap(); let search = balance @@ -242,7 +242,7 @@ async fn create_and_burn_native_tokens() -> Result<()> { let tx = account.create_account_output(None, None).await?; account - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; account.sync(None).await?; @@ -258,7 +258,7 @@ async fn create_and_burn_native_tokens() -> Result<()> { ) .await?; account - .retry_transaction_until_included(&create_tx.transaction.transaction_id, None, None) + .reissue_transaction_until_included(&create_tx.transaction.transaction_id, None, None) .await?; account.sync(None).await?; @@ -266,7 +266,7 @@ async fn create_and_burn_native_tokens() -> Result<()> { .burn(NativeToken::new(create_tx.token_id, native_token_amount)?, None) .await?; account - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account.sync(None).await?; @@ -286,7 +286,7 @@ async fn mint_and_burn_nft_with_account() -> Result<()> { let tx = account.create_account_output(None, None).await?; account - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; account.sync(None).await?; @@ -295,7 +295,7 @@ async fn mint_and_burn_nft_with_account() -> Result<()> { .with_immutable_metadata(b"some immutable nft metadata".to_vec())]; let nft_tx = account.mint_nfts(nft_options, None).await.unwrap(); account - .retry_transaction_until_included(&nft_tx.transaction_id, None, None) + .reissue_transaction_until_included(&nft_tx.transaction_id, None, None) .await?; let output_id = OutputId::new(nft_tx.transaction_id, 0u16).unwrap(); let nft_id = NftId::from(&output_id); @@ -307,7 +307,7 @@ async fn mint_and_burn_nft_with_account() -> Result<()> { .burn(Burn::new().add_nft(nft_id).add_account(*account_id), None) .await?; account - .retry_transaction_until_included(&burn_tx.transaction_id, None, None) + .reissue_transaction_until_included(&burn_tx.transaction_id, None, None) .await?; let balance = account.sync(None).await?; diff --git a/sdk/tests/wallet/claim_outputs.rs b/sdk/tests/wallet/claim_outputs.rs index c252e531d5..723a8009c7 100644 --- a/sdk/tests/wallet/claim_outputs.rs +++ b/sdk/tests/wallet/claim_outputs.rs @@ -40,7 +40,7 @@ async fn claim_2_basic_micro_outputs() -> Result<()> { .await?; accounts[1] - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // Claim with account 0 @@ -52,7 +52,7 @@ async fn claim_2_basic_micro_outputs() -> Result<()> { .claim_outputs(accounts[0].claimable_outputs(OutputsToClaim::MicroTransactions).await?) .await?; accounts[0] - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = accounts[0].sync(None).await.unwrap(); @@ -90,7 +90,7 @@ async fn claim_1_of_2_basic_outputs() -> Result<()> { .await?; accounts[1] - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // Claim with account 0 @@ -102,7 +102,7 @@ async fn claim_1_of_2_basic_outputs() -> Result<()> { .claim_outputs(accounts[0].claimable_outputs(OutputsToClaim::Amount).await?) .await?; accounts[0] - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = accounts[0].sync(None).await.unwrap(); @@ -146,7 +146,7 @@ async fn claim_2_basic_outputs_no_outputs_in_claim_account() -> Result<()> { let tx = account_0.send_outputs(outputs, None).await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // Claim with account 1 @@ -158,7 +158,7 @@ async fn claim_2_basic_outputs_no_outputs_in_claim_account() -> Result<()> { .claim_outputs(account_1.claimable_outputs(OutputsToClaim::All).await?) .await?; account_1 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account_1.sync(None).await.unwrap(); @@ -185,7 +185,7 @@ async fn claim_2_native_tokens() -> Result<()> { let tx = accounts[1].create_account_output(None, None).await?; accounts[1] - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; accounts[1].sync(None).await?; @@ -201,7 +201,7 @@ async fn claim_2_native_tokens() -> Result<()> { ) .await?; accounts[1] - .retry_transaction_until_included(&create_tx_0.transaction.transaction_id, None, None) + .reissue_transaction_until_included(&create_tx_0.transaction.transaction_id, None, None) .await?; accounts[1].sync(None).await?; @@ -217,7 +217,7 @@ async fn claim_2_native_tokens() -> Result<()> { ) .await?; accounts[1] - .retry_transaction_until_included(&create_tx_1.transaction.transaction_id, None, None) + .reissue_transaction_until_included(&create_tx_1.transaction.transaction_id, None, None) .await?; accounts[1].sync(None).await?; @@ -237,7 +237,7 @@ async fn claim_2_native_tokens() -> Result<()> { ) .await?; accounts[1] - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // Claim with account 0 @@ -248,7 +248,7 @@ async fn claim_2_native_tokens() -> Result<()> { .claim_outputs(accounts[0].claimable_outputs(OutputsToClaim::NativeTokens).await?) .await?; accounts[0] - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = accounts[0].sync(None).await.unwrap(); @@ -285,7 +285,7 @@ async fn claim_2_native_tokens_no_outputs_in_claim_account() -> Result<()> { let tx = account_0.create_account_output(None, None).await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; account_0.sync(None).await?; @@ -301,7 +301,7 @@ async fn claim_2_native_tokens_no_outputs_in_claim_account() -> Result<()> { ) .await?; account_0 - .retry_transaction_until_included(&create_tx_0.transaction.transaction_id, None, None) + .reissue_transaction_until_included(&create_tx_0.transaction.transaction_id, None, None) .await?; account_0.sync(None).await?; @@ -317,7 +317,7 @@ async fn claim_2_native_tokens_no_outputs_in_claim_account() -> Result<()> { ) .await?; account_0 - .retry_transaction_until_included(&create_tx_1.transaction.transaction_id, None, None) + .reissue_transaction_until_included(&create_tx_1.transaction.transaction_id, None, None) .await?; account_0.sync(None).await?; @@ -352,7 +352,7 @@ async fn claim_2_native_tokens_no_outputs_in_claim_account() -> Result<()> { ) .await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // Claim with account 1 @@ -363,7 +363,7 @@ async fn claim_2_native_tokens_no_outputs_in_claim_account() -> Result<()> { .claim_outputs(account_1.claimable_outputs(OutputsToClaim::NativeTokens).await?) .await?; account_1 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account_1.sync(None).await.unwrap(); @@ -424,7 +424,7 @@ async fn claim_2_nft_outputs() -> Result<()> { let tx = accounts[1].send_outputs(outputs, None).await?; accounts[1] - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // Claim with account 0 @@ -435,7 +435,7 @@ async fn claim_2_nft_outputs() -> Result<()> { .claim_outputs(accounts[0].claimable_outputs(OutputsToClaim::Nfts).await?) .await?; accounts[0] - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = accounts[0].sync(None).await.unwrap(); @@ -485,7 +485,7 @@ async fn claim_2_nft_outputs_no_outputs_in_claim_account() -> Result<()> { let tx = account_0.send_outputs(outputs, None).await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // Claim with account 1 @@ -496,7 +496,7 @@ async fn claim_2_nft_outputs_no_outputs_in_claim_account() -> Result<()> { .claim_outputs(account_1.claimable_outputs(OutputsToClaim::Nfts).await?) .await?; account_1 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account_1.sync(None).await.unwrap(); @@ -532,7 +532,7 @@ async fn claim_basic_micro_output_error() -> Result<()> { .await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // Try claim with account 1 will fail since it has no funds to cover the storage deposit diff --git a/sdk/tests/wallet/consolidation.rs b/sdk/tests/wallet/consolidation.rs index 68ae94793c..c11fc9d92c 100644 --- a/sdk/tests/wallet/consolidation.rs +++ b/sdk/tests/wallet/consolidation.rs @@ -26,7 +26,7 @@ async fn consolidation() -> Result<()> { .await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account_1.sync(None).await.unwrap(); @@ -37,7 +37,7 @@ async fn consolidation() -> Result<()> { .consolidate_outputs(ConsolidationParams::new().with_force(true)) .await?; account_1 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account_1.sync(None).await.unwrap(); diff --git a/sdk/tests/wallet/native_tokens.rs b/sdk/tests/wallet/native_tokens.rs index 36b4faa592..263646c9cf 100644 --- a/sdk/tests/wallet/native_tokens.rs +++ b/sdk/tests/wallet/native_tokens.rs @@ -20,7 +20,7 @@ async fn create_and_mint_native_token() -> Result<()> { let tx = account.create_account_output(None, None).await?; account - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; account.sync(None).await?; @@ -36,7 +36,7 @@ async fn create_and_mint_native_token() -> Result<()> { ) .await?; account - .retry_transaction_until_included(&create_tx.transaction.transaction_id, None, None) + .reissue_transaction_until_included(&create_tx.transaction.transaction_id, None, None) .await?; let balance = account.sync(None).await?; assert_eq!(balance.native_tokens().len(), 1); @@ -52,7 +52,7 @@ async fn create_and_mint_native_token() -> Result<()> { let tx = account.mint_native_token(create_tx.token_id, 50, None).await?; account - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account.sync(None).await?; assert_eq!(balance.native_tokens().len(), 1); @@ -81,7 +81,7 @@ async fn native_token_foundry_metadata() -> Result<()> { let tx = account.create_account_output(None, None).await?; account - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; account.sync(None).await?; @@ -99,7 +99,7 @@ async fn native_token_foundry_metadata() -> Result<()> { ) .await?; account - .retry_transaction_until_included(&create_tx.transaction.transaction_id, None, None) + .reissue_transaction_until_included(&create_tx.transaction.transaction_id, None, None) .await?; // Sync native_token_foundries to get the metadata let balance = account diff --git a/sdk/tests/wallet/output_preparation.rs b/sdk/tests/wallet/output_preparation.rs index 4d91794200..4e6690da39 100644 --- a/sdk/tests/wallet/output_preparation.rs +++ b/sdk/tests/wallet/output_preparation.rs @@ -521,7 +521,7 @@ async fn prepare_nft_output_features_update() -> Result<()> { let transaction = accounts[0].mint_nfts(nft_options, None).await.unwrap(); accounts[0] - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let nft_id = *accounts[0].sync(None).await?.nfts().first().unwrap(); @@ -602,7 +602,7 @@ async fn prepare_output_remainder_dust() -> Result<()> { .await?; let transaction = account.send_outputs(vec![output], None).await?; account - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let balance = account.sync(None).await?; @@ -725,7 +725,7 @@ async fn prepare_output_only_single_nft() -> Result<()> { .mint_nfts([MintNftParams::new().try_with_address(account_1_address)?], None) .await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account_1.sync(None).await?; @@ -752,7 +752,7 @@ async fn prepare_output_only_single_nft() -> Result<()> { .await?; let tx = account_1.send_outputs([output], None).await?; account_1 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // account_0 now has the NFT diff --git a/sdk/tests/wallet/syncing.rs b/sdk/tests/wallet/syncing.rs index d499f1e016..4d3625f0c7 100644 --- a/sdk/tests/wallet/syncing.rs +++ b/sdk/tests/wallet/syncing.rs @@ -116,7 +116,7 @@ async fn sync_only_most_basic_outputs() -> Result<()> { let tx = account_0.send_outputs(outputs, None).await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // Sync with sync_only_most_basic_outputs: true, only the first output should be synced @@ -175,7 +175,7 @@ async fn sync_incoming_transactions() -> Result<()> { let tx = account_0.send_outputs(outputs, None).await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; account_1 diff --git a/sdk/tests/wallet/transactions.rs b/sdk/tests/wallet/transactions.rs index 9f9b7c81ef..b5f150f847 100644 --- a/sdk/tests/wallet/transactions.rs +++ b/sdk/tests/wallet/transactions.rs @@ -25,7 +25,7 @@ async fn send_amount() -> Result<()> { .await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account_1.sync(None).await.unwrap(); @@ -61,7 +61,7 @@ async fn send_amount_127_outputs() -> Result<()> { .await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account_1.sync(None).await.unwrap(); @@ -91,7 +91,7 @@ async fn send_amount_custom_input() -> Result<()> { .await?; account_0 - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; let balance = account_1.sync(None).await.unwrap(); @@ -131,7 +131,7 @@ async fn send_nft() -> Result<()> { let transaction = accounts[0].mint_nfts(nft_options, None).await.unwrap(); accounts[0] - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let nft_id = *accounts[0].sync(None).await?.nfts().first().unwrap(); @@ -147,7 +147,7 @@ async fn send_nft() -> Result<()> { .await .unwrap(); accounts[0] - .retry_transaction_until_included(&transaction.transaction_id, None, None) + .reissue_transaction_until_included(&transaction.transaction_id, None, None) .await?; let balance = accounts[1].sync(None).await?; @@ -213,7 +213,7 @@ async fn conflicting_transaction() -> Result<()> { ) .await?; wallet_0_account - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await?; // Second transaction will be conflicting let tx = wallet_1_account @@ -229,7 +229,7 @@ async fn conflicting_transaction() -> Result<()> { .await?; // Should return an error since the tx is conflicting match wallet_1_account - .retry_transaction_until_included(&tx.transaction_id, None, None) + .reissue_transaction_until_included(&tx.transaction_id, None, None) .await .unwrap_err() { From 4029dd550fa8cc1fa3fec188ec9f84aa85947e0d Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 14 Aug 2023 15:52:20 -0400 Subject: [PATCH 44/57] Add ext trait to help block builder signing --- bindings/core/src/method_handler/client.rs | 12 ++++--- .../client/block/00_block_no_payload.rs | 18 +++++------ .../block/01_block_confirmation_time.rs | 18 +++++------ .../client/block/02_block_custom_parents.rs | 13 +++++--- .../client/block/03_block_custom_payload.rs | 13 +++++--- .../client/block/04_block_tagged_data.rs | 13 +++++--- .../client/node_api_core/04_post_block.rs | 18 +++++------ .../client/node_api_core/05_post_block_raw.rs | 18 +++++------ sdk/src/client/api/block_builder/mod.rs | 22 ++++--------- sdk/src/client/api/high_level.rs | 1 - sdk/src/client/secret/mod.rs | 32 +++++++++++++++++++ sdk/src/wallet/account/operations/reissue.rs | 21 +++++++++--- .../transaction/submit_transaction.rs | 11 +++++-- sdk/tests/client/node_api/mod.rs | 16 +++++++--- 14 files changed, 145 insertions(+), 81 deletions(-) diff --git a/bindings/core/src/method_handler/client.rs b/bindings/core/src/method_handler/client.rs index 227c35c189..be391d3028 100644 --- a/bindings/core/src/method_handler/client.rs +++ b/bindings/core/src/method_handler/client.rs @@ -4,7 +4,11 @@ #[cfg(feature = "mqtt")] use iota_sdk::client::mqtt::{MqttPayload, Topic}; use iota_sdk::{ - client::{request_funds_from_faucet, secret::SecretManager, Client}, + client::{ + request_funds_from_faucet, + secret::{SecretManager, SignBlockExt}, + Client, + }, types::{ api::core::response::OutputWithMetadataResponse, block::{ @@ -174,14 +178,14 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM ClientMethod::PostBlockPayload { payload } => { let protocol_params = client.get_protocol_parameters().await?; let block = client - .finish_basic_block_builder::( + .unsigned_basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, Some(Payload::try_from_dto_with_params(payload, &protocol_params)?), - todo!("coin type"), - todo!("secret manager"), ) + .await? + .sign_ed25519::(todo!("secret manager"), todo!("chain")) .await?; let block_id = block.id(&protocol_params); diff --git a/sdk/examples/client/block/00_block_no_payload.rs b/sdk/examples/client/block/00_block_no_payload.rs index 6292985ff6..9acd995a2e 100644 --- a/sdk/examples/client/block/00_block_no_payload.rs +++ b/sdk/examples/client/block/00_block_no_payload.rs @@ -8,7 +8,12 @@ //! cargo run --release --example block_no_payload //! ``` -use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; +use crypto::keys::bip44::Bip44; +use iota_sdk::client::{ + constants::IOTA_COIN_TYPE, + secret::{SecretManager, SignBlockExt}, + Client, Result, +}; #[tokio::main] async fn main() -> Result<()> { @@ -26,14 +31,9 @@ async fn main() -> Result<()> { // Create and send the block. let block = client - .finish_basic_block_builder( - todo!("issuer id"), - todo!("issuing time"), - None, - None, - IOTA_COIN_TYPE, - &secret_manager, - ) + .unsigned_basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) + .await? + .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/01_block_confirmation_time.rs b/sdk/examples/client/block/01_block_confirmation_time.rs index c79f1b2574..6b5a4b6511 100644 --- a/sdk/examples/client/block/01_block_confirmation_time.rs +++ b/sdk/examples/client/block/01_block_confirmation_time.rs @@ -8,7 +8,12 @@ //! cargo run --release --example block_confirmation_time //! ``` -use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; +use crypto::keys::bip44::Bip44; +use iota_sdk::client::{ + constants::IOTA_COIN_TYPE, + secret::{SecretManager, SignBlockExt}, + Client, Result, +}; #[tokio::main] async fn main() -> Result<()> { @@ -26,14 +31,9 @@ async fn main() -> Result<()> { // Create and send a block. let block = client - .finish_basic_block_builder( - todo!("issuer id"), - todo!("issuing time"), - None, - None, - IOTA_COIN_TYPE, - &secret_manager, - ) + .unsigned_basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) + .await? + .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; let block_id = block.id(&protocol_parameters); diff --git a/sdk/examples/client/block/02_block_custom_parents.rs b/sdk/examples/client/block/02_block_custom_parents.rs index 674c994509..224d36f7e7 100644 --- a/sdk/examples/client/block/02_block_custom_parents.rs +++ b/sdk/examples/client/block/02_block_custom_parents.rs @@ -8,8 +8,13 @@ //! cargo run --release --example block_custom_parents //! ``` +use crypto::keys::bip44::Bip44; use iota_sdk::{ - client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}, + client::{ + constants::IOTA_COIN_TYPE, + secret::{SecretManager, SignBlockExt}, + Client, Result, + }, types::block::parent::StrongParents, }; @@ -33,14 +38,14 @@ async fn main() -> Result<()> { // Create and send the block with custom parents. let block = client - .finish_basic_block_builder( + .unsigned_basic_block_builder( todo!("issuer id"), todo!("issuing time"), Some(StrongParents::from_vec(tips)?), None, - IOTA_COIN_TYPE, - &secret_manager, ) + .await? + .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/03_block_custom_payload.rs b/sdk/examples/client/block/03_block_custom_payload.rs index d00ccf5309..3a90bf4592 100644 --- a/sdk/examples/client/block/03_block_custom_payload.rs +++ b/sdk/examples/client/block/03_block_custom_payload.rs @@ -8,8 +8,13 @@ //! cargo run --release --example block_custom_payload //! ``` +use crypto::keys::bip44::Bip44; use iota_sdk::{ - client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}, + client::{ + constants::IOTA_COIN_TYPE, + secret::{SecretManager, SignBlockExt}, + Client, Result, + }, types::block::payload::{Payload, TaggedDataPayload}, }; @@ -32,14 +37,14 @@ async fn main() -> Result<()> { // Create and send the block with the custom payload. let block = client - .finish_basic_block_builder( + .unsigned_basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, Some(Payload::from(tagged_data_payload)), - IOTA_COIN_TYPE, - &secret_manager, ) + .await? + .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/04_block_tagged_data.rs b/sdk/examples/client/block/04_block_tagged_data.rs index c670d1d670..f68ab55eba 100644 --- a/sdk/examples/client/block/04_block_tagged_data.rs +++ b/sdk/examples/client/block/04_block_tagged_data.rs @@ -8,8 +8,13 @@ //! cargo run --release --example block_tagged_data [TAG] [DATA] //! ``` +use crypto::keys::bip44::Bip44; use iota_sdk::{ - client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}, + client::{ + constants::IOTA_COIN_TYPE, + secret::{SecretManager, SignBlockExt}, + Client, Result, + }, types::block::payload::{Payload, TaggedDataPayload}, }; @@ -29,7 +34,7 @@ async fn main() -> Result<()> { // Create and send the block with tag and data. let block = client - .finish_basic_block_builder( + .unsigned_basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, @@ -46,9 +51,9 @@ async fn main() -> Result<()> { ) .unwrap(), ))), - IOTA_COIN_TYPE, - &secret_manager, ) + .await? + .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; println!("{block:#?}\n"); diff --git a/sdk/examples/client/node_api_core/04_post_block.rs b/sdk/examples/client/node_api_core/04_post_block.rs index b2ecb1d16d..1ab0f5de34 100644 --- a/sdk/examples/client/node_api_core/04_post_block.rs +++ b/sdk/examples/client/node_api_core/04_post_block.rs @@ -8,7 +8,12 @@ //! cargo run --release --example node_api_core_post_block [NODE URL] //! ``` -use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; +use crypto::keys::bip44::Bip44; +use iota_sdk::client::{ + constants::IOTA_COIN_TYPE, + secret::{SecretManager, SignBlockExt}, + Client, Result, +}; #[tokio::main] async fn main() -> Result<()> { @@ -27,14 +32,9 @@ async fn main() -> Result<()> { // Create the block. let block = client - .finish_basic_block_builder( - todo!("issuer id"), - todo!("issuing time"), - None, - None, - IOTA_COIN_TYPE, - &secret_manager, - ) + .unsigned_basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) + .await? + .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; // Post the block. let block_id = client.post_block(&block).await?; diff --git a/sdk/examples/client/node_api_core/05_post_block_raw.rs b/sdk/examples/client/node_api_core/05_post_block_raw.rs index b7a556c7e5..b76fc082c9 100644 --- a/sdk/examples/client/node_api_core/05_post_block_raw.rs +++ b/sdk/examples/client/node_api_core/05_post_block_raw.rs @@ -8,7 +8,12 @@ //! cargo run --release --example node_api_core_post_block_raw [NODE URL] //! ``` -use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; +use crypto::keys::bip44::Bip44; +use iota_sdk::client::{ + constants::IOTA_COIN_TYPE, + secret::{SecretManager, SignBlockExt}, + Client, Result, +}; #[tokio::main] async fn main() -> Result<()> { @@ -27,14 +32,9 @@ async fn main() -> Result<()> { // Create the block. let block = client - .finish_basic_block_builder( - todo!("issuer id"), - todo!("issuing time"), - None, - None, - IOTA_COIN_TYPE, - &secret_manager, - ) + .unsigned_basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) + .await? + .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; // Post the block as raw bytes. let block_id = client.post_block_raw(&block).await?; diff --git a/sdk/src/client/api/block_builder/mod.rs b/sdk/src/client/api/block_builder/mod.rs index 9b3d26ed0b..3cbe81a349 100644 --- a/sdk/src/client/api/block_builder/mod.rs +++ b/sdk/src/client/api/block_builder/mod.rs @@ -4,27 +4,22 @@ pub mod input_selection; pub mod transaction; -use crypto::keys::bip44::Bip44; - pub use self::transaction::verify_semantic; use crate::{ - client::{secret::SecretManage, ClientInner, Result}, - types::block::{core::Block, parent::StrongParents, payload::Payload, IssuerId}, + client::{ClientInner, Result}, + types::block::{ + basic::BasicBlockData, core::Block, parent::StrongParents, payload::Payload, BlockBuilder, IssuerId, + }, }; impl ClientInner { - pub async fn finish_basic_block_builder( + pub async fn unsigned_basic_block_builder( &self, issuer_id: IssuerId, issuing_time: Option, strong_parents: Option, payload: Option, - coin_type: u32, - secret_manager: &S, - ) -> Result - where - crate::client::Error: From, - { + ) -> Result> { // Use tips as strong parents if none are provided. let strong_parents = match strong_parents { Some(strong_parents) => strong_parents, @@ -57,10 +52,7 @@ impl ClientInner { strong_parents, ) .with_payload(payload); - let signature = secret_manager - .sign_ed25519(&builder.signing_input(), Bip44::new(coin_type)) - .await?; - Ok(builder.finish(signature)?) + Ok(builder) } } diff --git a/sdk/src/client/api/high_level.rs b/sdk/src/client/api/high_level.rs index 5fb53c0ab7..8fbe24a0b2 100644 --- a/sdk/src/client/api/high_level.rs +++ b/sdk/src/client/api/high_level.rs @@ -11,7 +11,6 @@ use crate::{ constants::FIVE_MINUTES_IN_SECONDS, error::{Error, Result}, node_api::indexer::query_parameters::QueryParameter, - secret::SecretManage, Client, }, types::block::{ diff --git a/sdk/src/client/secret/mod.rs b/sdk/src/client/secret/mod.rs index 1690f4e2fc..bcc29e8d4a 100644 --- a/sdk/src/client/secret/mod.rs +++ b/sdk/src/client/secret/mod.rs @@ -46,11 +46,14 @@ use crate::{ }, types::block::{ address::{Address, Ed25519Address}, + basic::BasicBlockData, output::Output, payload::{transaction::TransactionEssence, TransactionPayload}, semantic::ConflictReason, signature::{Ed25519Signature, Signature}, unlock::{AccountUnlock, NftUnlock, ReferenceUnlock, SignatureUnlock, Unlock, Unlocks}, + validation::ValidationBlockData, + Block, BlockBuilder, }, utils::unix_timestamp_now, }; @@ -525,3 +528,32 @@ where Ok(tx_payload) } + +#[async_trait] +pub trait SignBlockExt { + async fn sign_ed25519(self, secret_manager: &S, chain: Bip44) -> crate::client::Result + where + crate::client::Error: From; +} + +#[async_trait] +impl SignBlockExt for BlockBuilder { + async fn sign_ed25519(self, secret_manager: &S, chain: Bip44) -> crate::client::Result + where + crate::client::Error: From, + { + let msg = self.signing_input(); + Ok(self.finish(secret_manager.sign_ed25519(&msg, chain).await?)?) + } +} + +#[async_trait] +impl SignBlockExt for BlockBuilder { + async fn sign_ed25519(self, secret_manager: &S, chain: Bip44) -> crate::client::Result + where + crate::client::Error: From, + { + let msg = self.signing_input(); + Ok(self.finish(secret_manager.sign_ed25519(&msg, chain).await?)?) + } +} diff --git a/sdk/src/wallet/account/operations/reissue.rs b/sdk/src/wallet/account/operations/reissue.rs index aedbfc0cc3..73a32ca457 100644 --- a/sdk/src/wallet/account/operations/reissue.rs +++ b/sdk/src/wallet/account/operations/reissue.rs @@ -1,8 +1,13 @@ // Copyright 2022 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use crypto::keys::bip44::Bip44; + use crate::{ - client::{secret::SecretManage, Error as ClientError}, + client::{ + secret::{SecretManage, SignBlockExt}, + Error as ClientError, + }, types::{ api::core::response::LedgerInclusionState, block::{ @@ -57,13 +62,16 @@ where Some(block_id) => block_id, None => self .client() - .finish_basic_block_builder( + .unsigned_basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, Some(Payload::Transaction(Box::new(transaction.payload.clone()))), - self.wallet.coin_type(), + ) + .await? + .sign_ed25519( &*self.get_secret_manager().read().await, + Bip44::new(self.wallet.coin_type()), ) .await? .id(&protocol_params), @@ -102,13 +110,16 @@ where if index == block_ids_len - 1 && block_metadata.should_reattach.unwrap_or(false) { let reissued_block = self .client() - .finish_basic_block_builder( + .unsigned_basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, Some(Payload::Transaction(Box::new(transaction.payload.clone()))), - self.wallet.coin_type(), + ) + .await? + .sign_ed25519( &*self.get_secret_manager().read().await, + Bip44::new(self.wallet.coin_type()), ) .await?; block_ids.push(reissued_block.id(&protocol_params)); diff --git a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs index 3b226290b5..59b665e80c 100644 --- a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs +++ b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs @@ -1,10 +1,12 @@ // Copyright 2021 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use crypto::keys::bip44::Bip44; + #[cfg(feature = "events")] use crate::wallet::events::types::{TransactionProgressEvent, WalletEvent}; use crate::{ - client::secret::SecretManage, + client::secret::{SecretManage, SignBlockExt}, types::block::{payload::Payload, BlockId}, wallet::account::{operations::transaction::TransactionPayload, Account}, }; @@ -25,13 +27,16 @@ where let block = self .client() - .finish_basic_block_builder( + .unsigned_basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, Some(Payload::from(transaction_payload)), - self.wallet.coin_type(), + ) + .await? + .sign_ed25519( &*self.get_secret_manager().read().await, + Bip44::new(self.wallet.coin_type()), ) .await?; diff --git a/sdk/tests/client/node_api/mod.rs b/sdk/tests/client/node_api/mod.rs index 02a2112f45..335094abf0 100644 --- a/sdk/tests/client/node_api/mod.rs +++ b/sdk/tests/client/node_api/mod.rs @@ -6,10 +6,15 @@ mod indexer; #[cfg(feature = "mqtt")] mod mqtt; +use crypto::keys::bip44::Bip44; use iota_sdk::{ client::{ - api::GetAddressesOptions, constants::IOTA_COIN_TYPE, node_api::indexer::query_parameters::QueryParameter, - request_funds_from_faucet, secret::SecretManager, Client, + api::GetAddressesOptions, + constants::IOTA_COIN_TYPE, + node_api::indexer::query_parameters::QueryParameter, + request_funds_from_faucet, + secret::{SecretManager, SignBlockExt}, + Client, }, types::block::{ payload::{tagged_data::TaggedDataPayload, transaction::TransactionId, Payload}, @@ -29,18 +34,19 @@ async fn setup_tagged_data_block(secret_manager: &SecretManager) -> BlockId { let protocol_parameters = client.get_protocol_parameters().await.unwrap(); client - .finish_basic_block_builder( + .unsigned_basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, Some(Payload::TaggedData(Box::new( TaggedDataPayload::new(b"Hello".to_vec(), b"Tangle".to_vec()).unwrap(), ))), - IOTA_COIN_TYPE, - secret_manager, ) .await .unwrap() + .sign_ed25519(secret_manager, Bip44::new(IOTA_COIN_TYPE)) + .await + .unwrap() .id(&protocol_parameters) } From 19002f732f48850638ad0bf0ba7db43e85b42dd6 Mon Sep 17 00:00:00 2001 From: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Date: Tue, 15 Aug 2023 09:38:30 +0200 Subject: [PATCH 45/57] Update sdk/src/types/block/core.rs --- sdk/src/types/block/core.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 33d52ce435..ac36bcb7fe 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -555,11 +555,10 @@ impl Block { } pub(crate) fn block_hash(&self) -> [u8; 32] { - let bytes = match self { + match self { Self::Basic(b) => b.block_hash(), Self::Validation(b) => b.block_hash(), - }; - Blake2b256::digest(bytes).into() + } } pub(crate) fn signature_bytes(&self) -> [u8; Self::SIGNATURE_LENGTH] { From 4510bbe4c57fe05ce61294852b78a292b976f806 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 28 Aug 2023 11:59:22 -0400 Subject: [PATCH 46/57] Fix merge breakage and clippy --- sdk/src/client/builder.rs | 2 +- sdk/src/types/block/core.rs | 2 +- sdk/src/types/block/slot/epoch.rs | 2 +- sdk/src/types/block/slot/index.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/src/client/builder.rs b/sdk/src/client/builder.rs index 5a7407e629..5643d7a865 100644 --- a/sdk/src/client/builder.rs +++ b/sdk/src/client/builder.rs @@ -275,7 +275,7 @@ impl NetworkInfo { } pub fn with_tangle_time(mut self, tangle_time: u64) -> Self { - self.tangle_time = Some(tangle_time.into()); + self.tangle_time = Some(tangle_time); self } } diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index d427257b05..cb3e1385c5 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -106,7 +106,7 @@ where impl BlockBuilder { pub(crate) fn pack_header(&self, packer: &mut P) -> Result<(), P::Error> { - self.protocol_params.protocol_version().pack(packer)?; + self.protocol_params.version().pack(packer)?; self.protocol_params.network_id().pack(packer)?; self.issuing_time.pack(packer)?; self.slot_commitment_id.pack(packer)?; diff --git a/sdk/src/types/block/slot/epoch.rs b/sdk/src/types/block/slot/epoch.rs index 47857c394f..5a2b2e7a0f 100644 --- a/sdk/src/types/block/slot/epoch.rs +++ b/sdk/src/types/block/slot/epoch.rs @@ -46,7 +46,7 @@ impl EpochIndex { /// Gets the epoch index given a [`SlotIndex`]. pub fn from_slot_index( slot_index: SlotIndex, - slots_per_epoch_exponent_iter: impl Iterator, + slots_per_epoch_exponent_iter: impl Iterator, ) -> Result { let mut slot_index = *slot_index; let mut res = 0; diff --git a/sdk/src/types/block/slot/index.rs b/sdk/src/types/block/slot/index.rs index 7eba8d7d65..bfdbbbe699 100644 --- a/sdk/src/types/block/slot/index.rs +++ b/sdk/src/types/block/slot/index.rs @@ -43,7 +43,7 @@ impl SlotIndex { } /// Gets the slot index of a unix timestamp. - pub fn from_timestamp(timestamp: u64, genesis_unix_timestamp: u32, slot_duration_in_seconds: u8) -> SlotIndex { + pub fn from_timestamp(timestamp: u64, genesis_unix_timestamp: u32, slot_duration_in_seconds: u8) -> Self { (1 + (timestamp - genesis_unix_timestamp as u64) / slot_duration_in_seconds as u64).into() } From 0ba8d2ff488d6284da30591103eefa1c86b1a3de Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Thu, 14 Sep 2023 13:53:56 -0400 Subject: [PATCH 47/57] fix nostd --- sdk/src/types/block/core/basic.rs | 2 ++ sdk/src/types/block/core/validation.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sdk/src/types/block/core/basic.rs b/sdk/src/types/block/core/basic.rs index 4e7347e2f5..00ce8c990c 100644 --- a/sdk/src/types/block/core/basic.rs +++ b/sdk/src/types/block/core/basic.rs @@ -1,6 +1,8 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use alloc::vec::Vec; + use crypto::hashes::{blake2b::Blake2b256, Digest}; use packable::{ error::{UnpackError, UnpackErrorExt}, diff --git a/sdk/src/types/block/core/validation.rs b/sdk/src/types/block/core/validation.rs index f40c99aae9..4a7e621044 100644 --- a/sdk/src/types/block/core/validation.rs +++ b/sdk/src/types/block/core/validation.rs @@ -1,6 +1,8 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use alloc::vec::Vec; + use crypto::hashes::{blake2b::Blake2b256, Digest}; use packable::{ error::{UnpackError, UnpackErrorExt}, From 387cf082266fb29159b7b76ff79e066c342814c8 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Thu, 14 Sep 2023 14:22:57 -0400 Subject: [PATCH 48/57] fix tests --- sdk/src/types/block/core/wrapper.rs | 3 ++- sdk/src/types/block/rand/block.rs | 12 ++---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index 546be59606..770a6f7d92 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -96,7 +96,8 @@ impl BlockBuilder { pub(crate) fn pack_header(&self, packer: &mut P) -> Result<(), P::Error> { self.protocol_parameters.version().pack(packer)?; self.protocol_parameters.network_id().pack(packer)?; - self.issuing_time.pack(packer)?; + // TODO: what do here + self.issuing_time.expect("issuing time not set").pack(packer)?; self.slot_commitment_id.pack(packer)?; self.latest_finalized_slot.pack(packer)?; self.issuer_id.pack(packer)?; diff --git a/sdk/src/types/block/rand/block.rs b/sdk/src/types/block/rand/block.rs index 9d21fd70dc..0284a1ab06 100644 --- a/sdk/src/types/block/rand/block.rs +++ b/sdk/src/types/block/rand/block.rs @@ -36,16 +36,7 @@ pub fn rand_basic_block_with_strong_parents( protocol_params: ProtocolParameters, strong_parents: StrongParents, ) -> BlockWrapper { - BlockWrapper::build_basic( - protocol_params, - rand_slot_commitment_id(), - rand_slot_index(), - rand_issuer_id(), - strong_parents, - rand_number(), - ) - .with_payload(rand_payload_for_block()) - .sign_random() + rand_basic_block_builder_with_strong_parents(protocol_params, strong_parents).sign_random() } /// Generates a random basic block builder with given strong parents. @@ -61,6 +52,7 @@ pub fn rand_basic_block_builder_with_strong_parents( strong_parents, rand_number(), ) + .with_issuing_time(rand_number::()) .with_payload(rand_payload_for_block()) } From ab366b75b2a935a5601cf288ba021d65b85b564c Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Tue, 3 Oct 2023 17:14:08 -0400 Subject: [PATCH 49/57] remove generics --- sdk/src/client/api/block_builder/mod.rs | 20 +++---- sdk/src/client/secret/mod.rs | 19 +----- sdk/src/types/block/core/basic.rs | 80 ------------------------- sdk/src/types/block/core/mod.rs | 2 +- sdk/src/types/block/core/validation.rs | 80 ------------------------- sdk/src/types/block/core/wrapper.rs | 69 ++++++++++----------- sdk/src/types/block/rand/block.rs | 46 ++++++++------ sdk/tests/types/block.rs | 8 ++- 8 files changed, 80 insertions(+), 244 deletions(-) diff --git a/sdk/src/client/api/block_builder/mod.rs b/sdk/src/client/api/block_builder/mod.rs index 2c3f60eebd..19a0496601 100644 --- a/sdk/src/client/api/block_builder/mod.rs +++ b/sdk/src/client/api/block_builder/mod.rs @@ -8,9 +8,9 @@ pub use self::transaction::verify_semantic; use crate::{ client::{ClientInner, Result}, types::block::{ - core::{basic, BasicBlockBuilder, BlockBuilder, BlockWrapper}, + core::{basic, BlockWrapper, BlockWrapperBuilder}, payload::Payload, - IssuerId, + Block, IssuerId, }, }; @@ -21,7 +21,7 @@ impl ClientInner { issuing_time: Option, strong_parents: Option, payload: Option, - ) -> Result> { + ) -> Result { let issuance = self.get_issuance().await?; let strong_parents = strong_parents.unwrap_or(issuance.strong_parents()?); @@ -40,18 +40,18 @@ impl ClientInner { let protocol_params = self.get_protocol_parameters().await?; - Ok(BlockWrapper::build_basic( + Ok(BlockWrapper::build( protocol_params.version(), protocol_params.network_id(), issuance.commitment.id(), issuance.latest_finalized_slot, issuer_id, - strong_parents, - 0, // TODO: burned mana calculation + Block::build_basic(strong_parents, 0) // TODO: burned mana calculation + .with_weak_parents(issuance.weak_parents()?) + .with_shallow_like_parents(issuance.shallow_like_parents()?) + .with_payload(payload) + .finish_block()?, ) - .with_issuing_time(issuing_time) - .with_weak_parents(issuance.weak_parents()?) - .with_shallow_like_parents(issuance.shallow_like_parents()?) - .with_payload(payload)) + .with_issuing_time(issuing_time)) } } diff --git a/sdk/src/client/secret/mod.rs b/sdk/src/client/secret/mod.rs index 6b1b18baf8..a995400f36 100644 --- a/sdk/src/client/secret/mod.rs +++ b/sdk/src/client/secret/mod.rs @@ -53,7 +53,7 @@ use crate::{ }, types::block::{ address::{Address, Ed25519Address}, - core::{BasicBlockBuilder, BlockBuilder, ValidationBlockBuilder}, + core::BlockWrapperBuilder, output::Output, payload::{transaction::TransactionEssence, TransactionPayload}, signature::{Ed25519Signature, Signature}, @@ -617,22 +617,7 @@ pub trait SignBlockExt { } #[async_trait] -impl SignBlockExt for BlockBuilder { - async fn sign_ed25519( - self, - secret_manager: &S, - chain: Bip44, - ) -> crate::client::Result - where - crate::client::Error: From, - { - let msg = self.signing_input(); - Ok(self.finish(secret_manager.sign_ed25519(&msg, chain).await?)?) - } -} - -#[async_trait] -impl SignBlockExt for BlockBuilder { +impl SignBlockExt for BlockWrapperBuilder { async fn sign_ed25519( self, secret_manager: &S, diff --git a/sdk/src/types/block/core/basic.rs b/sdk/src/types/block/core/basic.rs index b0c7e1501f..5535c70075 100644 --- a/sdk/src/types/block/core/basic.rs +++ b/sdk/src/types/block/core/basic.rs @@ -1,9 +1,6 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use alloc::vec::Vec; - -use crypto::hashes::{blake2b::Blake2b256, Digest}; use packable::{ error::{UnpackError, UnpackErrorExt}, packer::Packer, @@ -11,12 +8,10 @@ use packable::{ Packable, }; -use super::{BlockBuilder, BlockWrapper}; use crate::types::block::{ core::{parent::verify_parents_sets, Block, Parents}, payload::{OptionalPayload, Payload}, protocol::ProtocolParameters, - signature::Ed25519Signature, Error, }; @@ -81,24 +76,6 @@ impl BasicBlockBuilder { self } - // TODO: It's bothersome that this is duplicated code - pub(crate) fn pack_block(&self, packer: &mut P) -> Result<(), P::Error> { - BasicBlock::KIND.pack(packer)?; - self.strong_parents.pack(packer)?; - self.weak_parents.pack(packer)?; - self.shallow_like_parents.pack(packer)?; - self.payload.pack(packer)?; - self.max_burned_mana.pack(packer)?; - - Ok(()) - } - - pub(crate) fn hash(&self) -> [u8; 32] { - let mut bytes = Vec::new(); - self.pack_block(&mut bytes).unwrap(); - Blake2b256::digest(bytes).into() - } - /// Finishes the builder into a [`BasicBlock`]. pub fn finish(self) -> Result { verify_parents_sets(&self.strong_parents, &self.weak_parents, &self.shallow_like_parents)?; @@ -118,63 +95,6 @@ impl BasicBlockBuilder { } } -impl BlockBuilder { - /// Adds strong parents to a [`BasicBlockBuilder`]. - #[inline(always)] - pub fn with_strong_parents(mut self, strong_parents: impl Into) -> Self { - self.block = self.block.with_strong_parents(strong_parents); - self - } - - /// Adds weak parents to a [`BasicBlockBuilder`]. - #[inline(always)] - pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { - self.block = self.block.with_weak_parents(weak_parents); - self - } - - /// Adds shallow like parents to a [`BasicBlockBuilder`]. - #[inline(always)] - pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { - self.block = self.block.with_shallow_like_parents(shallow_like_parents); - self - } - - /// Adds a payload to a [`BasicBlockBuilder`]. - #[inline(always)] - pub fn with_payload(mut self, payload: impl Into) -> Self { - self.block = self.block.with_payload(payload); - self - } - - /// Adds max burned mana to a [`BasicBlockBuilder`]. - #[inline(always)] - pub fn with_max_burned_mana(mut self, max_burned_mana: u64) -> Self { - self.block = self.block.with_max_burned_mana(max_burned_mana); - self - } - - /// Get the signing input that can be used to generate an - /// [`Ed25519Signature`](crate::types::block::signature::Ed25519Signature) for the resulting block. - pub fn signing_input(&self) -> Vec { - [self.header_hash(), self.block.hash()].concat() - } - - pub fn finish(self, signature: Ed25519Signature) -> Result { - Ok(BlockWrapper::new( - self.protocol_version, - self.network_id, - // TODO provide a sensible default - self.issuing_time.ok_or(Error::InvalidField("issuing time"))?, - self.slot_commitment_id, - self.latest_finalized_slot, - self.issuer_id, - self.block.finish_block()?, - signature, - )) - } -} - impl From for BasicBlockBuilder { fn from(value: BasicBlock) -> Self { Self { diff --git a/sdk/src/types/block/core/mod.rs b/sdk/src/types/block/core/mod.rs index 5f1e2e72fe..bd3c3fcd38 100644 --- a/sdk/src/types/block/core/mod.rs +++ b/sdk/src/types/block/core/mod.rs @@ -21,7 +21,7 @@ pub use self::{ basic::{BasicBlock, BasicBlockBuilder}, parent::Parents, validation::{ValidationBlock, ValidationBlockBuilder}, - wrapper::{BlockBuilder, BlockHeader, BlockWrapper}, + wrapper::{BlockHeader, BlockWrapper, BlockWrapperBuilder}, }; use crate::types::block::{ protocol::{ProtocolParameters, ProtocolParametersHash}, diff --git a/sdk/src/types/block/core/validation.rs b/sdk/src/types/block/core/validation.rs index 4dc8683cc1..f93970c41b 100644 --- a/sdk/src/types/block/core/validation.rs +++ b/sdk/src/types/block/core/validation.rs @@ -1,9 +1,6 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use alloc::vec::Vec; - -use crypto::hashes::{blake2b::Blake2b256, Digest}; use packable::{ error::{UnpackError, UnpackErrorExt}, packer::Packer, @@ -11,11 +8,9 @@ use packable::{ Packable, }; -use super::{BlockBuilder, BlockWrapper}; use crate::types::block::{ core::{parent::verify_parents_sets, Block, Parents}, protocol::{ProtocolParameters, ProtocolParametersHash}, - signature::Ed25519Signature, Error, }; @@ -84,24 +79,6 @@ impl ValidationBlockBuilder { self } - // TODO: It's bothersome that this is duplicated code - pub(crate) fn pack_block(&self, packer: &mut P) -> Result<(), P::Error> { - ValidationBlock::KIND.pack(packer)?; - self.strong_parents.pack(packer)?; - self.weak_parents.pack(packer)?; - self.shallow_like_parents.pack(packer)?; - self.highest_supported_version.pack(packer)?; - self.protocol_parameters_hash.pack(packer)?; - - Ok(()) - } - - pub(crate) fn hash(&self) -> [u8; 32] { - let mut bytes = Vec::new(); - self.pack_block(&mut bytes).unwrap(); - Blake2b256::digest(bytes).into() - } - /// Finishes the builder into a [`ValidationBlock`]. pub fn finish(self) -> Result { verify_parents_sets(&self.strong_parents, &self.weak_parents, &self.shallow_like_parents)?; @@ -121,63 +98,6 @@ impl ValidationBlockBuilder { } } -impl BlockBuilder { - /// Adds strong parents to a [`ValidationBlockBuilder`]. - #[inline(always)] - pub fn with_strong_parents(mut self, strong_parents: impl Into) -> Self { - self.block = self.block.with_strong_parents(strong_parents); - self - } - - /// Adds weak parents to a [`ValidationBlockBuilder`]. - #[inline(always)] - pub fn with_weak_parents(mut self, weak_parents: impl Into) -> Self { - self.block = self.block.with_weak_parents(weak_parents); - self - } - - /// Adds shallow like parents to a [`ValidationBlockBuilder`]. - #[inline(always)] - pub fn with_shallow_like_parents(mut self, shallow_like_parents: impl Into) -> Self { - self.block = self.block.with_shallow_like_parents(shallow_like_parents); - self - } - - /// Adds a highest supported version to a [`ValidationBlockBuilder`]. - #[inline(always)] - pub fn with_highest_supported_version(mut self, highest_supported_version: u8) -> Self { - self.block = self.block.with_highest_supported_version(highest_supported_version); - self - } - - /// Adds a protocol parameter hash to a [`ValidationBlockBuilder`]. - #[inline(always)] - pub fn with_protocol_parameters_hash(mut self, protocol_parameters_hash: ProtocolParametersHash) -> Self { - self.block = self.block.with_protocol_parameters_hash(protocol_parameters_hash); - self - } - - /// Get the signing input that can be used to generate an - /// [`Ed25519Signature`](crate::types::block::signature::Ed25519Signature) for the resulting block. - pub fn signing_input(&self) -> Vec { - [self.header_hash(), self.block.hash()].concat() - } - - pub fn finish(self, signature: Ed25519Signature) -> Result { - Ok(BlockWrapper::new( - self.protocol_version, - self.network_id, - // TODO provide a sensible default - self.issuing_time.ok_or(Error::InvalidField("issuing time"))?, - self.slot_commitment_id, - self.latest_finalized_slot, - self.issuer_id, - self.block.finish_block()?, - signature, - )) - } -} - impl From for ValidationBlockBuilder { fn from(value: ValidationBlock) -> Self { Self { diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index b6f46ae0ce..d874853c34 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -12,19 +12,18 @@ use packable::{ Packable, PackableExt, }; -use super::{BasicBlockBuilder, ValidationBlockBuilder}; use crate::types::block::{ block_id::{BlockHash, BlockId}, - core::{basic, validation, BasicBlock, ValidationBlock}, + core::{BasicBlock, ValidationBlock}, protocol::ProtocolParameters, - signature::Signature, + signature::{Ed25519Signature, Signature}, slot::{SlotCommitmentId, SlotIndex}, Block, Error, IssuerId, }; /// Represent the object that nodes gossip around the network. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct BlockBuilder { +pub struct BlockWrapperBuilder { /// Protocol version of the network to which this block belongs. pub(crate) protocol_version: u8, /// The identifier of the network to which this block belongs. @@ -38,17 +37,17 @@ pub struct BlockBuilder { /// The identifier of the account that issued this block. pub(crate) issuer_id: IssuerId, /// The inner block. - pub(crate) block: B, + pub(crate) block: Block, } -impl BlockBuilder { +impl BlockWrapperBuilder { pub fn new( protocol_version: u8, network_id: u64, slot_commitment_id: SlotCommitmentId, latest_finalized_slot: SlotIndex, issuer_id: IssuerId, - block: B, + block: Block, ) -> Self { Self { protocol_version, @@ -105,7 +104,7 @@ impl BlockBuilder { /// Updates the block. #[inline(always)] - pub fn with_block(mut self, block: impl Into) -> Self { + pub fn with_block(mut self, block: impl Into) -> Self { self.block = block.into(); self } @@ -125,6 +124,26 @@ impl BlockBuilder { .unwrap(); Blake2b256::digest(bytes).into() } + + /// Get the signing input that can be used to generate an + /// [`Ed25519Signature`](crate::types::block::signature::Ed25519Signature) for the resulting block. + pub fn signing_input(&self) -> Vec { + [self.header_hash(), self.block.hash()].concat() + } + + pub fn finish(self, signature: Ed25519Signature) -> Result { + Ok(BlockWrapper::new( + self.protocol_version, + self.network_id, + // TODO provide a sensible default + self.issuing_time.ok_or(Error::InvalidField("issuing time"))?, + self.slot_commitment_id, + self.latest_finalized_slot, + self.issuer_id, + self.block, + signature, + )) + } } #[derive(Clone, Debug, Eq, PartialEq, CopyGetters)] @@ -262,45 +281,23 @@ impl BlockWrapper { } } - /// Creates a new basic [`BlockBuilder`]. + /// Creates a new [`BlockWrapperBuilder`]. #[inline(always)] - pub fn build_basic( + pub fn build( protocol_version: u8, network_id: u64, slot_commitment_id: SlotCommitmentId, latest_finalized_slot: SlotIndex, issuer_id: IssuerId, - strong_parents: basic::StrongParents, - burned_mana: u64, - ) -> BlockBuilder { - BlockBuilder::new( + block: Block, + ) -> BlockWrapperBuilder { + BlockWrapperBuilder::new( protocol_version, network_id, slot_commitment_id, latest_finalized_slot, issuer_id, - BasicBlockBuilder::new(strong_parents, burned_mana), - ) - } - - /// Creates a new validation [`BlockBuilder`]. - #[inline(always)] - pub fn build_validation( - protocol_parameters: ProtocolParameters, - slot_commitment_id: SlotCommitmentId, - latest_finalized_slot: SlotIndex, - issuer_id: IssuerId, - strong_parents: validation::StrongParents, - highest_supported_version: u8, - ) -> BlockBuilder { - let protocol_hash = protocol_parameters.hash(); - BlockBuilder::new( - protocol_parameters.version(), - protocol_parameters.network_id(), - slot_commitment_id, - latest_finalized_slot, - issuer_id, - ValidationBlockBuilder::new(strong_parents, highest_supported_version, protocol_hash), + block, ) } diff --git a/sdk/src/types/block/rand/block.rs b/sdk/src/types/block/rand/block.rs index 9cdc7c291a..e7d5a69bdf 100644 --- a/sdk/src/types/block/rand/block.rs +++ b/sdk/src/types/block/rand/block.rs @@ -5,7 +5,10 @@ use alloc::vec::Vec; use super::signature::rand_sign_ed25519; use crate::types::block::{ - core::{basic, BasicBlockBuilder, BlockBuilder, BlockWrapper}, + core::{ + basic::{self, BasicBlockBuilder}, + BlockWrapper, BlockWrapperBuilder, + }, protocol::ProtocolParameters, rand::{ bytes::rand_bytes_array, @@ -15,7 +18,7 @@ use crate::types::block::{ payload::rand_payload_for_block, slot::{rand_slot_commitment_id, rand_slot_index}, }, - BlockId, + Block, BlockId, }; /// Generates a random block id. @@ -31,41 +34,50 @@ pub fn rand_block_ids(len: usize) -> Vec { } /// Generates a random basic block with given strong parents. -pub fn rand_basic_block_with_strong_parents( - protocol_params: ProtocolParameters, - strong_parents: basic::StrongParents, -) -> BlockWrapper { - rand_basic_block_builder_with_strong_parents(protocol_params, strong_parents).sign_random() +pub fn rand_basic_block_with_strong_parents(strong_parents: basic::StrongParents) -> Block { + rand_basic_block_builder_with_strong_parents(strong_parents) + .with_payload(rand_payload_for_block()) + .finish_block() + .unwrap() } /// Generates a random basic block builder with given strong parents. -pub fn rand_basic_block_builder_with_strong_parents( - protocol_params: ProtocolParameters, - strong_parents: basic::StrongParents, -) -> BlockBuilder { - BlockWrapper::build_basic( +pub fn rand_basic_block_builder_with_strong_parents(strong_parents: basic::StrongParents) -> BasicBlockBuilder { + Block::build_basic(strong_parents, rand_number()) +} + +/// Generates a random block wrapper with given block. +pub fn rand_block_wrapper_with_block(protocol_params: ProtocolParameters, block: Block) -> BlockWrapper { + BlockWrapper::build( protocol_params.version(), protocol_params.network_id(), rand_slot_commitment_id(), rand_slot_index(), rand_issuer_id(), - strong_parents, - rand_number(), + block, ) .with_issuing_time(rand_number::()) - .with_payload(rand_payload_for_block()) + .sign_random() +} + +/// Generates a random block wrapper with given strong parents. +pub fn rand_block_wrapper_with_strong_parents( + protocol_params: ProtocolParameters, + strong_parents: basic::StrongParents, +) -> BlockWrapper { + rand_block_wrapper_with_block(protocol_params, rand_basic_block_with_strong_parents(strong_parents)) } /// Generates a random block wrapper. pub fn rand_block_wrapper(protocol_params: ProtocolParameters) -> BlockWrapper { - rand_basic_block_with_strong_parents(protocol_params, rand_strong_parents()) + rand_block_wrapper_with_strong_parents(protocol_params, rand_strong_parents()) } pub trait SignBlockRandom { fn sign_random(self) -> BlockWrapper; } -impl SignBlockRandom for BlockBuilder { +impl SignBlockRandom for BlockWrapperBuilder { fn sign_random(self) -> BlockWrapper { let signing_input = self.signing_input(); self.finish(rand_sign_ed25519(&signing_input)).unwrap() diff --git a/sdk/tests/types/block.rs b/sdk/tests/types/block.rs index da93fbe05e..0a19f5ff98 100644 --- a/sdk/tests/types/block.rs +++ b/sdk/tests/types/block.rs @@ -7,7 +7,7 @@ use iota_sdk::types::{ payload::Payload, protocol::{protocol_parameters, ProtocolParameters}, rand::{ - block::{rand_basic_block_builder_with_strong_parents, rand_block_wrapper, SignBlockRandom}, + block::{rand_basic_block_builder_with_strong_parents, rand_block_wrapper, rand_block_wrapper_with_block}, parents::rand_strong_parents, payload::rand_tagged_data_payload, }, @@ -108,9 +108,11 @@ fn getters() { let parents = rand_strong_parents(); let payload = Payload::from(rand_tagged_data_payload()); - let wrapper = rand_basic_block_builder_with_strong_parents(protocol_parameters.clone(), parents.clone()) + let block = rand_basic_block_builder_with_strong_parents(parents.clone()) .with_payload(payload.clone()) - .sign_random(); + .finish_block() + .unwrap(); + let wrapper = rand_block_wrapper_with_block(protocol_parameters.clone(), block); assert_eq!(wrapper.protocol_version(), protocol_parameters.version()); assert_eq!(*wrapper.as_basic().strong_parents(), parents); From e24855c23bf4aabc7964d7c798f065c49c59c28d Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Wed, 4 Oct 2023 18:20:54 +0200 Subject: [PATCH 50/57] Nits --- sdk/src/types/block/core/wrapper.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index d874853c34..7dd7134e18 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -21,7 +21,7 @@ use crate::types::block::{ Block, Error, IssuerId, }; -/// Represent the object that nodes gossip around the network. +/// Builder for a [`BlockWrapper`]. #[derive(Clone, Debug, Eq, PartialEq)] pub struct BlockWrapperBuilder { /// Protocol version of the network to which this block belongs. @@ -52,11 +52,11 @@ impl BlockWrapperBuilder { Self { protocol_version, network_id, + issuing_time: Default::default(), slot_commitment_id, latest_finalized_slot, issuer_id, block, - issuing_time: Default::default(), } } From 4dbbd3f911edb6fcaa5d3bd38e9b638f5ded002c Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 4 Oct 2023 12:43:16 -0400 Subject: [PATCH 51/57] simplify name --- bindings/core/src/method_handler/client.rs | 2 +- sdk/examples/client/block/00_block_no_payload.rs | 2 +- sdk/examples/client/block/01_block_confirmation_time.rs | 2 +- sdk/examples/client/block/02_block_custom_parents.rs | 2 +- sdk/examples/client/block/03_block_custom_payload.rs | 2 +- sdk/examples/client/block/04_block_tagged_data.rs | 2 +- sdk/examples/client/node_api_core/04_post_block.rs | 2 +- sdk/examples/client/node_api_core/05_post_block_raw.rs | 2 +- sdk/src/client/api/block_builder/mod.rs | 2 +- sdk/src/wallet/account/operations/reissue.rs | 4 ++-- .../account/operations/transaction/submit_transaction.rs | 2 +- sdk/tests/client/node_api/mod.rs | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/bindings/core/src/method_handler/client.rs b/bindings/core/src/method_handler/client.rs index 4994da2b67..b94a196937 100644 --- a/bindings/core/src/method_handler/client.rs +++ b/bindings/core/src/method_handler/client.rs @@ -177,7 +177,7 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM ClientMethod::GetProtocolParameters => Response::ProtocolParameters(client.get_protocol_parameters().await?), ClientMethod::PostBlockPayload { payload } => { let block = client - .unsigned_basic_block_builder( + .basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, diff --git a/sdk/examples/client/block/00_block_no_payload.rs b/sdk/examples/client/block/00_block_no_payload.rs index 701a4d51a2..f881d90ff6 100644 --- a/sdk/examples/client/block/00_block_no_payload.rs +++ b/sdk/examples/client/block/00_block_no_payload.rs @@ -29,7 +29,7 @@ async fn main() -> Result<()> { // Create and send the block. let block = client - .unsigned_basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) + .basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) .await? .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; diff --git a/sdk/examples/client/block/01_block_confirmation_time.rs b/sdk/examples/client/block/01_block_confirmation_time.rs index 8bba73d575..2086b1da75 100644 --- a/sdk/examples/client/block/01_block_confirmation_time.rs +++ b/sdk/examples/client/block/01_block_confirmation_time.rs @@ -32,7 +32,7 @@ async fn main() -> Result<()> { // Create and send a block. let block = client - .unsigned_basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) + .basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) .await? .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; diff --git a/sdk/examples/client/block/02_block_custom_parents.rs b/sdk/examples/client/block/02_block_custom_parents.rs index 55b1142628..3e010869b1 100644 --- a/sdk/examples/client/block/02_block_custom_parents.rs +++ b/sdk/examples/client/block/02_block_custom_parents.rs @@ -33,7 +33,7 @@ async fn main() -> Result<()> { // Create and send the block with custom parents. let block = client - .unsigned_basic_block_builder( + .basic_block_builder( todo!("issuer id"), todo!("issuing time"), Some(issuance.strong_parents()?), diff --git a/sdk/examples/client/block/03_block_custom_payload.rs b/sdk/examples/client/block/03_block_custom_payload.rs index 7bb4853399..f0503f348f 100644 --- a/sdk/examples/client/block/03_block_custom_payload.rs +++ b/sdk/examples/client/block/03_block_custom_payload.rs @@ -35,7 +35,7 @@ async fn main() -> Result<()> { // Create and send the block with the custom payload. let block = client - .unsigned_basic_block_builder( + .basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, diff --git a/sdk/examples/client/block/04_block_tagged_data.rs b/sdk/examples/client/block/04_block_tagged_data.rs index 19fe0f79c5..ca93def698 100644 --- a/sdk/examples/client/block/04_block_tagged_data.rs +++ b/sdk/examples/client/block/04_block_tagged_data.rs @@ -32,7 +32,7 @@ async fn main() -> Result<()> { // Create and send the block with tag and data. let block = client - .unsigned_basic_block_builder( + .basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, diff --git a/sdk/examples/client/node_api_core/04_post_block.rs b/sdk/examples/client/node_api_core/04_post_block.rs index 1ab0f5de34..57ecde0dfd 100644 --- a/sdk/examples/client/node_api_core/04_post_block.rs +++ b/sdk/examples/client/node_api_core/04_post_block.rs @@ -32,7 +32,7 @@ async fn main() -> Result<()> { // Create the block. let block = client - .unsigned_basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) + .basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) .await? .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; diff --git a/sdk/examples/client/node_api_core/05_post_block_raw.rs b/sdk/examples/client/node_api_core/05_post_block_raw.rs index b76fc082c9..56fc08f80f 100644 --- a/sdk/examples/client/node_api_core/05_post_block_raw.rs +++ b/sdk/examples/client/node_api_core/05_post_block_raw.rs @@ -32,7 +32,7 @@ async fn main() -> Result<()> { // Create the block. let block = client - .unsigned_basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) + .basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) .await? .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; diff --git a/sdk/src/client/api/block_builder/mod.rs b/sdk/src/client/api/block_builder/mod.rs index 19a0496601..da421c4027 100644 --- a/sdk/src/client/api/block_builder/mod.rs +++ b/sdk/src/client/api/block_builder/mod.rs @@ -15,7 +15,7 @@ use crate::{ }; impl ClientInner { - pub async fn unsigned_basic_block_builder( + pub async fn basic_block_builder( &self, issuer_id: IssuerId, issuing_time: Option, diff --git a/sdk/src/wallet/account/operations/reissue.rs b/sdk/src/wallet/account/operations/reissue.rs index cbcf888b79..85c4fc9c78 100644 --- a/sdk/src/wallet/account/operations/reissue.rs +++ b/sdk/src/wallet/account/operations/reissue.rs @@ -61,7 +61,7 @@ where Some(block_id) => block_id, None => self .client() - .unsigned_basic_block_builder( + .basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, @@ -114,7 +114,7 @@ where if index == block_ids_len - 1 && should_reissue { let reissued_block = self .client() - .unsigned_basic_block_builder( + .basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, diff --git a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs index 59b665e80c..dd9229a351 100644 --- a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs +++ b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs @@ -27,7 +27,7 @@ where let block = self .client() - .unsigned_basic_block_builder( + .basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, diff --git a/sdk/tests/client/node_api/mod.rs b/sdk/tests/client/node_api/mod.rs index e8a987aa4e..2235a6d369 100644 --- a/sdk/tests/client/node_api/mod.rs +++ b/sdk/tests/client/node_api/mod.rs @@ -34,7 +34,7 @@ async fn setup_tagged_data_block(secret_manager: &SecretManager) -> BlockId { let protocol_params = client.get_protocol_parameters().await.unwrap(); client - .unsigned_basic_block_builder( + .basic_block_builder( todo!("issuer id"), todo!("issuing time"), None, From b5d14e2cd67308eb0cd25c5a7d23814a7542f272 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 4 Oct 2023 12:43:42 -0400 Subject: [PATCH 52/57] rename trait --- bindings/core/src/method_handler/client.rs | 2 +- sdk/examples/client/block/00_block_no_payload.rs | 2 +- sdk/examples/client/block/01_block_confirmation_time.rs | 2 +- sdk/examples/client/block/02_block_custom_parents.rs | 2 +- sdk/examples/client/block/03_block_custom_payload.rs | 2 +- sdk/examples/client/block/04_block_tagged_data.rs | 2 +- sdk/examples/client/node_api_core/04_post_block.rs | 2 +- sdk/examples/client/node_api_core/05_post_block_raw.rs | 2 +- sdk/src/client/secret/mod.rs | 4 ++-- sdk/src/wallet/account/operations/reissue.rs | 2 +- .../account/operations/transaction/submit_transaction.rs | 2 +- sdk/tests/client/node_api/mod.rs | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/bindings/core/src/method_handler/client.rs b/bindings/core/src/method_handler/client.rs index b94a196937..d576a0938d 100644 --- a/bindings/core/src/method_handler/client.rs +++ b/bindings/core/src/method_handler/client.rs @@ -6,7 +6,7 @@ use iota_sdk::client::mqtt::{MqttPayload, Topic}; use iota_sdk::{ client::{ request_funds_from_faucet, - secret::{SecretManager, SignBlockExt}, + secret::{SecretManager, SignBlock}, Client, }, types::{ diff --git a/sdk/examples/client/block/00_block_no_payload.rs b/sdk/examples/client/block/00_block_no_payload.rs index f881d90ff6..cd3fd9f8b8 100644 --- a/sdk/examples/client/block/00_block_no_payload.rs +++ b/sdk/examples/client/block/00_block_no_payload.rs @@ -11,7 +11,7 @@ use crypto::keys::bip44::Bip44; use iota_sdk::client::{ constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlockExt}, + secret::{SecretManager, SignBlock}, Client, Result, }; diff --git a/sdk/examples/client/block/01_block_confirmation_time.rs b/sdk/examples/client/block/01_block_confirmation_time.rs index 2086b1da75..b6702946b5 100644 --- a/sdk/examples/client/block/01_block_confirmation_time.rs +++ b/sdk/examples/client/block/01_block_confirmation_time.rs @@ -12,7 +12,7 @@ use crypto::keys::bip44::Bip44; use iota_sdk::{ client::{ constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlockExt}, + secret::{SecretManager, SignBlock}, Client, Result, }, types::api::core::response::BlockState, diff --git a/sdk/examples/client/block/02_block_custom_parents.rs b/sdk/examples/client/block/02_block_custom_parents.rs index 3e010869b1..d480fe3eae 100644 --- a/sdk/examples/client/block/02_block_custom_parents.rs +++ b/sdk/examples/client/block/02_block_custom_parents.rs @@ -11,7 +11,7 @@ use crypto::keys::bip44::Bip44; use iota_sdk::client::{ constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlockExt}, + secret::{SecretManager, SignBlock}, Client, Result, }; diff --git a/sdk/examples/client/block/03_block_custom_payload.rs b/sdk/examples/client/block/03_block_custom_payload.rs index f0503f348f..88cad4a929 100644 --- a/sdk/examples/client/block/03_block_custom_payload.rs +++ b/sdk/examples/client/block/03_block_custom_payload.rs @@ -12,7 +12,7 @@ use crypto::keys::bip44::Bip44; use iota_sdk::{ client::{ constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlockExt}, + secret::{SecretManager, SignBlock}, Client, Result, }, types::block::payload::{Payload, TaggedDataPayload}, diff --git a/sdk/examples/client/block/04_block_tagged_data.rs b/sdk/examples/client/block/04_block_tagged_data.rs index ca93def698..5ebe6d2aaa 100644 --- a/sdk/examples/client/block/04_block_tagged_data.rs +++ b/sdk/examples/client/block/04_block_tagged_data.rs @@ -12,7 +12,7 @@ use crypto::keys::bip44::Bip44; use iota_sdk::{ client::{ constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlockExt}, + secret::{SecretManager, SignBlock}, Client, Result, }, types::block::payload::{Payload, TaggedDataPayload}, diff --git a/sdk/examples/client/node_api_core/04_post_block.rs b/sdk/examples/client/node_api_core/04_post_block.rs index 57ecde0dfd..7665018445 100644 --- a/sdk/examples/client/node_api_core/04_post_block.rs +++ b/sdk/examples/client/node_api_core/04_post_block.rs @@ -11,7 +11,7 @@ use crypto::keys::bip44::Bip44; use iota_sdk::client::{ constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlockExt}, + secret::{SecretManager, SignBlock}, Client, Result, }; diff --git a/sdk/examples/client/node_api_core/05_post_block_raw.rs b/sdk/examples/client/node_api_core/05_post_block_raw.rs index 56fc08f80f..56cb6307fd 100644 --- a/sdk/examples/client/node_api_core/05_post_block_raw.rs +++ b/sdk/examples/client/node_api_core/05_post_block_raw.rs @@ -11,7 +11,7 @@ use crypto::keys::bip44::Bip44; use iota_sdk::client::{ constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlockExt}, + secret::{SecretManager, SignBlock}, Client, Result, }; diff --git a/sdk/src/client/secret/mod.rs b/sdk/src/client/secret/mod.rs index a995400f36..1815419905 100644 --- a/sdk/src/client/secret/mod.rs +++ b/sdk/src/client/secret/mod.rs @@ -606,7 +606,7 @@ where } #[async_trait] -pub trait SignBlockExt { +pub trait SignBlock { async fn sign_ed25519( self, secret_manager: &S, @@ -617,7 +617,7 @@ pub trait SignBlockExt { } #[async_trait] -impl SignBlockExt for BlockWrapperBuilder { +impl SignBlock for BlockWrapperBuilder { async fn sign_ed25519( self, secret_manager: &S, diff --git a/sdk/src/wallet/account/operations/reissue.rs b/sdk/src/wallet/account/operations/reissue.rs index 85c4fc9c78..a2632a4b9f 100644 --- a/sdk/src/wallet/account/operations/reissue.rs +++ b/sdk/src/wallet/account/operations/reissue.rs @@ -5,7 +5,7 @@ use crypto::keys::bip44::Bip44; use crate::{ client::{ - secret::{SecretManage, SignBlockExt}, + secret::{SecretManage, SignBlock}, Error as ClientError, }, types::{ diff --git a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs index dd9229a351..793c732fec 100644 --- a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs +++ b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs @@ -6,7 +6,7 @@ use crypto::keys::bip44::Bip44; #[cfg(feature = "events")] use crate::wallet::events::types::{TransactionProgressEvent, WalletEvent}; use crate::{ - client::secret::{SecretManage, SignBlockExt}, + client::secret::{SecretManage, SignBlock}, types::block::{payload::Payload, BlockId}, wallet::account::{operations::transaction::TransactionPayload, Account}, }; diff --git a/sdk/tests/client/node_api/mod.rs b/sdk/tests/client/node_api/mod.rs index 2235a6d369..207f3d4246 100644 --- a/sdk/tests/client/node_api/mod.rs +++ b/sdk/tests/client/node_api/mod.rs @@ -13,7 +13,7 @@ use iota_sdk::{ constants::IOTA_COIN_TYPE, node_api::indexer::query_parameters::QueryParameter, request_funds_from_faucet, - secret::{SecretManager, SignBlockExt}, + secret::{SecretManager, SignBlock}, Client, }, types::block::{ From 555450a5c149be88c021590cca7efdc98f68684f Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 4 Oct 2023 12:55:57 -0400 Subject: [PATCH 53/57] use header more --- sdk/src/client/api/block_builder/mod.rs | 18 +-- sdk/src/types/block/core/wrapper.rs | 184 ++++++------------------ sdk/src/types/block/rand/block.rs | 16 ++- 3 files changed, 62 insertions(+), 156 deletions(-) diff --git a/sdk/src/client/api/block_builder/mod.rs b/sdk/src/client/api/block_builder/mod.rs index da421c4027..a863796d24 100644 --- a/sdk/src/client/api/block_builder/mod.rs +++ b/sdk/src/client/api/block_builder/mod.rs @@ -8,7 +8,7 @@ pub use self::transaction::verify_semantic; use crate::{ client::{ClientInner, Result}, types::block::{ - core::{basic, BlockWrapper, BlockWrapperBuilder}, + core::{basic, BlockHeader, BlockWrapper, BlockWrapperBuilder}, payload::Payload, Block, IssuerId, }, @@ -41,17 +41,19 @@ impl ClientInner { let protocol_params = self.get_protocol_parameters().await?; Ok(BlockWrapper::build( - protocol_params.version(), - protocol_params.network_id(), - issuance.commitment.id(), - issuance.latest_finalized_slot, - issuer_id, + BlockHeader::new( + protocol_params.version(), + protocol_params.network_id(), + issuing_time, + issuance.commitment.id(), + issuance.latest_finalized_slot, + issuer_id, + ), Block::build_basic(strong_parents, 0) // TODO: burned mana calculation .with_weak_parents(issuance.weak_parents()?) .with_shallow_like_parents(issuance.shallow_like_parents()?) .with_payload(payload) .finish_block()?, - ) - .with_issuing_time(issuing_time)) + )) } } diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index 7dd7134e18..67865aabf2 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -24,125 +24,39 @@ use crate::types::block::{ /// Builder for a [`BlockWrapper`]. #[derive(Clone, Debug, Eq, PartialEq)] pub struct BlockWrapperBuilder { - /// Protocol version of the network to which this block belongs. - pub(crate) protocol_version: u8, - /// The identifier of the network to which this block belongs. - pub(crate) network_id: u64, - /// The time at which the block was issued. It is a Unix timestamp in nanoseconds. - pub(crate) issuing_time: Option, - /// The identifier of the slot to which this block commits. - pub(crate) slot_commitment_id: SlotCommitmentId, - /// The slot index of the latest finalized slot. - pub(crate) latest_finalized_slot: SlotIndex, - /// The identifier of the account that issued this block. - pub(crate) issuer_id: IssuerId, + /// The block header. + pub(crate) header: BlockHeader, /// The inner block. pub(crate) block: Block, } impl BlockWrapperBuilder { - pub fn new( - protocol_version: u8, - network_id: u64, - slot_commitment_id: SlotCommitmentId, - latest_finalized_slot: SlotIndex, - issuer_id: IssuerId, - block: Block, - ) -> Self { - Self { - protocol_version, - network_id, - issuing_time: Default::default(), - slot_commitment_id, - latest_finalized_slot, - issuer_id, - block, - } + pub fn new(header: BlockHeader, block: Block) -> Self { + Self { header, block } } - /// Updates protocol version. + /// Updates the block header. #[inline(always)] - pub fn with_protocol_version(mut self, protocol_version: u8) -> Self { - self.protocol_version = protocol_version; - self - } - - /// Updates network id - #[inline(always)] - pub fn with_network_id(mut self, network_id: u64) -> Self { - self.network_id = network_id; - self - } - - /// Adds issuing time. - #[inline(always)] - pub fn with_issuing_time(mut self, issuing_time: impl Into>) -> Self { - self.issuing_time = issuing_time.into(); - self - } - - /// Updates the slot commitment id. - #[inline(always)] - pub fn with_slot_commitment_id(mut self, slot_commitment_id: impl Into) -> Self { - self.slot_commitment_id = slot_commitment_id.into(); - self - } - - /// Updates the latest finalized slot. - #[inline(always)] - pub fn with_latest_finalized_slot(mut self, latest_finalized_slot: impl Into) -> Self { - self.latest_finalized_slot = latest_finalized_slot.into(); - self - } - - /// Updates the issuer id. - #[inline(always)] - pub fn with_issuer_id(mut self, issuer_id: impl Into) -> Self { - self.issuer_id = issuer_id.into(); + pub fn with_block_header(mut self, header: BlockHeader) -> Self { + self.header = header; self } /// Updates the block. #[inline(always)] - pub fn with_block(mut self, block: impl Into) -> Self { - self.block = block.into(); + pub fn with_block(mut self, block: Block) -> Self { + self.block = block; self } - pub(crate) fn header_hash(&self) -> [u8; 32] { - let mut bytes = [0u8; BlockHeader::LENGTH]; - BlockHeader { - protocol_version: self.protocol_version, - network_id: self.network_id, - // TODO: what do here - issuing_time: self.issuing_time.expect("issuing time not set"), - slot_commitment_id: self.slot_commitment_id, - latest_finalized_slot: self.latest_finalized_slot, - issuer_id: self.issuer_id, - } - .pack(&mut SlicePacker::new(&mut bytes)) - .unwrap(); - Blake2b256::digest(bytes).into() - } - /// Get the signing input that can be used to generate an /// [`Ed25519Signature`](crate::types::block::signature::Ed25519Signature) for the resulting block. pub fn signing_input(&self) -> Vec { - [self.header_hash(), self.block.hash()].concat() + [self.header.hash(), self.block.hash()].concat() } pub fn finish(self, signature: Ed25519Signature) -> Result { - Ok(BlockWrapper::new( - self.protocol_version, - self.network_id, - // TODO provide a sensible default - self.issuing_time.ok_or(Error::InvalidField("issuing time"))?, - self.slot_commitment_id, - self.latest_finalized_slot, - self.issuer_id, - self.block, - signature, - )) + Ok(BlockWrapper::new(self.header, self.block, signature)) } } @@ -154,11 +68,11 @@ pub struct BlockHeader { /// The identifier of the network to which this block belongs. network_id: u64, /// The time at which the block was issued. It is a Unix timestamp in nanoseconds. - pub(crate) issuing_time: u64, + issuing_time: u64, /// The identifier of the slot to which this block commits. - pub(crate) slot_commitment_id: SlotCommitmentId, + slot_commitment_id: SlotCommitmentId, /// The slot index of the latest finalized slot. - pub(crate) latest_finalized_slot: SlotIndex, + latest_finalized_slot: SlotIndex, /// The identifier of the account that issued this block. issuer_id: IssuerId, } @@ -168,6 +82,24 @@ impl BlockHeader { pub const LENGTH: usize = size_of::() + 2 * size_of::() + SlotCommitmentId::LENGTH + size_of::() + IssuerId::LENGTH; + pub fn new( + protocol_version: u8, + network_id: u64, + issuing_time: u64, + slot_commitment_id: SlotCommitmentId, + latest_finalized_slot: SlotIndex, + issuer_id: IssuerId, + ) -> Self { + Self { + protocol_version, + network_id, + issuing_time, + slot_commitment_id, + latest_finalized_slot, + issuer_id, + } + } + pub(crate) fn hash(&self) -> [u8; 32] { let mut bytes = [0u8; Self::LENGTH]; @@ -253,25 +185,7 @@ impl BlockWrapper { /// Creates a new [`BlockWrapper`]. #[inline(always)] - pub fn new( - protocol_version: u8, - network_id: u64, - issuing_time: u64, - slot_commitment_id: SlotCommitmentId, - latest_finalized_slot: SlotIndex, - issuer_id: IssuerId, - block: impl Into, - signature: impl Into, - ) -> Self { - let header = BlockHeader { - protocol_version, - network_id, - issuing_time, - slot_commitment_id, - latest_finalized_slot, - issuer_id, - }; - let block = block.into(); + pub fn new(header: BlockHeader, block: Block, signature: impl Into) -> Self { let signature = signature.into(); Self { @@ -283,22 +197,8 @@ impl BlockWrapper { /// Creates a new [`BlockWrapperBuilder`]. #[inline(always)] - pub fn build( - protocol_version: u8, - network_id: u64, - slot_commitment_id: SlotCommitmentId, - latest_finalized_slot: SlotIndex, - issuer_id: IssuerId, - block: Block, - ) -> BlockWrapperBuilder { - BlockWrapperBuilder::new( - protocol_version, - network_id, - slot_commitment_id, - latest_finalized_slot, - issuer_id, - block, - ) + pub fn build(header: BlockHeader, block: Block) -> BlockWrapperBuilder { + BlockWrapperBuilder::new(header, block) } /// Returns the protocol version of a [`BlockWrapper`]. @@ -498,12 +398,14 @@ pub(crate) mod dto { } Ok(Self::new( - dto.protocol_version, - dto.network_id, - dto.issuing_time, - dto.slot_commitment_id, - dto.latest_finalized_slot, - dto.issuer_id, + BlockHeader::new( + dto.protocol_version, + dto.network_id, + dto.issuing_time, + dto.slot_commitment_id, + dto.latest_finalized_slot, + dto.issuer_id, + ), Block::try_from_dto_with_params_inner(dto.block, params)?, dto.signature, )) diff --git a/sdk/src/types/block/rand/block.rs b/sdk/src/types/block/rand/block.rs index e7d5a69bdf..a707d763b3 100644 --- a/sdk/src/types/block/rand/block.rs +++ b/sdk/src/types/block/rand/block.rs @@ -7,7 +7,7 @@ use super::signature::rand_sign_ed25519; use crate::types::block::{ core::{ basic::{self, BasicBlockBuilder}, - BlockWrapper, BlockWrapperBuilder, + BlockHeader, BlockWrapper, BlockWrapperBuilder, }, protocol::ProtocolParameters, rand::{ @@ -49,14 +49,16 @@ pub fn rand_basic_block_builder_with_strong_parents(strong_parents: basic::Stron /// Generates a random block wrapper with given block. pub fn rand_block_wrapper_with_block(protocol_params: ProtocolParameters, block: Block) -> BlockWrapper { BlockWrapper::build( - protocol_params.version(), - protocol_params.network_id(), - rand_slot_commitment_id(), - rand_slot_index(), - rand_issuer_id(), + BlockHeader::new( + protocol_params.version(), + protocol_params.network_id(), + rand_number(), + rand_slot_commitment_id(), + rand_slot_index(), + rand_issuer_id(), + ), block, ) - .with_issuing_time(rand_number::()) .sign_random() } From 981a673e9d1029725b91732d55b774942e3f1eb0 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 4 Oct 2023 12:57:19 -0400 Subject: [PATCH 54/57] move it move it --- sdk/src/types/block/rand/block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/rand/block.rs b/sdk/src/types/block/rand/block.rs index a707d763b3..cedfa623ce 100644 --- a/sdk/src/types/block/rand/block.rs +++ b/sdk/src/types/block/rand/block.rs @@ -3,7 +3,6 @@ use alloc::vec::Vec; -use super::signature::rand_sign_ed25519; use crate::types::block::{ core::{ basic::{self, BasicBlockBuilder}, @@ -16,6 +15,7 @@ use crate::types::block::{ number::rand_number, parents::rand_strong_parents, payload::rand_payload_for_block, + signature::rand_sign_ed25519, slot::{rand_slot_commitment_id, rand_slot_index}, }, Block, BlockId, From 5d692af260ef1147330c4676e4fddb33a8e622f8 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 4 Oct 2023 14:59:56 -0400 Subject: [PATCH 55/57] PR suggestions --- bindings/core/src/method_handler/client.rs | 12 ++++------ .../client/block/00_block_no_payload.rs | 17 +++++++------- .../block/01_block_confirmation_time.rs | 17 +++++++------- .../client/block/02_block_custom_parents.rs | 12 ++++------ .../client/block/03_block_custom_payload.rs | 12 ++++------ .../client/block/04_block_tagged_data.rs | 12 ++++------ .../client/node_api_core/04_post_block.rs | 17 +++++++------- .../client/node_api_core/05_post_block_raw.rs | 17 +++++++------- sdk/src/client/api/block_builder/mod.rs | 22 ++++++++++++++----- sdk/src/types/block/core/wrapper.rs | 4 ++-- sdk/src/wallet/account/operations/reissue.rs | 15 +++---------- .../transaction/submit_transaction.rs | 7 ++---- sdk/tests/client/node_api/mod.rs | 15 +++++-------- 13 files changed, 81 insertions(+), 98 deletions(-) diff --git a/bindings/core/src/method_handler/client.rs b/bindings/core/src/method_handler/client.rs index d576a0938d..5c1845d46d 100644 --- a/bindings/core/src/method_handler/client.rs +++ b/bindings/core/src/method_handler/client.rs @@ -4,11 +4,7 @@ #[cfg(feature = "mqtt")] use iota_sdk::client::mqtt::{MqttPayload, Topic}; use iota_sdk::{ - client::{ - request_funds_from_faucet, - secret::{SecretManager, SignBlock}, - Client, - }, + client::{request_funds_from_faucet, secret::SecretManager, Client}, types::{ api::core::response::OutputWithMetadataResponse, block::{ @@ -177,7 +173,7 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM ClientMethod::GetProtocolParameters => Response::ProtocolParameters(client.get_protocol_parameters().await?), ClientMethod::PostBlockPayload { payload } => { let block = client - .basic_block_builder( + .build_basic_block::( todo!("issuer id"), todo!("issuing time"), None, @@ -185,9 +181,9 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM payload, &client.get_protocol_parameters().await?, )?), + todo!("secret manager"), + todo!("chain"), ) - .await? - .sign_ed25519::(todo!("secret manager"), todo!("chain")) .await?; let block_id = client.block_id(&block).await?; diff --git a/sdk/examples/client/block/00_block_no_payload.rs b/sdk/examples/client/block/00_block_no_payload.rs index cd3fd9f8b8..ce029516bc 100644 --- a/sdk/examples/client/block/00_block_no_payload.rs +++ b/sdk/examples/client/block/00_block_no_payload.rs @@ -9,11 +9,7 @@ //! ``` use crypto::keys::bip44::Bip44; -use iota_sdk::client::{ - constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlock}, - Client, Result, -}; +use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; #[tokio::main] async fn main() -> Result<()> { @@ -29,9 +25,14 @@ async fn main() -> Result<()> { // Create and send the block. let block = client - .basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) - .await? - .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) + .build_basic_block( + todo!("issuer id"), + todo!("issuing time"), + None, + None, + &secret_manager, + Bip44::new(IOTA_COIN_TYPE), + ) .await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/01_block_confirmation_time.rs b/sdk/examples/client/block/01_block_confirmation_time.rs index b6702946b5..6b6b961dc8 100644 --- a/sdk/examples/client/block/01_block_confirmation_time.rs +++ b/sdk/examples/client/block/01_block_confirmation_time.rs @@ -10,11 +10,7 @@ use crypto::keys::bip44::Bip44; use iota_sdk::{ - client::{ - constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlock}, - Client, Result, - }, + client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}, types::api::core::response::BlockState, }; @@ -32,9 +28,14 @@ async fn main() -> Result<()> { // Create and send a block. let block = client - .basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) - .await? - .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) + .build_basic_block( + todo!("issuer id"), + todo!("issuing time"), + None, + None, + &secret_manager, + Bip44::new(IOTA_COIN_TYPE), + ) .await?; let block_id = client.block_id(&block).await?; diff --git a/sdk/examples/client/block/02_block_custom_parents.rs b/sdk/examples/client/block/02_block_custom_parents.rs index d480fe3eae..2a01e8f95b 100644 --- a/sdk/examples/client/block/02_block_custom_parents.rs +++ b/sdk/examples/client/block/02_block_custom_parents.rs @@ -9,11 +9,7 @@ //! ``` use crypto::keys::bip44::Bip44; -use iota_sdk::client::{ - constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlock}, - Client, Result, -}; +use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; #[tokio::main] async fn main() -> Result<()> { @@ -33,14 +29,14 @@ async fn main() -> Result<()> { // Create and send the block with custom parents. let block = client - .basic_block_builder( + .build_basic_block( todo!("issuer id"), todo!("issuing time"), Some(issuance.strong_parents()?), None, + &secret_manager, + Bip44::new(IOTA_COIN_TYPE), ) - .await? - .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/03_block_custom_payload.rs b/sdk/examples/client/block/03_block_custom_payload.rs index 88cad4a929..b27c5a289c 100644 --- a/sdk/examples/client/block/03_block_custom_payload.rs +++ b/sdk/examples/client/block/03_block_custom_payload.rs @@ -10,11 +10,7 @@ use crypto::keys::bip44::Bip44; use iota_sdk::{ - client::{ - constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlock}, - Client, Result, - }, + client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}, types::block::payload::{Payload, TaggedDataPayload}, }; @@ -35,14 +31,14 @@ async fn main() -> Result<()> { // Create and send the block with the custom payload. let block = client - .basic_block_builder( + .build_basic_block( todo!("issuer id"), todo!("issuing time"), None, Some(Payload::from(tagged_data_payload)), + &secret_manager, + Bip44::new(IOTA_COIN_TYPE), ) - .await? - .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; println!("{block:#?}"); diff --git a/sdk/examples/client/block/04_block_tagged_data.rs b/sdk/examples/client/block/04_block_tagged_data.rs index 5ebe6d2aaa..2fc25aa84f 100644 --- a/sdk/examples/client/block/04_block_tagged_data.rs +++ b/sdk/examples/client/block/04_block_tagged_data.rs @@ -10,11 +10,7 @@ use crypto::keys::bip44::Bip44; use iota_sdk::{ - client::{ - constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlock}, - Client, Result, - }, + client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}, types::block::payload::{Payload, TaggedDataPayload}, }; @@ -32,7 +28,7 @@ async fn main() -> Result<()> { // Create and send the block with tag and data. let block = client - .basic_block_builder( + .build_basic_block( todo!("issuer id"), todo!("issuing time"), None, @@ -49,9 +45,9 @@ async fn main() -> Result<()> { ) .unwrap(), ))), + &secret_manager, + Bip44::new(IOTA_COIN_TYPE), ) - .await? - .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) .await?; println!("{block:#?}\n"); diff --git a/sdk/examples/client/node_api_core/04_post_block.rs b/sdk/examples/client/node_api_core/04_post_block.rs index 7665018445..414e3ca7cf 100644 --- a/sdk/examples/client/node_api_core/04_post_block.rs +++ b/sdk/examples/client/node_api_core/04_post_block.rs @@ -9,11 +9,7 @@ //! ``` use crypto::keys::bip44::Bip44; -use iota_sdk::client::{ - constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlock}, - Client, Result, -}; +use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; #[tokio::main] async fn main() -> Result<()> { @@ -32,9 +28,14 @@ async fn main() -> Result<()> { // Create the block. let block = client - .basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) - .await? - .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) + .build_basic_block( + todo!("issuer id"), + todo!("issuing time"), + None, + None, + &secret_manager, + Bip44::new(IOTA_COIN_TYPE), + ) .await?; // Post the block. let block_id = client.post_block(&block).await?; diff --git a/sdk/examples/client/node_api_core/05_post_block_raw.rs b/sdk/examples/client/node_api_core/05_post_block_raw.rs index 56cb6307fd..a20a0ad257 100644 --- a/sdk/examples/client/node_api_core/05_post_block_raw.rs +++ b/sdk/examples/client/node_api_core/05_post_block_raw.rs @@ -9,11 +9,7 @@ //! ``` use crypto::keys::bip44::Bip44; -use iota_sdk::client::{ - constants::IOTA_COIN_TYPE, - secret::{SecretManager, SignBlock}, - Client, Result, -}; +use iota_sdk::client::{constants::IOTA_COIN_TYPE, secret::SecretManager, Client, Result}; #[tokio::main] async fn main() -> Result<()> { @@ -32,9 +28,14 @@ async fn main() -> Result<()> { // Create the block. let block = client - .basic_block_builder(todo!("issuer id"), todo!("issuing time"), None, None) - .await? - .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) + .build_basic_block( + todo!("issuer id"), + todo!("issuing time"), + None, + None, + &secret_manager, + Bip44::new(IOTA_COIN_TYPE), + ) .await?; // Post the block as raw bytes. let block_id = client.post_block_raw(&block).await?; diff --git a/sdk/src/client/api/block_builder/mod.rs b/sdk/src/client/api/block_builder/mod.rs index a863796d24..80b5b78280 100644 --- a/sdk/src/client/api/block_builder/mod.rs +++ b/sdk/src/client/api/block_builder/mod.rs @@ -4,24 +4,34 @@ pub mod input_selection; pub mod transaction; +use crypto::keys::bip44::Bip44; + pub use self::transaction::verify_semantic; use crate::{ - client::{ClientInner, Result}, + client::{ + secret::{SecretManage, SignBlock}, + ClientInner, Result, + }, types::block::{ - core::{basic, BlockHeader, BlockWrapper, BlockWrapperBuilder}, + core::{basic, BlockHeader, BlockWrapper}, payload::Payload, Block, IssuerId, }, }; impl ClientInner { - pub async fn basic_block_builder( + pub async fn build_basic_block( &self, issuer_id: IssuerId, issuing_time: Option, strong_parents: Option, payload: Option, - ) -> Result { + secret_manager: &S, + chain: Bip44, + ) -> Result + where + crate::client::Error: From, + { let issuance = self.get_issuance().await?; let strong_parents = strong_parents.unwrap_or(issuance.strong_parents()?); @@ -54,6 +64,8 @@ impl ClientInner { .with_shallow_like_parents(issuance.shallow_like_parents()?) .with_payload(payload) .finish_block()?, - )) + ) + .sign_ed25519(secret_manager, chain) + .await?) } } diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index 67865aabf2..da9c56b42d 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -16,7 +16,7 @@ use crate::types::block::{ block_id::{BlockHash, BlockId}, core::{BasicBlock, ValidationBlock}, protocol::ProtocolParameters, - signature::{Ed25519Signature, Signature}, + signature::Signature, slot::{SlotCommitmentId, SlotIndex}, Block, Error, IssuerId, }; @@ -55,7 +55,7 @@ impl BlockWrapperBuilder { [self.header.hash(), self.block.hash()].concat() } - pub fn finish(self, signature: Ed25519Signature) -> Result { + pub fn finish(self, signature: impl Into) -> Result { Ok(BlockWrapper::new(self.header, self.block, signature)) } } diff --git a/sdk/src/wallet/account/operations/reissue.rs b/sdk/src/wallet/account/operations/reissue.rs index a2632a4b9f..54c93a4f42 100644 --- a/sdk/src/wallet/account/operations/reissue.rs +++ b/sdk/src/wallet/account/operations/reissue.rs @@ -4,10 +4,7 @@ use crypto::keys::bip44::Bip44; use crate::{ - client::{ - secret::{SecretManage, SignBlock}, - Error as ClientError, - }, + client::{secret::SecretManage, Error as ClientError}, types::{ api::core::response::{BlockState, TransactionState}, block::{ @@ -61,14 +58,11 @@ where Some(block_id) => block_id, None => self .client() - .basic_block_builder( + .build_basic_block( todo!("issuer id"), todo!("issuing time"), None, Some(Payload::Transaction(Box::new(transaction.payload.clone()))), - ) - .await? - .sign_ed25519( &*self.get_secret_manager().read().await, Bip44::new(self.wallet.coin_type()), ) @@ -114,14 +108,11 @@ where if index == block_ids_len - 1 && should_reissue { let reissued_block = self .client() - .basic_block_builder( + .build_basic_block( todo!("issuer id"), todo!("issuing time"), None, Some(Payload::Transaction(Box::new(transaction.payload.clone()))), - ) - .await? - .sign_ed25519( &*self.get_secret_manager().read().await, Bip44::new(self.wallet.coin_type()), ) diff --git a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs index 793c732fec..3175410e34 100644 --- a/sdk/src/wallet/account/operations/transaction/submit_transaction.rs +++ b/sdk/src/wallet/account/operations/transaction/submit_transaction.rs @@ -6,7 +6,7 @@ use crypto::keys::bip44::Bip44; #[cfg(feature = "events")] use crate::wallet::events::types::{TransactionProgressEvent, WalletEvent}; use crate::{ - client::secret::{SecretManage, SignBlock}, + client::secret::SecretManage, types::block::{payload::Payload, BlockId}, wallet::account::{operations::transaction::TransactionPayload, Account}, }; @@ -27,14 +27,11 @@ where let block = self .client() - .basic_block_builder( + .build_basic_block( todo!("issuer id"), todo!("issuing time"), None, Some(Payload::from(transaction_payload)), - ) - .await? - .sign_ed25519( &*self.get_secret_manager().read().await, Bip44::new(self.wallet.coin_type()), ) diff --git a/sdk/tests/client/node_api/mod.rs b/sdk/tests/client/node_api/mod.rs index 207f3d4246..f4839038af 100644 --- a/sdk/tests/client/node_api/mod.rs +++ b/sdk/tests/client/node_api/mod.rs @@ -9,12 +9,8 @@ mod mqtt; use crypto::keys::bip44::Bip44; use iota_sdk::{ client::{ - api::GetAddressesOptions, - constants::IOTA_COIN_TYPE, - node_api::indexer::query_parameters::QueryParameter, - request_funds_from_faucet, - secret::{SecretManager, SignBlock}, - Client, + api::GetAddressesOptions, constants::IOTA_COIN_TYPE, node_api::indexer::query_parameters::QueryParameter, + request_funds_from_faucet, secret::SecretManager, Client, }, types::block::{ payload::{tagged_data::TaggedDataPayload, transaction::TransactionId, Payload}, @@ -34,19 +30,18 @@ async fn setup_tagged_data_block(secret_manager: &SecretManager) -> BlockId { let protocol_params = client.get_protocol_parameters().await.unwrap(); client - .basic_block_builder( + .build_basic_block( todo!("issuer id"), todo!("issuing time"), None, Some(Payload::TaggedData(Box::new( TaggedDataPayload::new(b"Hello".to_vec(), b"Tangle".to_vec()).unwrap(), ))), + secret_manager, + Bip44::new(IOTA_COIN_TYPE), ) .await .unwrap() - .sign_ed25519(secret_manager, Bip44::new(IOTA_COIN_TYPE)) - .await - .unwrap() .id(&protocol_params) } From 405aab4587a97cfa6a9ce300cebc15253fc2806b Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 4 Oct 2023 15:20:29 -0400 Subject: [PATCH 56/57] no_std --- sdk/src/types/block/core/wrapper.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index da9c56b42d..d0572a6394 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -1,6 +1,7 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use alloc::vec::Vec; use core::mem::size_of; use crypto::hashes::{blake2b::Blake2b256, Digest}; From 64c4550992ad3ff77481bf786a11eaede5a236a4 Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Thu, 5 Oct 2023 10:19:08 +0200 Subject: [PATCH 57/57] Nit --- sdk/src/types/block/core/wrapper.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index d0572a6394..d66cf14d71 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -50,8 +50,8 @@ impl BlockWrapperBuilder { self } - /// Get the signing input that can be used to generate an - /// [`Ed25519Signature`](crate::types::block::signature::Ed25519Signature) for the resulting block. + /// Get the signing input that can be used to generate a [`Signature`](crate::types::block::signature::Signature) + /// for the resulting block. pub fn signing_input(&self) -> Vec { [self.header.hash(), self.block.hash()].concat() }