From 80a2eda53f17cea049b638c047d4730c7e82a20a Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 15 Sep 2023 13:02:10 +0200 Subject: [PATCH 01/42] add workscore calc --- sdk/src/client/node_api/core/routes.rs | 2 +- sdk/src/types/block/basic.rs | 33 +++++++++++++++++++++++++- sdk/src/types/block/core.rs | 21 ++++++++++++++++ sdk/src/types/block/payload/mod.rs | 7 ++++++ sdk/src/types/block/protocol.rs | 30 +++++++++++++---------- sdk/src/types/block/slot/index.rs | 2 +- sdk/src/types/block/validation.rs | 21 +++++++++++++++- 7 files changed, 99 insertions(+), 17 deletions(-) diff --git a/sdk/src/client/node_api/core/routes.rs b/sdk/src/client/node_api/core/routes.rs index f6ad04fc61..538b4e11a2 100644 --- a/sdk/src/client/node_api/core/routes.rs +++ b/sdk/src/client/node_api/core/routes.rs @@ -112,7 +112,7 @@ impl ClientInner { /// Returns the information of committee members at the given epoch index. If epoch index is not provided, the /// current committee members are returned. /// GET /api/core/v3/committee/?epochIndex - pub async fn get_committee(&self, epoch_index: impl Into>) -> Result { + pub async fn get_committee(&self, epoch_index: impl Into> + Send) -> Result { const PATH: &str = "api/core/v3/committee"; let epoch_index = epoch_index.into().map(|i| format!("epochIndex={i}")); diff --git a/sdk/src/types/block/basic.rs b/sdk/src/types/block/basic.rs index c52405f0a0..711bc040c8 100644 --- a/sdk/src/types/block/basic.rs +++ b/sdk/src/types/block/basic.rs @@ -12,7 +12,7 @@ use super::{ core::{verify_parents, BlockWrapper}, parent::{ShallowLikeParents, StrongParents, WeakParents}, payload::{OptionalPayload, Payload}, - protocol::ProtocolParameters, + protocol::{ProtocolParameters, WorkScore, WorkScoreStructure}, signature::{Ed25519Signature, Signature}, slot::{SlotCommitmentId, SlotIndex}, Block, BlockBuilder, Error, IssuerId, @@ -125,6 +125,37 @@ impl BasicBlock { pub fn burned_mana(&self) -> u64 { self.data.burned_mana } + + /// Returns the work score of a [`BasicBlock`]. + pub fn workscore(&self) -> u32 { + let workscore_structure = self.protocol_parameters().work_score_structure; + let workscore_bytes = workscore_structure.data_kilobyte * self.packed_len() as u32; + let mut workscore_kilobytes = workscore_bytes / 1024; + + workscore_kilobytes += self.workscore_header(workscore_structure); + workscore_kilobytes += self.data.workscore(workscore_structure); + workscore_kilobytes += self.workscore_signature(workscore_structure); + workscore_kilobytes + } +} + +impl WorkScore for BasicBlockData { + fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + // offset for block, plus missing parents, plus payload. + let mut score = workscore_structure.block; + + let min_strong_parents_threshold = workscore_structure.min_strong_parents_threshold as usize; + if self.strong_parents.len() < min_strong_parents_threshold { + let missing_parents_count = min_strong_parents_threshold - self.strong_parents.len(); + score += workscore_structure.missing_parent * missing_parents_count as u32; + } + + if let Some(payload) = &*self.payload { + score += payload.workscore(workscore_structure); + } + + score + } } impl Packable for BasicBlockData { diff --git a/sdk/src/types/block/core.rs b/sdk/src/types/block/core.rs index 97c1bf476a..46a128116a 100644 --- a/sdk/src/types/block/core.rs +++ b/sdk/src/types/block/core.rs @@ -16,6 +16,7 @@ use packable::{ use super::{ basic::{BasicBlock, BasicBlockData}, block_id::BlockHash, + protocol::{WorkScore, WorkScoreStructure}, signature::{Ed25519Signature, Signature}, slot::{SlotCommitmentId, SlotIndex}, validation::{ValidationBlock, ValidationBlockData}, @@ -280,6 +281,18 @@ impl BlockWrapper { self.pack_header(&mut SlicePacker::new(&mut bytes)).unwrap(); Blake2b256::digest(bytes).into() } + + #[inline(always)] + pub(crate) fn workscore_header(&self, _workscore_structure: WorkScoreStructure) -> u32 { + // Header has 0 work score. + 0 + } + + #[inline(always)] + pub(crate) fn workscore_signature(&self, workscore_structure: WorkScoreStructure) -> u32 { + // TODO: check + workscore_structure.signature_ed25519 + } } impl Block { @@ -364,6 +377,14 @@ impl Block { } } + /// Calculates the work score of a [`Block`]. + pub fn workscore(&self) -> u32 { + match self { + Self::Basic(b) => b.workscore(), + Self::Validation(b) => b.workscore(), + } + } + /// Returns the network id of a [`Block`]. #[inline(always)] pub fn network_id(&self) -> u64 { diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index e7ce979cf8..1c3969474a 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -21,6 +21,7 @@ pub(crate) use self::{ tagged_data::{TagLength, TaggedDataLength}, transaction::{ContextInputCount, InputCount, OutputCount}, }; +use super::protocol::{WorkScore, WorkScoreStructure}; use crate::types::block::{protocol::ProtocolParameters, Error}; /// A generic payload that can represent different types defining block payloads. @@ -63,6 +64,12 @@ impl Payload { } } +impl WorkScore for Payload { + fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + 0 + } +} + impl Packable for Payload { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; diff --git a/sdk/src/types/block/protocol.rs b/sdk/src/types/block/protocol.rs index 7c1a5cbfc3..abe4ea6a16 100644 --- a/sdk/src/types/block/protocol.rs +++ b/sdk/src/types/block/protocol.rs @@ -175,30 +175,30 @@ impl ProtocolParameters { #[packable(unpack_error = Error)] #[getset(get_copy = "pub")] pub struct WorkScoreStructure { - /// Modifier for network traffic per byte. - data_kilobyte: u32, + /// Modifier for network traffic per kilobyte. + pub(crate) data_kilobyte: u32, /// Modifier for work done to process a block. - block: u32, + pub(crate) block: u32, /// Modifier for slashing when there are insufficient strong tips. - missing_parent: u32, + pub(crate) missing_parent: u32, /// Modifier for loading UTXOs and performing mana calculations. - input: u32, + pub(crate) input: u32, /// Modifier for loading and checking the context input. - context_input: u32, + pub(crate) context_input: u32, /// Modifier for storing UTXOs. - output: u32, + pub(crate) output: u32, /// Modifier for calculations using native tokens. - native_token: u32, + pub(crate) native_token: u32, /// Modifier for storing staking features. - staking: u32, + pub(crate) staking: u32, /// Modifier for storing block issuer features. - block_issuer: u32, + pub(crate) block_issuer: u32, /// Modifier for accessing the account-based ledger to transform mana to Block Issuance Credits. - allotment: u32, + pub(crate) allotment: u32, /// Modifier for the block signature check. - signature_ed25519: u32, + pub(crate) signature_ed25519: u32, /// The minimum count of strong parents in a basic block. - min_strong_parents_threshold: u8, + pub(crate) min_strong_parents_threshold: u8, } impl Default for WorkScoreStructure { @@ -220,6 +220,10 @@ impl Default for WorkScoreStructure { } } +pub trait WorkScore { + fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32; +} + /// Defines the parameters used to calculate the Reference Mana Cost (RMC). #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Packable, CopyGetters)] #[cfg_attr( diff --git a/sdk/src/types/block/slot/index.rs b/sdk/src/types/block/slot/index.rs index 73e9fd2ba8..4d2d617aa4 100644 --- a/sdk/src/types/block/slot/index.rs +++ b/sdk/src/types/block/slot/index.rs @@ -60,7 +60,7 @@ impl SlotIndex { /// Gets the slot index of a unix timestamp. /// Slots are counted starting from `1` with `0` being reserved for times before the genesis. - pub fn from_timestamp(timestamp: u64, genesis_unix_timestamp: u64, slot_duration_in_seconds: u8) -> SlotIndex { + pub fn from_timestamp(timestamp: u64, genesis_unix_timestamp: u64, slot_duration_in_seconds: u8) -> Self { timestamp .checked_sub(genesis_unix_timestamp as u64) .map(|diff| (diff / slot_duration_in_seconds as u64) + 1) diff --git a/sdk/src/types/block/validation.rs b/sdk/src/types/block/validation.rs index ea0cadef11..11267e6c2e 100644 --- a/sdk/src/types/block/validation.rs +++ b/sdk/src/types/block/validation.rs @@ -11,7 +11,7 @@ use packable::{ use super::{ core::{verify_parents, BlockWrapper}, parent::{ShallowLikeParents, StrongParents, WeakParents}, - protocol::{ProtocolParameters, ProtocolParametersHash}, + protocol::{ProtocolParameters, ProtocolParametersHash, WorkScore, WorkScoreStructure}, signature::{Ed25519Signature, Signature}, slot::{SlotCommitmentId, SlotIndex}, Block, BlockBuilder, Error, IssuerId, @@ -112,6 +112,25 @@ impl ValidationBlock { pub fn protocol_parameters_hash(&self) -> ProtocolParametersHash { self.data.protocol_parameters_hash } + + /// Returns the work score of a [`ValidationBlock`]. + pub fn workscore(&self) -> u32 { + let workscore_structure = self.protocol_parameters().work_score_structure; + let workscore_bytes = workscore_structure.data_kilobyte * self.packed_len() as u32; + let mut workscore_kilobytes = workscore_bytes / 1024; + + workscore_kilobytes += self.workscore_header(workscore_structure); + workscore_kilobytes += self.data.workscore(workscore_structure); + workscore_kilobytes += self.workscore_signature(workscore_structure); + workscore_kilobytes + } +} + +impl WorkScore for ValidationBlockData { + fn workscore(&self, _workscore_structure: WorkScoreStructure) -> u32 { + // Validator blocks do not incur any work score as they do not burn mana + 0 + } } impl Packable for ValidationBlockData { From 29843e503333b3cac96d8ea69ae23414c880b753 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 15 Sep 2023 13:56:58 +0200 Subject: [PATCH 02/42] fix merge --- sdk/src/types/block/core/basic.rs | 18 ++---------------- sdk/src/types/block/core/mod.rs | 7 ++++--- sdk/src/types/block/core/validation.rs | 18 ++---------------- sdk/src/types/block/core/wrapper.rs | 16 ++++++++++++++-- sdk/src/types/block/payload/mod.rs | 13 ++++++++----- sdk/src/types/block/protocol.rs | 4 ---- 6 files changed, 30 insertions(+), 46 deletions(-) diff --git a/sdk/src/types/block/core/basic.rs b/sdk/src/types/block/core/basic.rs index 38e0633bc0..3ae7db6431 100644 --- a/sdk/src/types/block/core/basic.rs +++ b/sdk/src/types/block/core/basic.rs @@ -12,7 +12,7 @@ use crate::types::block::{ core::{verify_parents, Block}, parent::{ShallowLikeParents, StrongParents, WeakParents}, payload::{OptionalPayload, Payload}, - protocol::{ProtocolParameters, WorkScore, WorkScoreStructure}, + protocol::{ProtocolParameters, WorkScoreStructure}, Error, }; @@ -141,21 +141,7 @@ impl BasicBlock { } /// Returns the work score of a [`BasicBlock`]. - pub fn workscore(&self) -> u32 { - // let workscore_structure = self.protocol_parameters().work_score_structure; - // let workscore_bytes = workscore_structure.data_kilobyte * self.packed_len() as u32; - // let mut workscore_kilobytes = workscore_bytes / 1024; - - // workscore_kilobytes += self.workscore_header(workscore_structure); - // workscore_kilobytes += self.data.workscore(workscore_structure); - // workscore_kilobytes += self.workscore_signature(workscore_structure); - // workscore_kilobytes - todo!() - } -} - -impl WorkScore for BasicBlock { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + pub fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { // offset for block, plus missing parents, plus payload. let mut score = workscore_structure.block; diff --git a/sdk/src/types/block/core/mod.rs b/sdk/src/types/block/core/mod.rs index 17e84d3afc..2d223aecdf 100644 --- a/sdk/src/types/block/core/mod.rs +++ b/sdk/src/types/block/core/mod.rs @@ -21,6 +21,7 @@ pub use self::{ validation::{ValidationBlock, ValidationBlockBuilder}, wrapper::BlockWrapper, }; +use super::protocol::WorkScoreStructure; use crate::types::block::{ parent::{ShallowLikeParents, StrongParents, WeakParents}, protocol::{ProtocolParameters, ProtocolParametersHash}, @@ -105,10 +106,10 @@ impl Block { } /// Calculates the work score of a [`Block`]. - pub fn workscore(&self) -> u32 { + pub fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { match self { - Self::Basic(block) => block.workscore(), - Self::Validation(block) => block.workscore(), + Self::Basic(block) => block.workscore(workscore_structure), + Self::Validation(block) => block.workscore(workscore_structure), } } } diff --git a/sdk/src/types/block/core/validation.rs b/sdk/src/types/block/core/validation.rs index c16cd27975..be7fc44049 100644 --- a/sdk/src/types/block/core/validation.rs +++ b/sdk/src/types/block/core/validation.rs @@ -11,7 +11,7 @@ use packable::{ use crate::types::block::{ core::{verify_parents, Block}, parent::{ShallowLikeParents, StrongParents, WeakParents}, - protocol::{ProtocolParameters, ProtocolParametersHash, WorkScore, WorkScoreStructure}, + protocol::{ProtocolParameters, ProtocolParametersHash, WorkScoreStructure}, Error, }; @@ -146,21 +146,7 @@ impl ValidationBlock { } /// Returns the work score of a [`ValidationBlock`]. - pub fn workscore(&self) -> u32 { - // let workscore_structure = self.protocol_parameters().work_score_structure; - // let workscore_bytes = workscore_structure.data_kilobyte * self.packed_len() as u32; - // let mut workscore_kilobytes = workscore_bytes / 1024; - - // workscore_kilobytes += self.workscore_header(workscore_structure); - // workscore_kilobytes += self.data.workscore(workscore_structure); - // workscore_kilobytes += self.workscore_signature(workscore_structure); - // workscore_kilobytes - todo!() - } -} - -impl WorkScore for ValidationBlock { - fn workscore(&self, _workscore_structure: WorkScoreStructure) -> u32 { + pub fn workscore(&self, _workscore_structure: WorkScoreStructure) -> u32 { // Validator blocks do not incur any work score as they do not burn mana 0 } diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index e6f0fbe703..4f7b71df94 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -128,14 +128,26 @@ impl BlockWrapper { &self.signature } + /// Returns the work score of a [`BlockWrapper`]. + pub fn workscore(&self) -> u32 { + let workscore_structure = self.protocol_parameters().work_score_structure; + let workscore_bytes = workscore_structure.data_kilobyte * self.packed_len() as u32; + let mut workscore_kilobytes = workscore_bytes / 1024; + + workscore_kilobytes += self.workscore_header(workscore_structure); + workscore_kilobytes += self.block.workscore(workscore_structure); + workscore_kilobytes += self.workscore_signature(workscore_structure); + workscore_kilobytes + } + #[inline(always)] - pub(crate) fn workscore_header(&self, _workscore_structure: WorkScoreStructure) -> u32 { + fn workscore_header(&self, _workscore_structure: WorkScoreStructure) -> u32 { // Header has 0 work score. 0 } #[inline(always)] - pub(crate) fn workscore_signature(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn workscore_signature(&self, workscore_structure: WorkScoreStructure) -> u32 { // TODO: check workscore_structure.signature_ed25519 } diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index 1c3969474a..f7bbe434fb 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -21,7 +21,7 @@ pub(crate) use self::{ tagged_data::{TagLength, TaggedDataLength}, transaction::{ContextInputCount, InputCount, OutputCount}, }; -use super::protocol::{WorkScore, WorkScoreStructure}; +use super::protocol::WorkScoreStructure; use crate::types::block::{protocol::ProtocolParameters, Error}; /// A generic payload that can represent different types defining block payloads. @@ -62,11 +62,14 @@ impl Payload { Self::TaggedData(_) => TaggedDataPayload::KIND, } } -} -impl WorkScore for Payload { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { - 0 + /// Returns the work score of a `Payload`. + pub fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + // TODO: complete impl + match self { + Self::Transaction(transaction_payload) => todo!(), + Self::TaggedData(tagged_data_payload) => todo!(), + } } } diff --git a/sdk/src/types/block/protocol.rs b/sdk/src/types/block/protocol.rs index abe4ea6a16..fb42f5b356 100644 --- a/sdk/src/types/block/protocol.rs +++ b/sdk/src/types/block/protocol.rs @@ -220,10 +220,6 @@ impl Default for WorkScoreStructure { } } -pub trait WorkScore { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32; -} - /// Defines the parameters used to calculate the Reference Mana Cost (RMC). #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Packable, CopyGetters)] #[cfg_attr( From 5da94e4525e0d45c47df70a678fa3fce33d12949 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Wed, 20 Sep 2023 00:24:18 +0200 Subject: [PATCH 03/42] finish calculations --- sdk/src/types/block/core/basic.rs | 5 +--- sdk/src/types/block/core/validation.rs | 2 +- sdk/src/types/block/payload/mod.rs | 5 ++-- .../types/block/payload/tagged_data/mod.rs | 8 ++++- .../payload/transaction/essence/regular.rs | 30 +++++++++++++++++-- .../types/block/payload/transaction/mod.rs | 17 ++++++++++- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/sdk/src/types/block/core/basic.rs b/sdk/src/types/block/core/basic.rs index 3ae7db6431..b5815d72e6 100644 --- a/sdk/src/types/block/core/basic.rs +++ b/sdk/src/types/block/core/basic.rs @@ -142,19 +142,16 @@ impl BasicBlock { /// Returns the work score of a [`BasicBlock`]. pub fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { - // offset for block, plus missing parents, plus payload. + // `Block + Missing Parents Score + Payload Score` let mut score = workscore_structure.block; - let min_strong_parents_threshold = workscore_structure.min_strong_parents_threshold as usize; if self.strong_parents.len() < min_strong_parents_threshold { let missing_parents_count = min_strong_parents_threshold - self.strong_parents.len(); score += workscore_structure.missing_parent * missing_parents_count as u32; } - if let Some(payload) = &*self.payload { score += payload.workscore(workscore_structure); } - score } } diff --git a/sdk/src/types/block/core/validation.rs b/sdk/src/types/block/core/validation.rs index be7fc44049..e8b5b7f631 100644 --- a/sdk/src/types/block/core/validation.rs +++ b/sdk/src/types/block/core/validation.rs @@ -147,7 +147,7 @@ impl ValidationBlock { /// Returns the work score of a [`ValidationBlock`]. pub fn workscore(&self, _workscore_structure: WorkScoreStructure) -> u32 { - // Validator blocks do not incur any work score as they do not burn mana + // The work score of a validation block is `0`. 0 } } diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index f7bbe434fb..6c93ad9181 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -65,10 +65,9 @@ impl Payload { /// Returns the work score of a `Payload`. pub fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { - // TODO: complete impl match self { - Self::Transaction(transaction_payload) => todo!(), - Self::TaggedData(tagged_data_payload) => todo!(), + Self::Transaction(transaction_payload) => transaction_payload.workscore(workscore_structure), + Self::TaggedData(tagged_data_payload) => tagged_data_payload.workscore(workscore_structure), } } } diff --git a/sdk/src/types/block/payload/tagged_data/mod.rs b/sdk/src/types/block/payload/tagged_data/mod.rs index 7fd29988e1..0792350094 100644 --- a/sdk/src/types/block/payload/tagged_data/mod.rs +++ b/sdk/src/types/block/payload/tagged_data/mod.rs @@ -12,7 +12,7 @@ use packable::{ Packable, }; -use crate::types::block::{BlockWrapper, Error}; +use crate::types::block::{protocol::WorkScoreStructure, BlockWrapper, Error}; pub(crate) type TagLength = BoundedU8<{ *TaggedDataPayload::TAG_LENGTH_RANGE.start() }, { *TaggedDataPayload::TAG_LENGTH_RANGE.end() }>; @@ -58,6 +58,12 @@ impl TaggedDataPayload { pub fn data(&self) -> &[u8] { &self.data } + + /// Returns the work score of a `TaggedDataPayload`. + pub fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + // For tagged data payloads the work score is `0`. + 0 + } } impl core::fmt::Debug for TaggedDataPayload { diff --git a/sdk/src/types/block/payload/transaction/essence/regular.rs b/sdk/src/types/block/payload/transaction/essence/regular.rs index c21dfb0ddd..7f85a0b908 100644 --- a/sdk/src/types/block/payload/transaction/essence/regular.rs +++ b/sdk/src/types/block/payload/transaction/essence/regular.rs @@ -11,9 +11,9 @@ use crate::types::{ context_input::{ContextInput, CONTEXT_INPUT_COUNT_RANGE}, input::{Input, INPUT_COUNT_RANGE}, mana::{verify_mana_allotments_sum, ManaAllotment, ManaAllotments}, - output::{InputsCommitment, NativeTokens, Output, OUTPUT_COUNT_RANGE}, + output::{Feature, InputsCommitment, NativeTokens, Output, TokenScheme, OUTPUT_COUNT_RANGE}, payload::{OptionalPayload, Payload}, - protocol::ProtocolParameters, + protocol::{ProtocolParameters, WorkScoreStructure}, slot::SlotIndex, Error, }, @@ -272,6 +272,32 @@ impl RegularTransactionEssence { pub fn payload(&self) -> Option<&Payload> { self.payload.as_ref() } + + /// Returns the work score of a `RegularTransactionEssence`. + pub fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + let mut score = self.inputs().len() as u32 * workscore_structure.input; + score += self.context_inputs().len() as u32 * workscore_structure.context_input; + for output in self.outputs() { + score += workscore_structure.output; + if let Some(nts) = output.native_tokens() { + score += nts.len() as u32 * workscore_structure.native_token; + } + if matches!(output, Output::Foundry(foundry) if foundry.token_scheme().is_simple()) { + score += workscore_structure.native_token + } + if let Some(features) = output.features() { + for feature in features.iter() { + score += match feature { + Feature::BlockIssuer(_) => workscore_structure.block_issuer, + Feature::Staking(_) => workscore_structure.staking, + _ => 0, + } + } + } + } + score += self.mana_allotments().len() as u32 * workscore_structure.allotment; + score + } } fn verify_network_id(network_id: &u64, visitor: &ProtocolParameters) -> Result<(), Error> { diff --git a/sdk/src/types/block/payload/transaction/mod.rs b/sdk/src/types/block/payload/transaction/mod.rs index 8161ee7cb1..a292c3db84 100644 --- a/sdk/src/types/block/payload/transaction/mod.rs +++ b/sdk/src/types/block/payload/transaction/mod.rs @@ -14,7 +14,11 @@ pub use self::{ essence::{RegularTransactionEssence, RegularTransactionEssenceBuilder, TransactionEssence}, transaction_id::TransactionId, }; -use crate::types::block::{protocol::ProtocolParameters, unlock::Unlocks, Error}; +use crate::types::block::{ + protocol::{ProtocolParameters, WorkScoreStructure}, + unlock::{Unlock, Unlocks}, + Error, +}; /// A transaction to move funds. #[derive(Clone, Debug, Eq, PartialEq)] @@ -53,6 +57,17 @@ impl TransactionPayload { TransactionId::new(hasher.finalize().into()) } + + /// Returns the work score of a `TransactionPayload`. + pub fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + let mut score = self.essence().workscore(workscore_structure); + for unlock in self.unlocks.iter() { + if matches!(unlock, Unlock::Signature(_)) { + score += workscore_structure.signature_ed25519; + } + } + score + } } impl Packable for TransactionPayload { From 9d8d0cd9817e18da31cb650e946bf401b4146e4b Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Wed, 20 Sep 2023 10:39:48 +0200 Subject: [PATCH 04/42] nits --- sdk/src/types/block/core/wrapper.rs | 29 ++++++++-------------------- sdk/src/types/block/signature/mod.rs | 8 ++++++++ 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index 4f7b71df94..281615c471 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -129,27 +129,14 @@ impl BlockWrapper { } /// Returns the work score of a [`BlockWrapper`]. - pub fn workscore(&self) -> u32 { - let workscore_structure = self.protocol_parameters().work_score_structure; - let workscore_bytes = workscore_structure.data_kilobyte * self.packed_len() as u32; - let mut workscore_kilobytes = workscore_bytes / 1024; - - workscore_kilobytes += self.workscore_header(workscore_structure); - workscore_kilobytes += self.block.workscore(workscore_structure); - workscore_kilobytes += self.workscore_signature(workscore_structure); - workscore_kilobytes - } - - #[inline(always)] - fn workscore_header(&self, _workscore_structure: WorkScoreStructure) -> u32 { - // Header has 0 work score. - 0 - } - - #[inline(always)] - fn workscore_signature(&self, workscore_structure: WorkScoreStructure) -> u32 { - // TODO: check - workscore_structure.signature_ed25519 + pub fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + let mut score = workscore_structure.data_kilobyte * self.packed_len() as u32 / 1024; + + // FIXME: when #1264 is merged + // score += self.header.workscore(workscore_structure); + score += self.block.workscore(workscore_structure); + score += self.signature.workscore(workscore_structure); + score } pub(crate) fn pack_header(&self, packer: &mut P) -> Result<(), P::Error> { diff --git a/sdk/src/types/block/signature/mod.rs b/sdk/src/types/block/signature/mod.rs index c8086fe668..1cd136189a 100644 --- a/sdk/src/types/block/signature/mod.rs +++ b/sdk/src/types/block/signature/mod.rs @@ -6,6 +6,7 @@ mod ed25519; use derive_more::From; pub use self::ed25519::Ed25519Signature; +use super::protocol::WorkScoreStructure; use crate::types::block::Error; /// A `Signature` contains a signature which is used to unlock a transaction input. @@ -50,4 +51,11 @@ impl Signature { let Self::Ed25519(sig) = self; sig } + + /// Returns the work score of a `Signature`. + pub fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + match self { + Self::Ed25519(_) => workscore_structure.signature_ed25519, + } + } } From 5cd1d54b3031d4840ed68c3351b87f032f57fd1b Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Wed, 20 Sep 2023 10:50:25 +0200 Subject: [PATCH 05/42] merge import --- sdk/src/types/block/core/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/src/types/block/core/mod.rs b/sdk/src/types/block/core/mod.rs index 2d223aecdf..d11e3cabc7 100644 --- a/sdk/src/types/block/core/mod.rs +++ b/sdk/src/types/block/core/mod.rs @@ -21,10 +21,9 @@ pub use self::{ validation::{ValidationBlock, ValidationBlockBuilder}, wrapper::BlockWrapper, }; -use super::protocol::WorkScoreStructure; use crate::types::block::{ parent::{ShallowLikeParents, StrongParents, WeakParents}, - protocol::{ProtocolParameters, ProtocolParametersHash}, + protocol::{ProtocolParameters, ProtocolParametersHash, WorkScoreStructure}, Error, }; From 00ddccfb0c0e89dd2bd231615edde7e18d3f4d51 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Wed, 20 Sep 2023 16:41:14 +0200 Subject: [PATCH 06/42] nits --- sdk/src/types/block/core/mod.rs | 4 ++-- sdk/src/types/block/core/wrapper.rs | 1 + sdk/src/types/block/payload/tagged_data/mod.rs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sdk/src/types/block/core/mod.rs b/sdk/src/types/block/core/mod.rs index 375f51b3ee..62442acdc1 100644 --- a/sdk/src/types/block/core/mod.rs +++ b/sdk/src/types/block/core/mod.rs @@ -109,8 +109,8 @@ impl Block { impl WorkScore for Block { fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { match self { - Self::Basic(block) => block.workscore(workscore_structure), - Self::Validation(block) => block.workscore(workscore_structure), + Self::Basic(basic) => basic.workscore(workscore_structure), + Self::Validation(validation) => validation.workscore(workscore_structure), } } } diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index 85b1b39680..fbba3e5228 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -53,6 +53,7 @@ impl BlockHeader { impl WorkScore for BlockHeader { fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + // The work score of a block header is `0`. 0 } } diff --git a/sdk/src/types/block/payload/tagged_data/mod.rs b/sdk/src/types/block/payload/tagged_data/mod.rs index 6098e339da..94c759770a 100644 --- a/sdk/src/types/block/payload/tagged_data/mod.rs +++ b/sdk/src/types/block/payload/tagged_data/mod.rs @@ -65,7 +65,7 @@ impl TaggedDataPayload { impl WorkScore for TaggedDataPayload { fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { - // For tagged data payloads the work score is `0`. + // The work score of a tagged data payload is `0`. 0 } } From ab3b9fee17939b53b98207e329b95cb3258c29b4 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Sun, 8 Oct 2023 21:13:17 +0200 Subject: [PATCH 07/42] rename trait fn --- sdk/src/types/block/core/basic.rs | 4 ++-- sdk/src/types/block/core/mod.rs | 6 +++--- sdk/src/types/block/core/validation.rs | 2 +- sdk/src/types/block/core/wrapper.rs | 10 +++++----- sdk/src/types/block/payload/mod.rs | 6 +++--- sdk/src/types/block/payload/tagged_data/mod.rs | 2 +- .../types/block/payload/transaction/essence/regular.rs | 2 +- sdk/src/types/block/payload/transaction/mod.rs | 4 ++-- sdk/src/types/block/protocol.rs | 2 +- sdk/src/types/block/signature/mod.rs | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/sdk/src/types/block/core/basic.rs b/sdk/src/types/block/core/basic.rs index f223274ab0..6060efd230 100644 --- a/sdk/src/types/block/core/basic.rs +++ b/sdk/src/types/block/core/basic.rs @@ -142,7 +142,7 @@ impl BasicBlock { } impl WorkScore for BasicBlock { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { let mut score = workscore_structure.block; let min_strong_parents_threshold = workscore_structure.min_strong_parents_threshold as usize; if self.strong_parents.len() < min_strong_parents_threshold { @@ -150,7 +150,7 @@ impl WorkScore for BasicBlock { score += workscore_structure.missing_parent * missing_parents_count as u32; } if let Some(payload) = &*self.payload { - score += payload.workscore(workscore_structure); + score += payload.work_score(workscore_structure); } score } diff --git a/sdk/src/types/block/core/mod.rs b/sdk/src/types/block/core/mod.rs index 62442acdc1..a37916c4fc 100644 --- a/sdk/src/types/block/core/mod.rs +++ b/sdk/src/types/block/core/mod.rs @@ -107,10 +107,10 @@ impl Block { } impl WorkScore for Block { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { match self { - Self::Basic(basic) => basic.workscore(workscore_structure), - Self::Validation(validation) => validation.workscore(workscore_structure), + Self::Basic(basic) => basic.work_score(workscore_structure), + Self::Validation(validation) => validation.work_score(workscore_structure), } } } diff --git a/sdk/src/types/block/core/validation.rs b/sdk/src/types/block/core/validation.rs index bbd6ee7f22..2fdbbe6db9 100644 --- a/sdk/src/types/block/core/validation.rs +++ b/sdk/src/types/block/core/validation.rs @@ -147,7 +147,7 @@ impl ValidationBlock { } impl WorkScore for ValidationBlock { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { // The work score of a validation block is `0`. 0 } diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index fbba3e5228..042e747ec4 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -52,7 +52,7 @@ impl BlockHeader { } impl WorkScore for BlockHeader { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { // The work score of a block header is `0`. 0 } @@ -254,11 +254,11 @@ impl BlockWrapper { } impl WorkScore for BlockWrapper { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { let mut score = workscore_structure.data_kilobyte * self.packed_len() as u32 / 1024; - score += self.header.workscore(workscore_structure); - score += self.block.workscore(workscore_structure); - score += self.signature.workscore(workscore_structure); + score += self.header.work_score(workscore_structure); + score += self.block.work_score(workscore_structure); + score += self.signature.work_score(workscore_structure); score } } diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index 52191dd5ae..9dcb948abf 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -65,10 +65,10 @@ impl Payload { } impl WorkScore for Payload { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { match self { - Self::Transaction(transaction_payload) => transaction_payload.workscore(workscore_structure), - Self::TaggedData(tagged_data_payload) => tagged_data_payload.workscore(workscore_structure), + Self::Transaction(transaction_payload) => transaction_payload.work_score(workscore_structure), + Self::TaggedData(tagged_data_payload) => tagged_data_payload.work_score(workscore_structure), } } } diff --git a/sdk/src/types/block/payload/tagged_data/mod.rs b/sdk/src/types/block/payload/tagged_data/mod.rs index 94c759770a..cbdb282cdc 100644 --- a/sdk/src/types/block/payload/tagged_data/mod.rs +++ b/sdk/src/types/block/payload/tagged_data/mod.rs @@ -64,7 +64,7 @@ impl TaggedDataPayload { } impl WorkScore for TaggedDataPayload { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { // The work score of a tagged data payload is `0`. 0 } diff --git a/sdk/src/types/block/payload/transaction/essence/regular.rs b/sdk/src/types/block/payload/transaction/essence/regular.rs index a12e6259cd..390acf2bf0 100644 --- a/sdk/src/types/block/payload/transaction/essence/regular.rs +++ b/sdk/src/types/block/payload/transaction/essence/regular.rs @@ -275,7 +275,7 @@ impl RegularTransactionEssence { } impl WorkScore for RegularTransactionEssence { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { let mut score = self.inputs().len() as u32 * workscore_structure.input; score += self.context_inputs().len() as u32 * workscore_structure.context_input; for output in self.outputs() { diff --git a/sdk/src/types/block/payload/transaction/mod.rs b/sdk/src/types/block/payload/transaction/mod.rs index 5e665170bc..2b3d562be6 100644 --- a/sdk/src/types/block/payload/transaction/mod.rs +++ b/sdk/src/types/block/payload/transaction/mod.rs @@ -60,8 +60,8 @@ impl TransactionPayload { } impl WorkScore for TransactionPayload { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { - let mut score = self.essence().workscore(workscore_structure); + fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { + let mut score = self.essence().work_score(workscore_structure); for unlock in self.unlocks.iter() { if matches!(unlock, Unlock::Signature(_)) { score += workscore_structure.signature_ed25519; diff --git a/sdk/src/types/block/protocol.rs b/sdk/src/types/block/protocol.rs index f90d50f161..2d92bbc373 100644 --- a/sdk/src/types/block/protocol.rs +++ b/sdk/src/types/block/protocol.rs @@ -226,7 +226,7 @@ impl Default for WorkScoreStructure { /// A trait to facilitate the computation of the work score of a block, which is central to mana cost calculation. pub trait WorkScore { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32; + fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32; } /// Defines the parameters used to calculate the Reference Mana Cost (RMC). diff --git a/sdk/src/types/block/signature/mod.rs b/sdk/src/types/block/signature/mod.rs index 6290258520..062288a5a6 100644 --- a/sdk/src/types/block/signature/mod.rs +++ b/sdk/src/types/block/signature/mod.rs @@ -54,7 +54,7 @@ impl Signature { } impl WorkScore for Signature { - fn workscore(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { match self { Self::Ed25519(_) => workscore_structure.signature_ed25519, } From 830ff47b1995ce8d69d4a8af33d9b78c52020848 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Mon, 9 Oct 2023 16:08:20 +0200 Subject: [PATCH 08/42] update work score computations --- sdk/src/types/block/core/basic.rs | 10 +++---- sdk/src/types/block/core/mod.rs | 6 ++-- sdk/src/types/block/core/validation.rs | 2 +- sdk/src/types/block/core/wrapper.rs | 12 ++++---- sdk/src/types/block/output/account.rs | 11 ++++++- sdk/src/types/block/output/basic.rs | 10 ++++++- sdk/src/types/block/output/delegation.rs | 8 ++++- sdk/src/types/block/output/feature/mod.rs | 20 ++++++++++++- sdk/src/types/block/output/foundry.rs | 16 +++++++++- sdk/src/types/block/output/mod.rs | 26 ++++++++++++++++- sdk/src/types/block/output/native_token.rs | 13 ++++++++- sdk/src/types/block/output/nft.rs | 11 ++++++- sdk/src/types/block/payload/mod.rs | 15 ++++++---- .../types/block/payload/tagged_data/mod.rs | 8 ++--- .../payload/transaction/essence/regular.rs | 29 ++++--------------- .../types/block/payload/transaction/mod.rs | 13 ++++----- sdk/src/types/block/protocol.rs | 2 +- sdk/src/types/block/unlock/mod.rs | 11 +++++++ 18 files changed, 158 insertions(+), 65 deletions(-) diff --git a/sdk/src/types/block/core/basic.rs b/sdk/src/types/block/core/basic.rs index 49f75e5434..f6512184e2 100644 --- a/sdk/src/types/block/core/basic.rs +++ b/sdk/src/types/block/core/basic.rs @@ -157,15 +157,15 @@ impl BasicBlock { } impl WorkScore for BasicBlock { - fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { - let mut score = workscore_structure.block; - let min_strong_parents_threshold = workscore_structure.min_strong_parents_threshold as usize; + fn work_score(&self, work_score_struct: WorkScoreStructure) -> u32 { + let mut score = work_score_struct.block; + let min_strong_parents_threshold = work_score_struct.min_strong_parents_threshold as usize; if self.strong_parents.len() < min_strong_parents_threshold { let missing_parents_count = min_strong_parents_threshold - self.strong_parents.len(); - score += workscore_structure.missing_parent * missing_parents_count as u32; + score += work_score_struct.missing_parent * missing_parents_count as u32; } if let Some(payload) = &*self.payload { - score += payload.work_score(workscore_structure); + score += payload.work_score(work_score_struct); } score } diff --git a/sdk/src/types/block/core/mod.rs b/sdk/src/types/block/core/mod.rs index c0a839ba77..b38d338d0d 100644 --- a/sdk/src/types/block/core/mod.rs +++ b/sdk/src/types/block/core/mod.rs @@ -132,10 +132,10 @@ impl Block { } impl WorkScore for Block { - fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, work_score_struct: WorkScoreStructure) -> u32 { match self { - Self::Basic(basic) => basic.work_score(workscore_structure), - Self::Validation(validation) => validation.work_score(workscore_structure), + Self::Basic(basic) => basic.work_score(work_score_struct), + Self::Validation(validation) => validation.work_score(work_score_struct), } } } diff --git a/sdk/src/types/block/core/validation.rs b/sdk/src/types/block/core/validation.rs index 8157a4f840..246e61e59e 100644 --- a/sdk/src/types/block/core/validation.rs +++ b/sdk/src/types/block/core/validation.rs @@ -162,7 +162,7 @@ impl ValidationBlock { } impl WorkScore for ValidationBlock { - fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, _: WorkScoreStructure) -> u32 { // The work score of a validation block is `0`. 0 } diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index 7252c6c40e..95b62f9356 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -110,7 +110,7 @@ impl BlockHeader { } impl WorkScore for BlockHeader { - fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { + fn work_score(&self, _: WorkScoreStructure) -> u32 { // The work score of a block header is `0`. 0 } @@ -298,11 +298,11 @@ impl BlockWrapper { } impl WorkScore for BlockWrapper { - fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { - let mut score = workscore_structure.data_byte * self.packed_len() as u32 / 1024; - score += self.header.work_score(workscore_structure); - score += self.block.work_score(workscore_structure); - score += self.signature.work_score(workscore_structure); + fn work_score(&self, work_score_struct: WorkScoreStructure) -> u32 { + let mut score = work_score_struct.data_byte * self.packed_len() as u32 / 1024; + score += self.header.work_score(work_score_struct); + score += self.block.work_score(work_score_struct); + score += self.signature.work_score(work_score_struct); score } } diff --git a/sdk/src/types/block/output/account.rs b/sdk/src/types/block/output/account.rs index f4ba0d9a7d..213fee9548 100644 --- a/sdk/src/types/block/output/account.rs +++ b/sdk/src/types/block/output/account.rs @@ -25,7 +25,7 @@ use crate::types::{ NativeTokens, Output, OutputBuilderAmount, OutputId, Rent, RentStructure, StateTransitionError, StateTransitionVerifier, }, - protocol::ProtocolParameters, + protocol::{ProtocolParameters, WorkScore, WorkScoreStructure}, semantic::{TransactionFailureReason, ValidationContext}, unlock::Unlock, Error, @@ -651,6 +651,15 @@ impl StateTransitionVerifier for AccountOutput { } } +impl WorkScore for AccountOutput { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + let native_token_score = self.native_tokens().work_score(work_score_params); + let features_score = self.features().work_score(work_score_params); + let immutable_features_score = self.immutable_features().work_score(work_score_params); + work_score_params.output + native_token_score + features_score + immutable_features_score + } +} + impl Packable for AccountOutput { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; diff --git a/sdk/src/types/block/output/basic.rs b/sdk/src/types/block/output/basic.rs index d557b28b1f..8a1df74e89 100644 --- a/sdk/src/types/block/output/basic.rs +++ b/sdk/src/types/block/output/basic.rs @@ -16,7 +16,7 @@ use crate::types::{ verify_output_amount_min, verify_output_amount_packable, verify_output_amount_supply, NativeToken, NativeTokens, Output, OutputBuilderAmount, OutputId, Rent, RentStructure, }, - protocol::ProtocolParameters, + protocol::{ProtocolParameters, WorkScore, WorkScoreStructure}, semantic::{TransactionFailureReason, ValidationContext}, unlock::Unlock, Error, @@ -323,6 +323,14 @@ impl BasicOutput { } } +impl WorkScore for BasicOutput { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + let native_token_score = self.native_tokens().work_score(work_score_params); + let features_score = self.features().work_score(work_score_params); + work_score_params.output + native_token_score + features_score + } +} + fn verify_unlock_conditions(unlock_conditions: &UnlockConditions) -> Result<(), Error> { if VERIFY { if unlock_conditions.address().is_none() { diff --git a/sdk/src/types/block/output/delegation.rs b/sdk/src/types/block/output/delegation.rs index 0c2dda387e..9e3ea05ed6 100644 --- a/sdk/src/types/block/output/delegation.rs +++ b/sdk/src/types/block/output/delegation.rs @@ -21,7 +21,7 @@ use crate::types::{ verify_output_amount_min, verify_output_amount_packable, verify_output_amount_supply, Output, OutputBuilderAmount, OutputId, Rent, RentStructure, StateTransitionError, StateTransitionVerifier, }, - protocol::ProtocolParameters, + protocol::{ProtocolParameters, WorkScore, WorkScoreStructure}, semantic::{TransactionFailureReason, ValidationContext}, slot::EpochIndex, unlock::Unlock, @@ -405,6 +405,12 @@ impl StateTransitionVerifier for DelegationOutput { } } +impl WorkScore for DelegationOutput { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + work_score_params.output + } +} + impl Packable for DelegationOutput { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; diff --git a/sdk/src/types/block/output/feature/mod.rs b/sdk/src/types/block/output/feature/mod.rs index 33904fe62e..8a66a5aef0 100644 --- a/sdk/src/types/block/output/feature/mod.rs +++ b/sdk/src/types/block/output/feature/mod.rs @@ -28,7 +28,11 @@ pub use self::{ staking::StakingFeature, tag::TagFeature, }; -use crate::types::block::{create_bitflags, Error}; +use crate::types::block::{ + create_bitflags, + protocol::{WorkScore, WorkScoreStructure}, + Error, +}; /// #[derive(Clone, Eq, PartialEq, Hash, From, Packable)] @@ -313,6 +317,20 @@ impl Features { } } +impl WorkScore for Features { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + let features_score = self + .iter() + .map(|f| match f { + Feature::BlockIssuer(_) => work_score_params.block_issuer, + Feature::Staking(_) => work_score_params.staking, + _ => 0, + }) + .sum::(); + features_score + } +} + #[inline] fn verify_unique_sorted(features: &[Feature], _: &()) -> Result<(), Error> { if VERIFY && !is_unique_sorted(features.iter().map(Feature::kind)) { diff --git a/sdk/src/types/block/output/foundry.rs b/sdk/src/types/block/output/foundry.rs index 90a042eade..97e52f111f 100644 --- a/sdk/src/types/block/output/foundry.rs +++ b/sdk/src/types/block/output/foundry.rs @@ -25,7 +25,7 @@ use crate::types::{ NativeTokens, Output, OutputBuilderAmount, OutputId, Rent, RentStructure, StateTransitionError, StateTransitionVerifier, TokenId, TokenScheme, }, - protocol::ProtocolParameters, + protocol::{ProtocolParameters, WorkScore, WorkScoreStructure}, semantic::{TransactionFailureReason, ValidationContext}, unlock::Unlock, Error, @@ -598,6 +598,20 @@ impl StateTransitionVerifier for FoundryOutput { } } +impl WorkScore for FoundryOutput { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + let native_token_score = self.native_tokens().work_score(work_score_params); + let features_score = self.features().work_score(work_score_params); + let immutable_features_score = self.immutable_features().work_score(work_score_params); + let token_scheme_score = self + .token_scheme() + .is_simple() + .then_some(work_score_params.native_token) + .unwrap_or(0); + work_score_params.output + native_token_score + features_score + immutable_features_score + token_scheme_score + } +} + impl Packable for FoundryOutput { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; diff --git a/sdk/src/types/block/output/mod.rs b/sdk/src/types/block/output/mod.rs index c9829eb5a0..3ed03c9b4d 100644 --- a/sdk/src/types/block/output/mod.rs +++ b/sdk/src/types/block/output/mod.rs @@ -58,7 +58,7 @@ pub use self::{ token_scheme::{SimpleTokenScheme, TokenScheme}, unlock_condition::{UnlockCondition, UnlockConditions}, }; -use super::protocol::ProtocolParameters; +use super::protocol::{ProtocolParameters, WorkScore, WorkScoreStructure}; use crate::types::block::{address::Address, semantic::ValidationContext, slot::SlotIndex, Error}; /// The maximum number of outputs of a transaction. @@ -474,6 +474,30 @@ impl Rent for Output { } } +impl WorkScore for Output { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + match self { + Self::Basic(basic) => basic.work_score(work_score_params), + Self::Account(account) => account.work_score(work_score_params), + Self::Foundry(foundry) => foundry.work_score(work_score_params), + Self::Nft(nft) => nft.work_score(work_score_params), + Self::Delegation(delegation) => delegation.work_score(work_score_params), + } + } +} + +impl WorkScore for [T; N] { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + self.as_slice().work_score(work_score_params) + } +} + +impl WorkScore for [T] { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + self.iter().map(|o| o.work_score(work_score_params)).sum() + } +} + pub(crate) fn verify_output_amount_min(amount: u64) -> Result<(), Error> { if amount < Output::AMOUNT_MIN { Err(Error::InvalidOutputAmount(amount)) diff --git a/sdk/src/types/block/output/native_token.rs b/sdk/src/types/block/output/native_token.rs index d3806f7523..69c5ec72f9 100644 --- a/sdk/src/types/block/output/native_token.rs +++ b/sdk/src/types/block/output/native_token.rs @@ -12,7 +12,11 @@ use iterator_sorted::is_unique_sorted; use packable::{bounded::BoundedU8, prefix::BoxedSlicePrefix, Packable}; use primitive_types::U256; -use crate::types::block::{output::foundry::FoundryId, Error}; +use crate::types::block::{ + output::foundry::FoundryId, + protocol::{WorkScore, WorkScoreStructure}, + Error, +}; impl_id!(pub TokenId, 38, "Unique identifiers of native tokens. The TokenId of native tokens minted by a specific foundry is the same as the FoundryId."); @@ -247,6 +251,13 @@ impl NativeTokens { } } +// TODO: should we also impl `WorkScore` for `NativeToken` for plain consistency? +impl WorkScore for NativeTokens { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + self.len() as u32 * work_score_params.native_token + } +} + #[inline] fn verify_unique_sorted(native_tokens: &[NativeToken], _: &()) -> Result<(), Error> { if VERIFY && !is_unique_sorted(native_tokens.iter().map(NativeToken::token_id)) { diff --git a/sdk/src/types/block/output/nft.rs b/sdk/src/types/block/output/nft.rs index 6e8430e44e..d07cea4194 100644 --- a/sdk/src/types/block/output/nft.rs +++ b/sdk/src/types/block/output/nft.rs @@ -22,7 +22,7 @@ use crate::types::{ NativeTokens, Output, OutputBuilderAmount, OutputId, Rent, RentStructure, StateTransitionError, StateTransitionVerifier, }, - protocol::ProtocolParameters, + protocol::{ProtocolParameters, WorkScore, WorkScoreStructure}, semantic::{TransactionFailureReason, ValidationContext}, unlock::Unlock, Error, @@ -461,6 +461,15 @@ impl StateTransitionVerifier for NftOutput { } } +impl WorkScore for NftOutput { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + let native_token_score = self.native_tokens().work_score(work_score_params); + let features_score = self.features().work_score(work_score_params); + let immutable_features_score = self.immutable_features().work_score(work_score_params); + work_score_params.output + native_token_score + features_score + immutable_features_score + } +} + impl Packable for NftOutput { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index 2bb7bb4fc3..325e3be27a 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -7,7 +7,7 @@ pub mod tagged_data; pub mod transaction; use alloc::boxed::Box; -use core::ops::Deref; +use core::{mem::size_of, ops::Deref}; use packable::{ error::{UnpackError, UnpackErrorExt}, @@ -65,11 +65,14 @@ impl Payload { } impl WorkScore for Payload { - fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { - match self { - Self::Transaction(transaction_payload) => transaction_payload.work_score(workscore_structure), - Self::TaggedData(tagged_data_payload) => tagged_data_payload.work_score(workscore_structure), - } + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + // 1 byte for the payload kind + let score = size_of::() as u32 + + match self { + Self::Transaction(transaction_payload) => transaction_payload.work_score(work_score_params), + Self::TaggedData(tagged_data_payload) => tagged_data_payload.work_score(work_score_params), + }; + score } } diff --git a/sdk/src/types/block/payload/tagged_data/mod.rs b/sdk/src/types/block/payload/tagged_data/mod.rs index 6cc48b73eb..27442b0ad0 100644 --- a/sdk/src/types/block/payload/tagged_data/mod.rs +++ b/sdk/src/types/block/payload/tagged_data/mod.rs @@ -9,7 +9,7 @@ use core::ops::RangeInclusive; use packable::{ bounded::{BoundedU32, BoundedU8}, prefix::BoxedSlicePrefix, - Packable, + Packable, PackableExt, }; use crate::types::block::{ @@ -64,9 +64,9 @@ impl TaggedDataPayload { } impl WorkScore for TaggedDataPayload { - fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { - // The work score of a tagged data payload is `0`. - 0 + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + let size_score = self.packed_len() as u32 * work_score_params.data_byte; + size_score } } diff --git a/sdk/src/types/block/payload/transaction/essence/regular.rs b/sdk/src/types/block/payload/transaction/essence/regular.rs index 390acf2bf0..26bc83dcdf 100644 --- a/sdk/src/types/block/payload/transaction/essence/regular.rs +++ b/sdk/src/types/block/payload/transaction/essence/regular.rs @@ -275,29 +275,12 @@ impl RegularTransactionEssence { } impl WorkScore for RegularTransactionEssence { - fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { - let mut score = self.inputs().len() as u32 * workscore_structure.input; - score += self.context_inputs().len() as u32 * workscore_structure.context_input; - for output in self.outputs() { - score += workscore_structure.output; - if let Some(nts) = output.native_tokens() { - score += nts.len() as u32 * workscore_structure.native_token; - } - if matches!(output, Output::Foundry(foundry) if foundry.token_scheme().is_simple()) { - score += workscore_structure.native_token - } - if let Some(features) = output.features() { - for feature in features.iter() { - score += match feature { - Feature::BlockIssuer(_) => workscore_structure.block_issuer, - Feature::Staking(_) => workscore_structure.staking, - _ => 0, - } - } - } - } - score += self.mana_allotments().len() as u32 * workscore_structure.allotment; - score + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + let input_score = self.inputs().len() as u32 * work_score_params.input; + let context_input_score = self.context_inputs().len() as u32 * work_score_params.context_input; + let outputs_score = self.outputs().work_score(work_score_params); + let allotment_score = self.mana_allotments().len() as u32 * work_score_params.allotment; + input_score + context_input_score + outputs_score + allotment_score } } diff --git a/sdk/src/types/block/payload/transaction/mod.rs b/sdk/src/types/block/payload/transaction/mod.rs index ffa0a0b1c4..66be7428a7 100644 --- a/sdk/src/types/block/payload/transaction/mod.rs +++ b/sdk/src/types/block/payload/transaction/mod.rs @@ -60,14 +60,11 @@ impl TransactionPayload { } impl WorkScore for TransactionPayload { - fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32 { - let mut score = self.essence().work_score(workscore_structure); - for unlock in self.unlocks.iter() { - if matches!(unlock, Unlock::Signature(_)) { - score += workscore_structure.signature_ed25519; - } - } - score + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + let size_score = self.packed_len() as u32 * work_score_params.data_byte; + let essence_score = self.essence().work_score(work_score_params); + let unlocks_score = self.unlocks().work_score(work_score_params); + size_score + essence_score + unlocks_score } } diff --git a/sdk/src/types/block/protocol.rs b/sdk/src/types/block/protocol.rs index ce09a859d2..21e8ac59e7 100644 --- a/sdk/src/types/block/protocol.rs +++ b/sdk/src/types/block/protocol.rs @@ -238,7 +238,7 @@ impl Default for WorkScoreStructure { /// A trait to facilitate the computation of the work score of a block, which is central to mana cost calculation. pub trait WorkScore { - fn work_score(&self, workscore_structure: WorkScoreStructure) -> u32; + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32; } /// Defines the parameters used to calculate the Reference Mana Cost (RMC). diff --git a/sdk/src/types/block/unlock/mod.rs b/sdk/src/types/block/unlock/mod.rs index bbd74b8f56..5852f585f9 100644 --- a/sdk/src/types/block/unlock/mod.rs +++ b/sdk/src/types/block/unlock/mod.rs @@ -14,6 +14,7 @@ use hashbrown::HashSet; use packable::{bounded::BoundedU16, prefix::BoxedSlicePrefix, Packable}; pub use self::{account::AccountUnlock, nft::NftUnlock, reference::ReferenceUnlock, signature::SignatureUnlock}; +use super::protocol::{WorkScore, WorkScoreStructure}; use crate::types::block::{ input::{INPUT_COUNT_MAX, INPUT_COUNT_RANGE, INPUT_INDEX_MAX}, Error, @@ -109,6 +110,16 @@ impl Unlocks { } } +impl WorkScore for Unlocks { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + let signature_score = self + .iter() + .filter_map(|u| matches!(u, Unlock::Signature(_)).then_some(work_score_params.signature_ed25519)) + .sum::(); + signature_score + } +} + fn verify_unlocks(unlocks: &[Unlock], _: &()) -> Result<(), Error> { if VERIFY { let mut seen_signatures = HashSet::new(); From 6306da5f593343d00aaca4c5bbb6955c6709a7b7 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Mon, 9 Oct 2023 16:11:58 +0200 Subject: [PATCH 09/42] nit --- sdk/src/types/block/output/account.rs | 4 ++-- sdk/src/types/block/output/basic.rs | 4 ++-- sdk/src/types/block/output/foundry.rs | 4 ++-- sdk/src/types/block/output/nft.rs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sdk/src/types/block/output/account.rs b/sdk/src/types/block/output/account.rs index 213fee9548..609414bd38 100644 --- a/sdk/src/types/block/output/account.rs +++ b/sdk/src/types/block/output/account.rs @@ -653,10 +653,10 @@ impl StateTransitionVerifier for AccountOutput { impl WorkScore for AccountOutput { fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { - let native_token_score = self.native_tokens().work_score(work_score_params); + let native_tokens_score = self.native_tokens().work_score(work_score_params); let features_score = self.features().work_score(work_score_params); let immutable_features_score = self.immutable_features().work_score(work_score_params); - work_score_params.output + native_token_score + features_score + immutable_features_score + work_score_params.output + native_tokens_score + features_score + immutable_features_score } } diff --git a/sdk/src/types/block/output/basic.rs b/sdk/src/types/block/output/basic.rs index 8a1df74e89..05d2b5bdd4 100644 --- a/sdk/src/types/block/output/basic.rs +++ b/sdk/src/types/block/output/basic.rs @@ -325,9 +325,9 @@ impl BasicOutput { impl WorkScore for BasicOutput { fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { - let native_token_score = self.native_tokens().work_score(work_score_params); + let native_tokens_score = self.native_tokens().work_score(work_score_params); let features_score = self.features().work_score(work_score_params); - work_score_params.output + native_token_score + features_score + work_score_params.output + native_tokens_score + features_score } } diff --git a/sdk/src/types/block/output/foundry.rs b/sdk/src/types/block/output/foundry.rs index 97e52f111f..c64f7a5e22 100644 --- a/sdk/src/types/block/output/foundry.rs +++ b/sdk/src/types/block/output/foundry.rs @@ -600,7 +600,7 @@ impl StateTransitionVerifier for FoundryOutput { impl WorkScore for FoundryOutput { fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { - let native_token_score = self.native_tokens().work_score(work_score_params); + let native_tokens_score = self.native_tokens().work_score(work_score_params); let features_score = self.features().work_score(work_score_params); let immutable_features_score = self.immutable_features().work_score(work_score_params); let token_scheme_score = self @@ -608,7 +608,7 @@ impl WorkScore for FoundryOutput { .is_simple() .then_some(work_score_params.native_token) .unwrap_or(0); - work_score_params.output + native_token_score + features_score + immutable_features_score + token_scheme_score + work_score_params.output + native_tokens_score + features_score + immutable_features_score + token_scheme_score } } diff --git a/sdk/src/types/block/output/nft.rs b/sdk/src/types/block/output/nft.rs index d07cea4194..74aee57ef6 100644 --- a/sdk/src/types/block/output/nft.rs +++ b/sdk/src/types/block/output/nft.rs @@ -463,10 +463,10 @@ impl StateTransitionVerifier for NftOutput { impl WorkScore for NftOutput { fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { - let native_token_score = self.native_tokens().work_score(work_score_params); + let native_tokens_score = self.native_tokens().work_score(work_score_params); let features_score = self.features().work_score(work_score_params); let immutable_features_score = self.immutable_features().work_score(work_score_params); - work_score_params.output + native_token_score + features_score + immutable_features_score + work_score_params.output + native_tokens_score + features_score + immutable_features_score } } From 7e8a2048c85bb0cf9841b58bb52767b9f6d856c0 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Mon, 9 Oct 2023 16:59:24 +0200 Subject: [PATCH 10/42] move work score types into own module --- sdk/src/types/block/core/basic.rs | 21 ++--- sdk/src/types/block/mana/computation.rs | 7 ++ sdk/src/types/block/mana/mod.rs | 6 +- sdk/src/types/block/output/mod.rs | 12 --- .../block/{protocol.rs => protocol/mod.rs} | 62 +------------- sdk/src/types/block/protocol/work_score.rs | 84 +++++++++++++++++++ 6 files changed, 110 insertions(+), 82 deletions(-) create mode 100644 sdk/src/types/block/mana/computation.rs rename sdk/src/types/block/{protocol.rs => protocol/mod.rs} (84%) create mode 100644 sdk/src/types/block/protocol/work_score.rs diff --git a/sdk/src/types/block/core/basic.rs b/sdk/src/types/block/core/basic.rs index f6512184e2..b6cde73360 100644 --- a/sdk/src/types/block/core/basic.rs +++ b/sdk/src/types/block/core/basic.rs @@ -158,16 +158,17 @@ impl BasicBlock { impl WorkScore for BasicBlock { fn work_score(&self, work_score_struct: WorkScoreStructure) -> u32 { - let mut score = work_score_struct.block; - let min_strong_parents_threshold = work_score_struct.min_strong_parents_threshold as usize; - if self.strong_parents.len() < min_strong_parents_threshold { - let missing_parents_count = min_strong_parents_threshold - self.strong_parents.len(); - score += work_score_struct.missing_parent * missing_parents_count as u32; - } - if let Some(payload) = &*self.payload { - score += payload.work_score(work_score_struct); - } - score + let missing_parent_score = { + let min_strong_parents_threshold = work_score_struct.min_strong_parents_threshold as usize; + if self.strong_parents.len() < min_strong_parents_threshold { + let missing_parents_count = min_strong_parents_threshold - self.strong_parents.len(); + work_score_struct.missing_parent * missing_parents_count as u32 + } else { + 0 + } + }; + let payload_score = self.payload.as_ref().map(|p| p.work_score(work_score_struct)).unwrap_or(0); + work_score_struct.block + missing_parent_score + payload_score } } diff --git a/sdk/src/types/block/mana/computation.rs b/sdk/src/types/block/mana/computation.rs new file mode 100644 index 0000000000..6636ead80c --- /dev/null +++ b/sdk/src/types/block/mana/computation.rs @@ -0,0 +1,7 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +/// Computes the necessary mana amount to fulfill the work score requirement. +pub fn compute_necessary_mana_amount(work_score: u32) -> u64 { + todo!("compute necessary mana amount") +} diff --git a/sdk/src/types/block/mana/mod.rs b/sdk/src/types/block/mana/mod.rs index 80320ac623..2c69d05cab 100644 --- a/sdk/src/types/block/mana/mod.rs +++ b/sdk/src/types/block/mana/mod.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 mod allotment; +mod computation; mod rewards; mod structure; @@ -14,7 +15,10 @@ use packable::{bounded::BoundedU16, prefix::BoxedSlicePrefix, Packable}; #[cfg(feature = "serde")] pub use self::allotment::dto::ManaAllotmentDto; -pub use self::{allotment::ManaAllotment, rewards::RewardsParameters, structure::ManaStructure}; +pub use self::{ + allotment::ManaAllotment, computation::compute_necessary_mana_amount, rewards::RewardsParameters, + structure::ManaStructure, +}; use super::{output::AccountId, protocol::ProtocolParameters, Error}; pub(crate) type ManaAllotmentCount = diff --git a/sdk/src/types/block/output/mod.rs b/sdk/src/types/block/output/mod.rs index 3ed03c9b4d..d5267c38b2 100644 --- a/sdk/src/types/block/output/mod.rs +++ b/sdk/src/types/block/output/mod.rs @@ -486,18 +486,6 @@ impl WorkScore for Output { } } -impl WorkScore for [T; N] { - fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { - self.as_slice().work_score(work_score_params) - } -} - -impl WorkScore for [T] { - fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { - self.iter().map(|o| o.work_score(work_score_params)).sum() - } -} - pub(crate) fn verify_output_amount_min(amount: u64) -> Result<(), Error> { if amount < Output::AMOUNT_MIN { Err(Error::InvalidOutputAmount(amount)) diff --git a/sdk/src/types/block/protocol.rs b/sdk/src/types/block/protocol/mod.rs similarity index 84% rename from sdk/src/types/block/protocol.rs rename to sdk/src/types/block/protocol/mod.rs index 21e8ac59e7..a2ed1abfe1 100644 --- a/sdk/src/types/block/protocol.rs +++ b/sdk/src/types/block/protocol/mod.rs @@ -1,12 +1,15 @@ // Copyright 2022 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +mod work_score; + use alloc::string::String; use core::borrow::Borrow; use crypto::hashes::{blake2b::Blake2b256, Digest}; use getset::{CopyGetters, Getters}; use packable::{prefix::StringPrefix, Packable, PackableExt}; +pub use work_score::*; use super::{ address::Hrp, @@ -182,65 +185,6 @@ impl ProtocolParameters { } } -#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Packable, CopyGetters)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(rename_all = "camelCase") -)] -#[packable(unpack_error = Error)] -#[getset(get_copy = "pub")] -pub struct WorkScoreStructure { - /// Modifier for network traffic per byte. - pub(crate) data_byte: u32, - /// Modifier for work done to process a block. - pub(crate) block: u32, - /// Modifier for slashing when there are insufficient strong tips. - pub(crate) missing_parent: u32, - /// Modifier for loading UTXOs and performing mana calculations. - pub(crate) input: u32, - /// Modifier for loading and checking the context input. - pub(crate) context_input: u32, - /// Modifier for storing UTXOs. - pub(crate) output: u32, - /// Modifier for calculations using native tokens. - pub(crate) native_token: u32, - /// Modifier for storing staking features. - pub(crate) staking: u32, - /// Modifier for storing block issuer features. - pub(crate) block_issuer: u32, - /// Modifier for accessing the account-based ledger to transform mana to Block Issuance Credits. - pub(crate) allotment: u32, - /// Modifier for the block signature check. - pub(crate) signature_ed25519: u32, - /// The minimum count of strong parents in a basic block. - pub(crate) min_strong_parents_threshold: u8, -} - -impl Default for WorkScoreStructure { - fn default() -> Self { - Self { - data_byte: 0, - block: 100, - missing_parent: 500, - input: 20, - context_input: 20, - output: 20, - native_token: 20, - staking: 100, - block_issuer: 100, - allotment: 100, - signature_ed25519: 200, - min_strong_parents_threshold: 4, - } - } -} - -/// A trait to facilitate the computation of the work score of a block, which is central to mana cost calculation. -pub trait WorkScore { - fn work_score(&self, work_score_params: WorkScoreStructure) -> u32; -} - /// Defines the parameters used to calculate the Reference Mana Cost (RMC). #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Packable, CopyGetters)] #[cfg_attr( diff --git a/sdk/src/types/block/protocol/work_score.rs b/sdk/src/types/block/protocol/work_score.rs new file mode 100644 index 0000000000..84982ac7e6 --- /dev/null +++ b/sdk/src/types/block/protocol/work_score.rs @@ -0,0 +1,84 @@ +// Copyright 2022 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use getset::CopyGetters; +use packable::Packable; + +use crate::types::block::{Error, mana::compute_necessary_mana_amount}; + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Packable, CopyGetters)] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(rename_all = "camelCase") +)] +#[packable(unpack_error = Error)] +#[getset(get_copy = "pub")] +pub struct WorkScoreStructure { + /// Modifier for network traffic per byte. + pub(crate) data_byte: u32, + /// Modifier for work done to process a block. + pub(crate) block: u32, + /// Modifier for slashing when there are insufficient strong tips. + pub(crate) missing_parent: u32, + /// Modifier for loading UTXOs and performing mana calculations. + pub(crate) input: u32, + /// Modifier for loading and checking the context input. + pub(crate) context_input: u32, + /// Modifier for storing UTXOs. + pub(crate) output: u32, + /// Modifier for calculations using native tokens. + pub(crate) native_token: u32, + /// Modifier for storing staking features. + pub(crate) staking: u32, + /// Modifier for storing block issuer features. + pub(crate) block_issuer: u32, + /// Modifier for accessing the account-based ledger to transform mana to Block Issuance Credits. + pub(crate) allotment: u32, + /// Modifier for the block signature check. + pub(crate) signature_ed25519: u32, + /// The minimum count of strong parents in a basic block. + pub(crate) min_strong_parents_threshold: u8, +} + +impl Default for WorkScoreStructure { + fn default() -> Self { + Self { + data_byte: 0, + block: 100, + missing_parent: 500, + input: 20, + context_input: 20, + output: 20, + native_token: 20, + staking: 100, + block_issuer: 100, + allotment: 100, + signature_ed25519: 200, + min_strong_parents_threshold: 4, + } + } +} + +/// A trait to facilitate the computation of the work score of a block, which is central to mana cost calculation. +pub trait WorkScore { + /// Returns the work score. + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32; + + /// Calculates the Mana cost. + fn mana_cost(&self, work_score_params: WorkScoreStructure) -> u64 { + compute_necessary_mana_amount(self.work_score(work_score_params)) + } +} + +impl WorkScore for [T; N] { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + self.as_slice().work_score(work_score_params) + } +} + +impl WorkScore for [T] { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + self.iter().map(|o| o.work_score(work_score_params)).sum() + } +} From f917fd9470f93d4c8eb0fc40570cf6a9528128b4 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Mon, 9 Oct 2023 17:21:07 +0200 Subject: [PATCH 11/42] add and impl mana cost fn --- sdk/src/types/block/core/basic.rs | 14 +++++++++----- sdk/src/types/block/core/mod.rs | 6 +++--- sdk/src/types/block/core/validation.rs | 7 ------- sdk/src/types/block/core/wrapper.rs | 17 ++++------------- sdk/src/types/block/mana/computation.rs | 7 ------- sdk/src/types/block/mana/mod.rs | 6 +----- sdk/src/types/block/protocol/work_score.rs | 10 +++++----- 7 files changed, 22 insertions(+), 45 deletions(-) delete mode 100644 sdk/src/types/block/mana/computation.rs diff --git a/sdk/src/types/block/core/basic.rs b/sdk/src/types/block/core/basic.rs index b6cde73360..4ad42748f2 100644 --- a/sdk/src/types/block/core/basic.rs +++ b/sdk/src/types/block/core/basic.rs @@ -157,18 +157,22 @@ impl BasicBlock { } impl WorkScore for BasicBlock { - fn work_score(&self, work_score_struct: WorkScoreStructure) -> u32 { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { let missing_parent_score = { - let min_strong_parents_threshold = work_score_struct.min_strong_parents_threshold as usize; + let min_strong_parents_threshold = work_score_params.min_strong_parents_threshold as usize; if self.strong_parents.len() < min_strong_parents_threshold { let missing_parents_count = min_strong_parents_threshold - self.strong_parents.len(); - work_score_struct.missing_parent * missing_parents_count as u32 + work_score_params.missing_parent * missing_parents_count as u32 } else { 0 } }; - let payload_score = self.payload.as_ref().map(|p| p.work_score(work_score_struct)).unwrap_or(0); - work_score_struct.block + missing_parent_score + payload_score + let payload_score = self + .payload + .as_ref() + .map(|p| p.work_score(work_score_params)) + .unwrap_or(0); + work_score_params.block + missing_parent_score + payload_score } } diff --git a/sdk/src/types/block/core/mod.rs b/sdk/src/types/block/core/mod.rs index b38d338d0d..76ad5984d1 100644 --- a/sdk/src/types/block/core/mod.rs +++ b/sdk/src/types/block/core/mod.rs @@ -132,10 +132,10 @@ impl Block { } impl WorkScore for Block { - fn work_score(&self, work_score_struct: WorkScoreStructure) -> u32 { + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { match self { - Self::Basic(basic) => basic.work_score(work_score_struct), - Self::Validation(validation) => validation.work_score(work_score_struct), + Self::Basic(basic) => basic.work_score(work_score_params), + Self::Validation(validation) => 0, } } } diff --git a/sdk/src/types/block/core/validation.rs b/sdk/src/types/block/core/validation.rs index 246e61e59e..e04d6ae266 100644 --- a/sdk/src/types/block/core/validation.rs +++ b/sdk/src/types/block/core/validation.rs @@ -161,13 +161,6 @@ impl ValidationBlock { } } -impl WorkScore for ValidationBlock { - fn work_score(&self, _: WorkScoreStructure) -> u32 { - // The work score of a validation block is `0`. - 0 - } -} - impl Packable for ValidationBlock { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; diff --git a/sdk/src/types/block/core/wrapper.rs b/sdk/src/types/block/core/wrapper.rs index 95b62f9356..4d1ea8c7bf 100644 --- a/sdk/src/types/block/core/wrapper.rs +++ b/sdk/src/types/block/core/wrapper.rs @@ -109,13 +109,6 @@ impl BlockHeader { } } -impl WorkScore for BlockHeader { - fn work_score(&self, _: WorkScoreStructure) -> u32 { - // The work score of a block header is `0`. - 0 - } -} - impl Packable for BlockHeader { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; @@ -298,12 +291,10 @@ impl BlockWrapper { } impl WorkScore for BlockWrapper { - fn work_score(&self, work_score_struct: WorkScoreStructure) -> u32 { - let mut score = work_score_struct.data_byte * self.packed_len() as u32 / 1024; - score += self.header.work_score(work_score_struct); - score += self.block.work_score(work_score_struct); - score += self.signature.work_score(work_score_struct); - score + fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { + let block_score = self.block.work_score(work_score_params); + let signature_score = self.signature.work_score(work_score_params); + block_score + signature_score } } diff --git a/sdk/src/types/block/mana/computation.rs b/sdk/src/types/block/mana/computation.rs deleted file mode 100644 index 6636ead80c..0000000000 --- a/sdk/src/types/block/mana/computation.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2023 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -/// Computes the necessary mana amount to fulfill the work score requirement. -pub fn compute_necessary_mana_amount(work_score: u32) -> u64 { - todo!("compute necessary mana amount") -} diff --git a/sdk/src/types/block/mana/mod.rs b/sdk/src/types/block/mana/mod.rs index 2c69d05cab..80320ac623 100644 --- a/sdk/src/types/block/mana/mod.rs +++ b/sdk/src/types/block/mana/mod.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 mod allotment; -mod computation; mod rewards; mod structure; @@ -15,10 +14,7 @@ use packable::{bounded::BoundedU16, prefix::BoxedSlicePrefix, Packable}; #[cfg(feature = "serde")] pub use self::allotment::dto::ManaAllotmentDto; -pub use self::{ - allotment::ManaAllotment, computation::compute_necessary_mana_amount, rewards::RewardsParameters, - structure::ManaStructure, -}; +pub use self::{allotment::ManaAllotment, rewards::RewardsParameters, structure::ManaStructure}; use super::{output::AccountId, protocol::ProtocolParameters, Error}; pub(crate) type ManaAllotmentCount = diff --git a/sdk/src/types/block/protocol/work_score.rs b/sdk/src/types/block/protocol/work_score.rs index 84982ac7e6..cd049233fa 100644 --- a/sdk/src/types/block/protocol/work_score.rs +++ b/sdk/src/types/block/protocol/work_score.rs @@ -4,7 +4,7 @@ use getset::CopyGetters; use packable::Packable; -use crate::types::block::{Error, mana::compute_necessary_mana_amount}; +use crate::types::block::Error; #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Packable, CopyGetters)] #[cfg_attr( @@ -62,12 +62,12 @@ impl Default for WorkScoreStructure { /// A trait to facilitate the computation of the work score of a block, which is central to mana cost calculation. pub trait WorkScore { - /// Returns the work score. + /// Returns its work score. fn work_score(&self, work_score_params: WorkScoreStructure) -> u32; - /// Calculates the Mana cost. - fn mana_cost(&self, work_score_params: WorkScoreStructure) -> u64 { - compute_necessary_mana_amount(self.work_score(work_score_params)) + /// Returns the Mana cost given its work score. + fn mana_cost(&self, work_score_params: WorkScoreStructure, reference_mana_cost: u64) -> u64 { + reference_mana_cost * self.work_score(work_score_params) as u64 } } From 1ee7870654c86b5bfb1df8835f90f0c7a105f4e9 Mon Sep 17 00:00:00 2001 From: /alex/ Date: Tue, 10 Oct 2023 15:31:23 +0200 Subject: [PATCH 12/42] PR suggestions 1 Co-authored-by: DaughterOfMars --- sdk/src/types/block/output/feature/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sdk/src/types/block/output/feature/mod.rs b/sdk/src/types/block/output/feature/mod.rs index 8a66a5aef0..e935099e17 100644 --- a/sdk/src/types/block/output/feature/mod.rs +++ b/sdk/src/types/block/output/feature/mod.rs @@ -319,15 +319,14 @@ impl Features { impl WorkScore for Features { fn work_score(&self, work_score_params: WorkScoreStructure) -> u32 { - let features_score = self + self .iter() .map(|f| match f { Feature::BlockIssuer(_) => work_score_params.block_issuer, Feature::Staking(_) => work_score_params.staking, _ => 0, }) - .sum::(); - features_score + .sum::() } } From 8789e802a74b3e5091bdcdc90f6a5c402488f444 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Thu, 9 Nov 2023 16:11:19 +0100 Subject: [PATCH 13/42] is_signature --- sdk/src/types/block/unlock/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/unlock/mod.rs b/sdk/src/types/block/unlock/mod.rs index ef8390d96d..50e848e69c 100644 --- a/sdk/src/types/block/unlock/mod.rs +++ b/sdk/src/types/block/unlock/mod.rs @@ -125,7 +125,7 @@ impl WorkScore for Unlocks { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { let signature_score = self .iter() - .filter_map(|u| matches!(u, Unlock::Signature(_)).then_some(work_score_params.signature_ed25519())) + .filter_map(|u| u.is_signature().then_some(work_score_params.signature_ed25519())) .sum::(); signature_score } From 0797c70216e6112f4b5c605d0a01bfcc1c2766fc Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Thu, 9 Nov 2023 21:29:29 +0100 Subject: [PATCH 14/42] remove todo --- sdk/src/types/block/output/native_token.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/src/types/block/output/native_token.rs b/sdk/src/types/block/output/native_token.rs index b35f428060..b811c0566c 100644 --- a/sdk/src/types/block/output/native_token.rs +++ b/sdk/src/types/block/output/native_token.rs @@ -255,7 +255,6 @@ impl NativeTokens { } } -// TODO: should we also impl `WorkScore` for `NativeToken` for plain consistency? impl WorkScore for NativeTokens { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { self.len() as u32 * work_score_params.native_token() From fac3fd29c5659d664869d89bd7fba64cb164d81c Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Mon, 20 Nov 2023 16:36:43 +0100 Subject: [PATCH 15/42] review 1 --- sdk/src/types/block/core/basic.rs | 12 ++++++------ sdk/src/types/block/core/block.rs | 4 +--- sdk/src/types/block/core/mod.rs | 2 +- sdk/src/types/block/output/account.rs | 6 +++--- sdk/src/types/block/output/anchor.rs | 8 ++++---- sdk/src/types/block/output/basic.rs | 3 +-- sdk/src/types/block/output/feature/mod.rs | 2 +- sdk/src/types/block/output/foundry.rs | 16 ++++++++-------- sdk/src/types/block/output/nft.rs | 6 +++--- sdk/src/types/block/payload/mod.rs | 19 ++++++++----------- .../block/payload/signed_transaction/mod.rs | 7 +++---- .../payload/signed_transaction/transaction.rs | 9 ++++----- sdk/src/types/block/payload/tagged_data.rs | 3 +-- sdk/src/types/block/unlock/mod.rs | 6 ++---- 14 files changed, 46 insertions(+), 57 deletions(-) diff --git a/sdk/src/types/block/core/basic.rs b/sdk/src/types/block/core/basic.rs index 6c0f62f2e9..91abfa1f81 100644 --- a/sdk/src/types/block/core/basic.rs +++ b/sdk/src/types/block/core/basic.rs @@ -156,12 +156,12 @@ impl BasicBlockBody { impl WorkScore for BasicBlockBody { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - let payload_score = self - .payload - .as_ref() - .map(|p| p.work_score(work_score_params)) - .unwrap_or(0); - work_score_params.block() + payload_score + work_score_params.block() + + self + .payload + .as_ref() + .map(|p| p.work_score(work_score_params)) + .unwrap_or(0) } } diff --git a/sdk/src/types/block/core/block.rs b/sdk/src/types/block/core/block.rs index abc251f59c..c0b9244321 100644 --- a/sdk/src/types/block/core/block.rs +++ b/sdk/src/types/block/core/block.rs @@ -292,9 +292,7 @@ impl Block { impl WorkScore for Block { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - let body_score = self.body.work_score(work_score_params); - let signature_score = self.signature.work_score(work_score_params); - body_score + signature_score + self.body.work_score(work_score_params) + self.signature.work_score(work_score_params) } } diff --git a/sdk/src/types/block/core/mod.rs b/sdk/src/types/block/core/mod.rs index 91da3e6ef8..c401d0cf5c 100644 --- a/sdk/src/types/block/core/mod.rs +++ b/sdk/src/types/block/core/mod.rs @@ -107,7 +107,7 @@ impl WorkScore for BlockBody { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { match self { Self::Basic(basic) => basic.work_score(work_score_params), - Self::Validation(validation) => 0, + Self::Validation(_) => 0, } } } diff --git a/sdk/src/types/block/output/account.rs b/sdk/src/types/block/output/account.rs index 46aa8b4bf3..29bb19b335 100644 --- a/sdk/src/types/block/output/account.rs +++ b/sdk/src/types/block/output/account.rs @@ -493,9 +493,9 @@ impl StateTransitionVerifier for AccountOutput { impl WorkScore for AccountOutput { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - let features_score = self.features().work_score(work_score_params); - let immutable_features_score = self.immutable_features().work_score(work_score_params); - work_score_params.output() + features_score + immutable_features_score + work_score_params.output() + + self.features().work_score(work_score_params) + + self.immutable_features().work_score(work_score_params) } } diff --git a/sdk/src/types/block/output/anchor.rs b/sdk/src/types/block/output/anchor.rs index e99e66c854..15a607c816 100644 --- a/sdk/src/types/block/output/anchor.rs +++ b/sdk/src/types/block/output/anchor.rs @@ -599,10 +599,10 @@ impl StateTransitionVerifier for AnchorOutput { impl WorkScore for AnchorOutput { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - let native_tokens_score = self.native_tokens().work_score(work_score_params); - let features_score = self.features().work_score(work_score_params); - let immutable_features_score = self.immutable_features().work_score(work_score_params); - work_score_params.output() + native_tokens_score + features_score + immutable_features_score + work_score_params.output() + + self.native_tokens().work_score(work_score_params) + + self.features().work_score(work_score_params) + + self.immutable_features().work_score(work_score_params) } } diff --git a/sdk/src/types/block/output/basic.rs b/sdk/src/types/block/output/basic.rs index 3b21f4e482..3c7a74109a 100644 --- a/sdk/src/types/block/output/basic.rs +++ b/sdk/src/types/block/output/basic.rs @@ -360,8 +360,7 @@ impl BasicOutput { impl WorkScore for BasicOutput { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - let features_score = self.features().work_score(work_score_params); - work_score_params.output() + features_score + work_score_params.output() + self.features().work_score(work_score_params) } } diff --git a/sdk/src/types/block/output/feature/mod.rs b/sdk/src/types/block/output/feature/mod.rs index 67d3c66e17..4a65e603e4 100644 --- a/sdk/src/types/block/output/feature/mod.rs +++ b/sdk/src/types/block/output/feature/mod.rs @@ -266,7 +266,7 @@ impl WorkScore for Features { Feature::Staking(_) => work_score_params.staking(), _ => 0, }) - .sum::() + .sum() } } diff --git a/sdk/src/types/block/output/foundry.rs b/sdk/src/types/block/output/foundry.rs index d260c401df..26bb45867b 100644 --- a/sdk/src/types/block/output/foundry.rs +++ b/sdk/src/types/block/output/foundry.rs @@ -589,14 +589,14 @@ impl StateTransitionVerifier for FoundryOutput { impl WorkScore for FoundryOutput { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - let features_score = self.features().work_score(work_score_params); - let immutable_features_score = self.immutable_features().work_score(work_score_params); - let token_scheme_score = self - .token_scheme() - .is_simple() - .then_some(work_score_params.native_token()) - .unwrap_or(0); - work_score_params.output() + features_score + immutable_features_score + token_scheme_score + work_score_params.output() + + self.features().work_score(work_score_params) + + self.immutable_features().work_score(work_score_params) + + self + .token_scheme() + .is_simple() + .then_some(work_score_params.native_token()) + .unwrap_or(0) } } diff --git a/sdk/src/types/block/output/nft.rs b/sdk/src/types/block/output/nft.rs index 90a8190695..27c665b589 100644 --- a/sdk/src/types/block/output/nft.rs +++ b/sdk/src/types/block/output/nft.rs @@ -489,9 +489,9 @@ impl StateTransitionVerifier for NftOutput { impl WorkScore for NftOutput { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - let features_score = self.features().work_score(work_score_params); - let immutable_features_score = self.immutable_features().work_score(work_score_params); - work_score_params.output() + features_score + immutable_features_score + work_score_params.output() + + self.features().work_score(work_score_params) + + self.immutable_features().work_score(work_score_params) } } diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index a8fcd752a3..012fb402bc 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -81,17 +81,14 @@ impl Payload { impl WorkScore for Payload { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { // 1 byte for the payload kind - let score = size_of::() as u32 - + match self { - Self::SignedTransaction(signed_transaction_payload) => { - signed_transaction_payload.work_score(work_score_params) - } - Self::TaggedData(tagged_data_payload) => tagged_data_payload.work_score(work_score_params), - Self::CandidacyAnnouncement(candidacy_announcement_payload) => { - todo!("work score for candidacy announcement payload") - } - }; - score + 1 + match self { + Self::SignedTransaction(signed_transaction) => signed_transaction.work_score(work_score_params), + Self::TaggedData(tagged_data) => tagged_data.work_score(work_score_params), + Self::CandidacyAnnouncement(candidacy_announcement) => { + // TODO: Issue #0000 + todo!("work score for candidacy announcement payload") + } + } } } diff --git a/sdk/src/types/block/payload/signed_transaction/mod.rs b/sdk/src/types/block/payload/signed_transaction/mod.rs index 422cce3bea..9b7c65cd0c 100644 --- a/sdk/src/types/block/payload/signed_transaction/mod.rs +++ b/sdk/src/types/block/payload/signed_transaction/mod.rs @@ -50,10 +50,9 @@ impl SignedTransactionPayload { impl WorkScore for SignedTransactionPayload { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - let size_score = self.packed_len() as u32 * work_score_params.data_byte(); - let essence_score = self.transaction().work_score(work_score_params); - let unlocks_score = self.unlocks().work_score(work_score_params); - size_score + essence_score + unlocks_score + self.packed_len() as u32 * work_score_params.data_byte() + + self.transaction().work_score(work_score_params) + + self.unlocks().work_score(work_score_params) } } diff --git a/sdk/src/types/block/payload/signed_transaction/transaction.rs b/sdk/src/types/block/payload/signed_transaction/transaction.rs index ff9d45ba66..914c975fce 100644 --- a/sdk/src/types/block/payload/signed_transaction/transaction.rs +++ b/sdk/src/types/block/payload/signed_transaction/transaction.rs @@ -326,11 +326,10 @@ impl Transaction { impl WorkScore for Transaction { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - let input_score = self.inputs().len() as u32 * work_score_params.input(); - let context_input_score = self.context_inputs().len() as u32 * work_score_params.context_input(); - let outputs_score = self.outputs().work_score(work_score_params); - let allotment_score = self.mana_allotments().len() as u32 * work_score_params.allotment(); - input_score + context_input_score + outputs_score + allotment_score + self.inputs().len() as u32 * work_score_params.input() + + self.context_inputs().len() as u32 * work_score_params.context_input() + + self.outputs().work_score(work_score_params) + + self.mana_allotments().len() as u32 * work_score_params.allotment() } } diff --git a/sdk/src/types/block/payload/tagged_data.rs b/sdk/src/types/block/payload/tagged_data.rs index c46ee9cafb..887eb776b0 100644 --- a/sdk/src/types/block/payload/tagged_data.rs +++ b/sdk/src/types/block/payload/tagged_data.rs @@ -61,8 +61,7 @@ impl TaggedDataPayload { impl WorkScore for TaggedDataPayload { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - let size_score = self.packed_len() as u32 * work_score_params.data_byte(); - size_score + self.packed_len() as u32 * work_score_params.data_byte() } } diff --git a/sdk/src/types/block/unlock/mod.rs b/sdk/src/types/block/unlock/mod.rs index 2f24c3f922..9a8d54fc6f 100644 --- a/sdk/src/types/block/unlock/mod.rs +++ b/sdk/src/types/block/unlock/mod.rs @@ -136,11 +136,9 @@ impl Unlocks { impl WorkScore for Unlocks { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - let signature_score = self - .iter() + self.iter() .filter_map(|u| u.is_signature().then_some(work_score_params.signature_ed25519())) - .sum::(); - signature_score + .sum() } } From 7aaae7da4c54518a20c39b7488e6a22f6f8a12f6 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Mon, 20 Nov 2023 16:55:02 +0100 Subject: [PATCH 16/42] review 2 --- sdk/src/types/block/core/mod.rs | 3 +-- sdk/src/types/block/output/mod.rs | 9 +++++++-- sdk/src/types/block/payload/mod.rs | 6 ++++-- sdk/src/types/block/signature/mod.rs | 6 ++++-- sdk/src/types/block/unlock/mod.rs | 2 +- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/sdk/src/types/block/core/mod.rs b/sdk/src/types/block/core/mod.rs index c401d0cf5c..0815cb59a7 100644 --- a/sdk/src/types/block/core/mod.rs +++ b/sdk/src/types/block/core/mod.rs @@ -18,9 +18,8 @@ pub use self::{ parent::Parents, validation::{ValidationBlockBody, ValidationBlockBodyBuilder}, }; -use super::protocol::WorkScore; use crate::types::block::{ - protocol::{ProtocolParameters, ProtocolParametersHash, WorkScoreParameters}, + protocol::{ProtocolParameters, ProtocolParametersHash, WorkScore, WorkScoreParameters}, Error, }; diff --git a/sdk/src/types/block/output/mod.rs b/sdk/src/types/block/output/mod.rs index 8faf749384..ea441cb3c8 100644 --- a/sdk/src/types/block/output/mod.rs +++ b/sdk/src/types/block/output/mod.rs @@ -52,8 +52,13 @@ pub(crate) use self::{ output_id::OutputIndex, unlock_condition::AddressUnlockCondition, }; -use super::protocol::{ProtocolParameters, WorkScore, WorkScoreParameters}; -use crate::types::block::{address::Address, semantic::SemanticValidationContext, slot::SlotIndex, Error}; +use crate::types::block::{ + address::Address, + protocol::{ProtocolParameters, WorkScore, WorkScoreParameters}, + semantic::SemanticValidationContext, + slot::SlotIndex, + Error, +}; /// The maximum number of outputs of a transaction. pub const OUTPUT_COUNT_MAX: u16 = 128; diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index 012fb402bc..172a1915b3 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -23,8 +23,10 @@ pub use self::{ candidacy_announcement::CandidacyAnnouncementPayload, signed_transaction::SignedTransactionPayload, tagged_data::TaggedDataPayload, }; -use super::protocol::{WorkScore, WorkScoreParameters}; -use crate::types::block::{protocol::ProtocolParameters, Error}; +use crate::types::block::{ + protocol::{ProtocolParameters, WorkScore, WorkScoreParameters}, + Error, +}; /// A generic payload that can represent different types defining block payloads. #[derive(Clone, Eq, PartialEq, From, Packable)] diff --git a/sdk/src/types/block/signature/mod.rs b/sdk/src/types/block/signature/mod.rs index 159affbe30..b30e557298 100644 --- a/sdk/src/types/block/signature/mod.rs +++ b/sdk/src/types/block/signature/mod.rs @@ -6,8 +6,10 @@ mod ed25519; use derive_more::From; pub use self::ed25519::Ed25519Signature; -use super::protocol::{WorkScore, WorkScoreParameters}; -use crate::types::block::Error; +use crate::types::block::{ + protocol::{WorkScore, WorkScoreParameters}, + Error, +}; /// A `Signature` contains a signature which is used to unlock a transaction input. /// diff --git a/sdk/src/types/block/unlock/mod.rs b/sdk/src/types/block/unlock/mod.rs index 9a8d54fc6f..1f4ade5275 100644 --- a/sdk/src/types/block/unlock/mod.rs +++ b/sdk/src/types/block/unlock/mod.rs @@ -21,9 +21,9 @@ pub use self::{ account::AccountUnlock, anchor::AnchorUnlock, empty::EmptyUnlock, multi::MultiUnlock, nft::NftUnlock, reference::ReferenceUnlock, signature::SignatureUnlock, }; -use super::protocol::{WorkScore, WorkScoreParameters}; use crate::types::block::{ input::{INPUT_COUNT_MAX, INPUT_COUNT_RANGE, INPUT_INDEX_MAX}, + protocol::{WorkScore, WorkScoreParameters}, Error, }; From d7929c689de73d57c5a26dc3eecb240561ba72f9 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Mon, 20 Nov 2023 16:58:16 +0100 Subject: [PATCH 17/42] review 3 --- sdk/src/types/block/output/anchor.rs | 6 +----- sdk/src/types/block/protocol/mod.rs | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/sdk/src/types/block/output/anchor.rs b/sdk/src/types/block/output/anchor.rs index d86bee0e08..2e7944b738 100644 --- a/sdk/src/types/block/output/anchor.rs +++ b/sdk/src/types/block/output/anchor.rs @@ -42,11 +42,7 @@ impl From<&OutputId> for AnchorId { impl AnchorId { /// pub fn or_from_output_id(self, output_id: &OutputId) -> Self { - if self.is_null() { - Self::from(output_id) - } else { - self - } + if self.is_null() { Self::from(output_id) } else { self } } } diff --git a/sdk/src/types/block/protocol/mod.rs b/sdk/src/types/block/protocol/mod.rs index 063d4805cf..c1c32bd675 100644 --- a/sdk/src/types/block/protocol/mod.rs +++ b/sdk/src/types/block/protocol/mod.rs @@ -9,7 +9,7 @@ use core::borrow::Borrow; use crypto::hashes::{blake2b::Blake2b256, Digest}; use getset::{CopyGetters, Getters}; use packable::{prefix::StringPrefix, Packable, PackableExt}; -pub use work_score::*; +pub use work_score::{WorkScore, WorkScoreParameters}; use crate::{ types::block::{ From ecf08e3d3f4ec78f19b8df3476cf7b47cbcefc65 Mon Sep 17 00:00:00 2001 From: /alex/ Date: Mon, 20 Nov 2023 17:01:11 +0100 Subject: [PATCH 18/42] fix copyright year Co-authored-by: Thibault Martinez --- sdk/src/types/block/protocol/work_score.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/protocol/work_score.rs b/sdk/src/types/block/protocol/work_score.rs index dd3a46722d..c60ca2e916 100644 --- a/sdk/src/types/block/protocol/work_score.rs +++ b/sdk/src/types/block/protocol/work_score.rs @@ -1,4 +1,4 @@ -// Copyright 2022 IOTA Stiftung +// Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 use getset::CopyGetters; From 711c35b95c9d0e9aeb43a1949948d15198c49a4b Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Tue, 21 Nov 2023 16:54:10 +0100 Subject: [PATCH 19/42] StorageScore :heart: WorkScore --- sdk/src/types/block/output/anchor.rs | 18 +++++++++--------- sdk/src/types/block/output/basic.rs | 12 ++++++------ sdk/src/types/block/output/foundry.rs | 26 +++++++++++++------------- sdk/src/types/block/output/nft.rs | 16 ++++++++-------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/sdk/src/types/block/output/anchor.rs b/sdk/src/types/block/output/anchor.rs index 2e7944b738..ac3acf4e7a 100644 --- a/sdk/src/types/block/output/anchor.rs +++ b/sdk/src/types/block/output/anchor.rs @@ -531,6 +531,15 @@ impl StorageScore for AnchorOutput { } } +impl WorkScore for AnchorOutput { + fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { + work_score_params.output() + + self.native_tokens().work_score(work_score_params) + + self.features().work_score(work_score_params) + + self.immutable_features().work_score(work_score_params) + } +} + impl MinimumOutputAmount for AnchorOutput {} impl StateTransitionVerifier for AnchorOutput { @@ -573,15 +582,6 @@ impl StateTransitionVerifier for AnchorOutput { } } -impl WorkScore for AnchorOutput { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - work_score_params.output() - + self.native_tokens().work_score(work_score_params) - + self.features().work_score(work_score_params) - + self.immutable_features().work_score(work_score_params) - } -} - impl Packable for AnchorOutput { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; diff --git a/sdk/src/types/block/output/basic.rs b/sdk/src/types/block/output/basic.rs index 3c7a74109a..296112df6e 100644 --- a/sdk/src/types/block/output/basic.rs +++ b/sdk/src/types/block/output/basic.rs @@ -358,12 +358,6 @@ impl BasicOutput { } } -impl WorkScore for BasicOutput { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - work_score_params.output() + self.features().work_score(work_score_params) - } -} - impl StorageScore for BasicOutput { fn storage_score(&self, params: StorageScoreParameters) -> u64 { params.output_offset() @@ -374,6 +368,12 @@ impl StorageScore for BasicOutput { } } +impl WorkScore for BasicOutput { + fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { + work_score_params.output() + self.features().work_score(work_score_params) + } +} + impl MinimumOutputAmount for BasicOutput {} fn verify_unlock_conditions(unlock_conditions: &UnlockConditions) -> Result<(), Error> { diff --git a/sdk/src/types/block/output/foundry.rs b/sdk/src/types/block/output/foundry.rs index 26bb45867b..651e44dee0 100644 --- a/sdk/src/types/block/output/foundry.rs +++ b/sdk/src/types/block/output/foundry.rs @@ -510,6 +510,19 @@ impl StorageScore for FoundryOutput { } } +impl WorkScore for FoundryOutput { + fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { + work_score_params.output() + + self.features().work_score(work_score_params) + + self.immutable_features().work_score(work_score_params) + + self + .token_scheme() + .is_simple() + .then_some(work_score_params.native_token()) + .unwrap_or(0) + } +} + impl MinimumOutputAmount for FoundryOutput {} impl StateTransitionVerifier for FoundryOutput { @@ -587,19 +600,6 @@ impl StateTransitionVerifier for FoundryOutput { } } -impl WorkScore for FoundryOutput { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - work_score_params.output() - + self.features().work_score(work_score_params) - + self.immutable_features().work_score(work_score_params) - + self - .token_scheme() - .is_simple() - .then_some(work_score_params.native_token()) - .unwrap_or(0) - } -} - impl Packable for FoundryOutput { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; diff --git a/sdk/src/types/block/output/nft.rs b/sdk/src/types/block/output/nft.rs index 27c665b589..04c119dacb 100644 --- a/sdk/src/types/block/output/nft.rs +++ b/sdk/src/types/block/output/nft.rs @@ -451,6 +451,14 @@ impl StorageScore for NftOutput { } } +impl WorkScore for NftOutput { + fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { + work_score_params.output() + + self.features().work_score(work_score_params) + + self.immutable_features().work_score(work_score_params) + } +} + impl MinimumOutputAmount for NftOutput {} impl StateTransitionVerifier for NftOutput { @@ -487,14 +495,6 @@ impl StateTransitionVerifier for NftOutput { } } -impl WorkScore for NftOutput { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - work_score_params.output() - + self.features().work_score(work_score_params) - + self.immutable_features().work_score(work_score_params) - } -} - impl Packable for NftOutput { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; From 8d6b744f8b22bc158e42722b5c7aeff3e59e30b1 Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Tue, 21 Nov 2023 14:14:28 +0100 Subject: [PATCH 20/42] Fix def_is_as_opt panic message (#1659) --- sdk/src/types/block/macro.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/macro.rs b/sdk/src/types/block/macro.rs index 74b74a6ec8..9ddf21391e 100644 --- a/sdk/src/types/block/macro.rs +++ b/sdk/src/types/block/macro.rs @@ -343,7 +343,7 @@ macro_rules! def_is_as_opt { if let Self::$name(v) = self { v } else { - panic!("{} called on a non-{} {}", stringify!([]), stringify!([<$name>]), stringify!($type:snake)); + panic!("{} called on a non-{} {}", stringify!([]), stringify!([<$name>]), stringify!([<$type:snake>])); } } From 5f8e14f35c523fff57066ef9d110c764d792b193 Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Tue, 21 Nov 2023 15:50:14 +0100 Subject: [PATCH 21/42] Remove native tokens from AnchorOutput (#1660) --- sdk/src/types/block/output/anchor.rs | 46 ++-------------------------- 1 file changed, 3 insertions(+), 43 deletions(-) diff --git a/sdk/src/types/block/output/anchor.rs b/sdk/src/types/block/output/anchor.rs index ac3acf4e7a..479076bff7 100644 --- a/sdk/src/types/block/output/anchor.rs +++ b/sdk/src/types/block/output/anchor.rs @@ -16,8 +16,8 @@ use crate::types::block::{ output::{ feature::{verify_allowed_features, Feature, FeatureFlags, Features}, unlock_condition::{verify_allowed_unlock_conditions, UnlockCondition, UnlockConditionFlags, UnlockConditions}, - ChainId, MinimumOutputAmount, NativeToken, NativeTokens, Output, OutputBuilderAmount, OutputId, - StateTransitionError, StateTransitionVerifier, StorageScore, StorageScoreParameters, + ChainId, MinimumOutputAmount, Output, OutputBuilderAmount, OutputId, StateTransitionError, + StateTransitionVerifier, StorageScore, StorageScoreParameters, }, payload::signed_transaction::TransactionCapabilityFlag, protocol::{ProtocolParameters, WorkScore, WorkScoreParameters}, @@ -89,7 +89,6 @@ impl core::fmt::Display for AnchorTransition { pub struct AnchorOutputBuilder { amount: OutputBuilderAmount, mana: u64, - native_tokens: BTreeSet, anchor_id: AnchorId, state_index: u32, unlock_conditions: BTreeSet, @@ -114,7 +113,6 @@ impl AnchorOutputBuilder { Self { amount, mana: Default::default(), - native_tokens: BTreeSet::new(), anchor_id, state_index: 0, unlock_conditions: BTreeSet::new(), @@ -144,20 +142,6 @@ impl AnchorOutputBuilder { self } - /// - #[inline(always)] - pub fn add_native_token(mut self, native_token: NativeToken) -> Self { - self.native_tokens.insert(native_token); - self - } - - /// - #[inline(always)] - pub fn with_native_tokens(mut self, native_tokens: impl IntoIterator) -> Self { - self.native_tokens = native_tokens.into_iter().collect(); - self - } - /// Sets the anchor ID to the provided value. #[inline(always)] pub fn with_anchor_id(mut self, anchor_id: AnchorId) -> Self { @@ -275,7 +259,6 @@ impl AnchorOutputBuilder { let mut output = AnchorOutput { amount: 0, mana: self.mana, - native_tokens: NativeTokens::from_set(self.native_tokens)?, anchor_id: self.anchor_id, state_index: self.state_index, unlock_conditions, @@ -302,7 +285,6 @@ impl From<&AnchorOutput> for AnchorOutputBuilder { Self { amount: OutputBuilderAmount::Amount(output.amount), mana: output.mana, - native_tokens: output.native_tokens.iter().copied().collect(), anchor_id: output.anchor_id, state_index: output.state_index, unlock_conditions: output.unlock_conditions.iter().cloned().collect(), @@ -318,8 +300,6 @@ pub struct AnchorOutput { /// Amount of IOTA coins held by the output. amount: u64, mana: u64, - /// Native tokens held by the output. - native_tokens: NativeTokens, /// Unique identifier of the anchor. anchor_id: AnchorId, /// A counter that must increase by 1 every time the anchor is state transitioned. @@ -367,12 +347,6 @@ impl AnchorOutput { self.mana } - /// - #[inline(always)] - pub fn native_tokens(&self) -> &NativeTokens { - &self.native_tokens - } - /// #[inline(always)] pub fn anchor_id(&self) -> &AnchorId { @@ -503,7 +477,7 @@ impl AnchorOutput { } } else if next_state.state_index == current_state.state_index { // Governance transition. - if current_state.amount != next_state.amount || current_state.native_tokens != next_state.native_tokens + if current_state.amount != next_state.amount // TODO https://github.com/iotaledger/iota-sdk/issues/1650 // || current_state.state_metadata != next_state.state_metadata { @@ -589,7 +563,6 @@ impl Packable for AnchorOutput { fn pack(&self, packer: &mut P) -> Result<(), P::Error> { self.amount.pack(packer)?; self.mana.pack(packer)?; - self.native_tokens.pack(packer)?; self.anchor_id.pack(packer)?; self.state_index.pack(packer)?; self.unlock_conditions.pack(packer)?; @@ -607,7 +580,6 @@ impl Packable for AnchorOutput { let mana = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?; - let native_tokens = NativeTokens::unpack::<_, VERIFY>(unpacker, &())?; let anchor_id = AnchorId::unpack::<_, VERIFY>(unpacker, &()).coerce()?; let state_index = u32::unpack::<_, VERIFY>(unpacker, &()).coerce()?; @@ -637,7 +609,6 @@ impl Packable for AnchorOutput { Ok(Self { amount, mana, - native_tokens, anchor_id, state_index, unlock_conditions, @@ -701,8 +672,6 @@ pub(crate) mod dto { pub amount: u64, #[serde(with = "string")] pub mana: u64, - #[serde(skip_serializing_if = "Vec::is_empty", default)] - pub native_tokens: Vec, pub anchor_id: AnchorId, pub state_index: u32, pub unlock_conditions: Vec, @@ -718,7 +687,6 @@ pub(crate) mod dto { kind: AnchorOutput::KIND, amount: value.amount(), mana: value.mana(), - native_tokens: value.native_tokens().to_vec(), anchor_id: *value.anchor_id(), state_index: value.state_index(), unlock_conditions: value.unlock_conditions().iter().map(Into::into).collect::<_>(), @@ -735,7 +703,6 @@ pub(crate) mod dto { let mut builder = AnchorOutputBuilder::new_with_amount(dto.amount, dto.anchor_id) .with_mana(dto.mana) .with_state_index(dto.state_index) - .with_native_tokens(dto.native_tokens) .with_features(dto.features) .with_immutable_features(dto.immutable_features); @@ -752,7 +719,6 @@ pub(crate) mod dto { pub fn try_from_dtos( amount: OutputBuilderAmount, mana: u64, - native_tokens: Option>, anchor_id: &AnchorId, state_index: u32, unlock_conditions: Vec, @@ -768,10 +734,6 @@ pub(crate) mod dto { .with_mana(mana) .with_state_index(state_index); - if let Some(native_tokens) = native_tokens { - builder = builder.with_native_tokens(native_tokens); - } - let unlock_conditions = unlock_conditions .into_iter() .map(UnlockCondition::from) @@ -820,7 +782,6 @@ mod tests { let output_split = AnchorOutput::try_from_dtos( OutputBuilderAmount::Amount(output.amount()), output.mana(), - Some(output.native_tokens().to_vec()), output.anchor_id(), output.state_index(), output.unlock_conditions().iter().map(Into::into).collect(), @@ -838,7 +799,6 @@ mod tests { let output_split = AnchorOutput::try_from_dtos( builder.amount, builder.mana, - Some(builder.native_tokens.iter().copied().collect()), &builder.anchor_id, builder.state_index, builder.unlock_conditions.iter().map(Into::into).collect(), From 21217b9cb28be6786fc291cbdf01a6f087da29c4 Mon Sep 17 00:00:00 2001 From: /alex/ Date: Tue, 21 Nov 2023 16:27:38 +0100 Subject: [PATCH 22/42] Python: add multi address (#1658) * add weighted address and multi address * fmt --- bindings/python/iota_sdk/types/address.py | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/bindings/python/iota_sdk/types/address.py b/bindings/python/iota_sdk/types/address.py index 36697010b5..aa55d0fe5f 100644 --- a/bindings/python/iota_sdk/types/address.py +++ b/bindings/python/iota_sdk/types/address.py @@ -16,6 +16,7 @@ class AddressType(IntEnum): NFT (16): Nft address. ANCHOR (24): Anchor address. IMPLICIT_ACCOUNT_CREATION (32): Implicit Account Creation address. + MULTI (40): Multi address. RESTRICTED (48): Address with restricted capabilities. """ @@ -24,6 +25,7 @@ class AddressType(IntEnum): NFT = 16 ANCHOR = 24 IMPLICIT_ACCOUNT_CREATION = 32 + MULTI = 40 RESTRICTED = 48 @@ -109,6 +111,34 @@ def from_dict(addr_dict: dict): Ed25519Address(addr_dict['pubKeyHash'])) +@json +@dataclass +class WeightedAddress: + """An address with an assigned weight. + Attributes: + address: The unlocked address. + weight: The weight of the unlocked address. + """ + address: Union[Ed25519Address, AccountAddress, NFTAddress, AnchorAddress] + weight: int + + +@json +@dataclass +class MultiAddress: + """An address that consists of addresses with weights and a threshold value. + The Multi Address can be unlocked if the cumulative weight of all unlocked addresses is equal to or exceeds the + threshold. + Attributes: + addresses: The weighted unlocked addresses. + threshold: The threshold that needs to be reached by the unlocked addresses in order to unlock the multi address. + """ + addresses: List[WeightedAddress] + threshold: int + type: int = field(default_factory=lambda: int( + AddressType.MULTI), init=False) + + @json @dataclass class RestrictedAddress: @@ -149,6 +179,7 @@ class AddressWithUnspentOutputs(): NFTAddress, AnchorAddress, ImplicitAccountCreationAddress, + MultiAddress, RestrictedAddress] @@ -170,6 +201,8 @@ def deserialize_address(d: Dict[str, Any]) -> Address: return AnchorAddress.from_dict(d) if address_type == AddressType.IMPLICIT_ACCOUNT_CREATION: return ImplicitAccountCreationAddress.from_dict(d) + if address_type == AddressType.MULTI: + return MultiAddress.from_dict(d) if address_type == AddressType.RESTRICTED: return RestrictedAddress.from_dict(d) raise Exception(f'invalid address type: {address_type}') From e4491564dd6660e84ae865fdbe2dc990bbc40648 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Tue, 21 Nov 2023 16:56:35 +0100 Subject: [PATCH 23/42] fmt --- sdk/src/client/secret/ledger_nano.rs | 1 - sdk/src/client/stronghold/secret.rs | 10 ++++++---- sdk/src/types/block/output/anchor.rs | 1 - 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sdk/src/client/secret/ledger_nano.rs b/sdk/src/client/secret/ledger_nano.rs index 7c38f03597..d3b3009665 100644 --- a/sdk/src/client/secret/ledger_nano.rs +++ b/sdk/src/client/secret/ledger_nano.rs @@ -145,7 +145,6 @@ impl SecretManage for LedgerSecretManager { ) -> Result, Self::Error> { // need an update on the ledger C lib todo!(); - // // let options = options.into().unwrap_or_default(); // let bip32_account = account_index.harden().into(); diff --git a/sdk/src/client/stronghold/secret.rs b/sdk/src/client/stronghold/secret.rs index cc0993a522..7568cc176d 100644 --- a/sdk/src/client/stronghold/secret.rs +++ b/sdk/src/client/stronghold/secret.rs @@ -581,10 +581,12 @@ mod tests { stronghold_adapter.clear_key().await; // Address generation returns an error when the key is cleared. - assert!(stronghold_adapter - .generate_ed25519_addresses(IOTA_COIN_TYPE, 0, 0..1, None,) - .await - .is_err()); + assert!( + stronghold_adapter + .generate_ed25519_addresses(IOTA_COIN_TYPE, 0, 0..1, None) + .await + .is_err() + ); stronghold_adapter.set_password("drowssap".to_owned()).await.unwrap(); diff --git a/sdk/src/types/block/output/anchor.rs b/sdk/src/types/block/output/anchor.rs index 479076bff7..191403b116 100644 --- a/sdk/src/types/block/output/anchor.rs +++ b/sdk/src/types/block/output/anchor.rs @@ -508,7 +508,6 @@ impl StorageScore for AnchorOutput { impl WorkScore for AnchorOutput { fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { work_score_params.output() - + self.native_tokens().work_score(work_score_params) + self.features().work_score(work_score_params) + self.immutable_features().work_score(work_score_params) } From f48a8cfaf08bc23bed4b436414dd925a7e6ae5d4 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Tue, 21 Nov 2023 18:32:31 +0100 Subject: [PATCH 24/42] align + more impls --- sdk/src/types/block/core/basic.rs | 6 +-- sdk/src/types/block/core/block.rs | 6 ++- sdk/src/types/block/core/mod.rs | 6 +-- sdk/src/types/block/core/validation.rs | 2 + sdk/src/types/block/output/account.rs | 14 +++---- sdk/src/types/block/output/anchor.rs | 6 +-- sdk/src/types/block/output/basic.rs | 4 +- sdk/src/types/block/output/delegation.rs | 12 +++--- .../block/output/feature/block_issuer.rs | 7 ++++ sdk/src/types/block/output/feature/mod.rs | 20 +++++----- .../block/output/feature/native_token.rs | 11 +++++- sdk/src/types/block/output/feature/staking.rs | 7 ++++ sdk/src/types/block/output/foundry.rs | 15 +++----- sdk/src/types/block/output/mod.rs | 38 +++++++++---------- sdk/src/types/block/output/native_token.rs | 10 ++++- sdk/src/types/block/output/nft.rs | 6 +-- .../types/block/output/token_scheme/mod.rs | 13 ++++++- .../types/block/output/token_scheme/simple.rs | 5 ++- .../block/output/unlock_condition/mod.rs | 17 ++++++++- .../block/payload/candidacy_announcement.rs | 5 +++ sdk/src/types/block/payload/mod.rs | 11 ++---- .../block/payload/signed_transaction/mod.rs | 8 ++-- .../payload/signed_transaction/transaction.rs | 10 ++--- sdk/src/types/block/payload/tagged_data.rs | 4 +- sdk/src/types/block/protocol/work_score.rs | 18 +++++---- sdk/src/types/block/signature/ed25519.rs | 12 +++++- sdk/src/types/block/signature/mod.rs | 4 +- sdk/src/types/block/unlock/mod.rs | 4 +- 28 files changed, 173 insertions(+), 108 deletions(-) diff --git a/sdk/src/types/block/core/basic.rs b/sdk/src/types/block/core/basic.rs index 91abfa1f81..70ff8ee4c6 100644 --- a/sdk/src/types/block/core/basic.rs +++ b/sdk/src/types/block/core/basic.rs @@ -155,12 +155,12 @@ impl BasicBlockBody { } impl WorkScore for BasicBlockBody { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - work_score_params.block() + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.block() + self .payload .as_ref() - .map(|p| p.work_score(work_score_params)) + .map(|payload| payload.work_score(params)) .unwrap_or(0) } } diff --git a/sdk/src/types/block/core/block.rs b/sdk/src/types/block/core/block.rs index c0b9244321..acafa643bf 100644 --- a/sdk/src/types/block/core/block.rs +++ b/sdk/src/types/block/core/block.rs @@ -109,6 +109,8 @@ impl BlockHeader { } } +impl WorkScore for BlockHeader {} + impl Packable for BlockHeader { type UnpackError = Error; type UnpackVisitor = ProtocolParameters; @@ -291,8 +293,8 @@ impl Block { } impl WorkScore for Block { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - self.body.work_score(work_score_params) + self.signature.work_score(work_score_params) + fn work_score(&self, params: WorkScoreParameters) -> u32 { + self.header.work_score(params) + self.body.work_score(params) + self.signature.work_score(params) } } diff --git a/sdk/src/types/block/core/mod.rs b/sdk/src/types/block/core/mod.rs index 0815cb59a7..5b16fb9b0a 100644 --- a/sdk/src/types/block/core/mod.rs +++ b/sdk/src/types/block/core/mod.rs @@ -103,10 +103,10 @@ impl BlockBody { } impl WorkScore for BlockBody { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { + fn work_score(&self, params: WorkScoreParameters) -> u32 { match self { - Self::Basic(basic) => basic.work_score(work_score_params), - Self::Validation(_) => 0, + Self::Basic(basic) => basic.work_score(params), + Self::Validation(validation) => validation.work_score(params), } } } diff --git a/sdk/src/types/block/core/validation.rs b/sdk/src/types/block/core/validation.rs index 9233686217..137bccf1ec 100644 --- a/sdk/src/types/block/core/validation.rs +++ b/sdk/src/types/block/core/validation.rs @@ -160,6 +160,8 @@ impl ValidationBlockBody { } } +impl WorkScore for ValidationBlockBody {} + fn verify_protocol_parameters_hash( hash: &ProtocolParametersHash, params: &ProtocolParameters, diff --git a/sdk/src/types/block/output/account.rs b/sdk/src/types/block/output/account.rs index 3507abd66d..b7b40f9d74 100644 --- a/sdk/src/types/block/output/account.rs +++ b/sdk/src/types/block/output/account.rs @@ -494,14 +494,6 @@ impl StateTransitionVerifier for AccountOutput { } } -impl WorkScore for AccountOutput { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - work_score_params.output() - + self.features().work_score(work_score_params) - + self.immutable_features().work_score(work_score_params) - } -} - impl StorageScore for AccountOutput { fn storage_score(&self, params: StorageScoreParameters) -> u64 { params.output_offset() @@ -513,6 +505,12 @@ impl StorageScore for AccountOutput { } } +impl WorkScore for AccountOutput { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.output() + self.features().work_score(params) + self.immutable_features().work_score(params) + } +} + impl MinimumOutputAmount for AccountOutput {} impl Packable for AccountOutput { diff --git a/sdk/src/types/block/output/anchor.rs b/sdk/src/types/block/output/anchor.rs index 191403b116..43a5605217 100644 --- a/sdk/src/types/block/output/anchor.rs +++ b/sdk/src/types/block/output/anchor.rs @@ -506,10 +506,8 @@ impl StorageScore for AnchorOutput { } impl WorkScore for AnchorOutput { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - work_score_params.output() - + self.features().work_score(work_score_params) - + self.immutable_features().work_score(work_score_params) + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.output() + self.features().work_score(params) + self.immutable_features().work_score(params) } } diff --git a/sdk/src/types/block/output/basic.rs b/sdk/src/types/block/output/basic.rs index 296112df6e..cc391f7e5e 100644 --- a/sdk/src/types/block/output/basic.rs +++ b/sdk/src/types/block/output/basic.rs @@ -369,8 +369,8 @@ impl StorageScore for BasicOutput { } impl WorkScore for BasicOutput { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - work_score_params.output() + self.features().work_score(work_score_params) + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.output() + self.features().work_score(params) } } diff --git a/sdk/src/types/block/output/delegation.rs b/sdk/src/types/block/output/delegation.rs index af7b6e85ca..7ddc1a3c7d 100644 --- a/sdk/src/types/block/output/delegation.rs +++ b/sdk/src/types/block/output/delegation.rs @@ -380,12 +380,6 @@ impl StateTransitionVerifier for DelegationOutput { } } -impl WorkScore for DelegationOutput { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - work_score_params.output() - } -} - impl StorageScore for DelegationOutput { fn storage_score(&self, params: StorageScoreParameters) -> u64 { params.output_offset() @@ -396,6 +390,12 @@ impl StorageScore for DelegationOutput { } } +impl WorkScore for DelegationOutput { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.output() + } +} + impl MinimumOutputAmount for DelegationOutput {} fn verify_validator_address(validator_address: &AccountAddress) -> Result<(), Error> { diff --git a/sdk/src/types/block/output/feature/block_issuer.rs b/sdk/src/types/block/output/feature/block_issuer.rs index 545d1b4f13..114226b14c 100644 --- a/sdk/src/types/block/output/feature/block_issuer.rs +++ b/sdk/src/types/block/output/feature/block_issuer.rs @@ -18,6 +18,7 @@ use packable::{ use crate::types::block::{ output::{StorageScore, StorageScoreParameters}, + protocol::{WorkScore, WorkScoreParameters}, slot::SlotIndex, Error, }; @@ -244,6 +245,12 @@ impl StorageScore for BlockIssuerFeature { } } +impl WorkScore for BlockIssuerFeature { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.block_issuer() + } +} + #[cfg(feature = "serde")] mod dto { use alloc::{string::String, vec::Vec}; diff --git a/sdk/src/types/block/output/feature/mod.rs b/sdk/src/types/block/output/feature/mod.rs index 4a65e603e4..85690bcc36 100644 --- a/sdk/src/types/block/output/feature/mod.rs +++ b/sdk/src/types/block/output/feature/mod.rs @@ -257,25 +257,25 @@ impl Features { } } +impl StorageScore for Features { + fn storage_score(&self, params: StorageScoreParameters) -> u64 { + self.iter().map(|f| f.storage_score(params)).sum::() + } +} + impl WorkScore for Features { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { + fn work_score(&self, params: WorkScoreParameters) -> u32 { self.iter() .map(|f| match f { - Feature::BlockIssuer(_) => work_score_params.block_issuer(), - Feature::NativeToken(_) => work_score_params.native_token(), - Feature::Staking(_) => work_score_params.staking(), + Feature::BlockIssuer(block_issuer) => block_issuer.work_score(params), + Feature::NativeToken(native_token) => native_token.work_score(params), + Feature::Staking(staking) => staking.work_score(params), _ => 0, }) .sum() } } -impl StorageScore for Features { - fn storage_score(&self, params: StorageScoreParameters) -> u64 { - self.iter().map(|f| f.storage_score(params)).sum::() - } -} - #[inline] fn verify_unique_sorted(features: &[Feature]) -> Result<(), Error> { if VERIFY && !is_unique_sorted(features.iter().map(Feature::kind)) { diff --git a/sdk/src/types/block/output/feature/native_token.rs b/sdk/src/types/block/output/feature/native_token.rs index 191fec2070..1cf0b766ba 100644 --- a/sdk/src/types/block/output/feature/native_token.rs +++ b/sdk/src/types/block/output/feature/native_token.rs @@ -3,7 +3,10 @@ use derive_more::{Deref, From}; -use crate::types::block::output::{NativeToken, StorageScore}; +use crate::types::block::{ + output::{NativeToken, StorageScore}, + protocol::{WorkScore, WorkScoreParameters}, +}; #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Deref, From, packable::Packable)] pub struct NativeTokenFeature(NativeToken); @@ -25,6 +28,12 @@ impl NativeTokenFeature { impl StorageScore for NativeTokenFeature {} +impl WorkScore for NativeTokenFeature { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.native_token() + } +} + #[cfg(feature = "serde")] mod dto { use primitive_types::U256; diff --git a/sdk/src/types/block/output/feature/staking.rs b/sdk/src/types/block/output/feature/staking.rs index 34d8da0094..c56b71b838 100644 --- a/sdk/src/types/block/output/feature/staking.rs +++ b/sdk/src/types/block/output/feature/staking.rs @@ -3,6 +3,7 @@ use crate::types::block::{ output::{StorageScore, StorageScoreParameters}, + protocol::{WorkScore, WorkScoreParameters}, slot::EpochIndex, }; @@ -65,6 +66,12 @@ impl StorageScore for StakingFeature { } } +impl WorkScore for StakingFeature { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.staking() + } +} + #[cfg(feature = "serde")] mod dto { use serde::{Deserialize, Serialize}; diff --git a/sdk/src/types/block/output/foundry.rs b/sdk/src/types/block/output/foundry.rs index 651e44dee0..08fc8aa84d 100644 --- a/sdk/src/types/block/output/foundry.rs +++ b/sdk/src/types/block/output/foundry.rs @@ -511,15 +511,12 @@ impl StorageScore for FoundryOutput { } impl WorkScore for FoundryOutput { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - work_score_params.output() - + self.features().work_score(work_score_params) - + self.immutable_features().work_score(work_score_params) - + self - .token_scheme() - .is_simple() - .then_some(work_score_params.native_token()) - .unwrap_or(0) + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.output() + + self.token_scheme().work_score(params) + + self.unlock_conditions().work_score(params) + + self.features().work_score(params) + + self.immutable_features().work_score(params) } } diff --git a/sdk/src/types/block/output/mod.rs b/sdk/src/types/block/output/mod.rs index ea441cb3c8..d7253f2ebc 100644 --- a/sdk/src/types/block/output/mod.rs +++ b/sdk/src/types/block/output/mod.rs @@ -393,12 +393,25 @@ impl Output { impl StorageScore for Output { fn storage_score(&self, params: StorageScoreParameters) -> u64 { match self { - Self::Basic(o) => o.storage_score(params), - Self::Account(o) => o.storage_score(params), - Self::Anchor(o) => o.storage_score(params), - Self::Foundry(o) => o.storage_score(params), - Self::Nft(o) => o.storage_score(params), - Self::Delegation(o) => o.storage_score(params), + Self::Basic(basic) => basic.storage_score(params), + Self::Account(account) => account.storage_score(params), + Self::Anchor(anchor) => anchor.storage_score(params), + Self::Foundry(foundry) => foundry.storage_score(params), + Self::Nft(nft) => nft.storage_score(params), + Self::Delegation(delegation) => delegation.storage_score(params), + } + } +} + +impl WorkScore for Output { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + match self { + Self::Basic(basic) => basic.work_score(params), + Self::Account(account) => account.work_score(params), + Self::Anchor(anchor) => anchor.work_score(params), + Self::Foundry(foundry) => foundry.work_score(params), + Self::Nft(nft) => nft.work_score(params), + Self::Delegation(delegation) => delegation.work_score(params), } } } @@ -414,19 +427,6 @@ pub trait MinimumOutputAmount: StorageScore { } } -impl WorkScore for Output { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - match self { - Self::Basic(basic) => basic.work_score(work_score_params), - Self::Account(account) => account.work_score(work_score_params), - Self::Anchor(anchor) => anchor.work_score(work_score_params), - Self::Foundry(foundry) => foundry.work_score(work_score_params), - Self::Nft(nft) => nft.work_score(work_score_params), - Self::Delegation(delegation) => delegation.work_score(work_score_params), - } - } -} - #[cfg(feature = "serde")] pub mod dto { use alloc::format; diff --git a/sdk/src/types/block/output/native_token.rs b/sdk/src/types/block/output/native_token.rs index 30328e7aa0..ecd8cf6e32 100644 --- a/sdk/src/types/block/output/native_token.rs +++ b/sdk/src/types/block/output/native_token.rs @@ -70,6 +70,12 @@ impl NativeToken { } } +impl WorkScore for NativeToken { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.native_token() + } +} + impl PartialOrd for NativeToken { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -256,8 +262,8 @@ impl NativeTokens { } impl WorkScore for NativeTokens { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - self.len() as u32 * work_score_params.native_token() + fn work_score(&self, params: WorkScoreParameters) -> u32 { + self.iter().map(|nt| nt.work_score(params)).sum() } } diff --git a/sdk/src/types/block/output/nft.rs b/sdk/src/types/block/output/nft.rs index 04c119dacb..9248ba1215 100644 --- a/sdk/src/types/block/output/nft.rs +++ b/sdk/src/types/block/output/nft.rs @@ -452,10 +452,8 @@ impl StorageScore for NftOutput { } impl WorkScore for NftOutput { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - work_score_params.output() - + self.features().work_score(work_score_params) - + self.immutable_features().work_score(work_score_params) + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.output() + self.features().work_score(params) + self.immutable_features().work_score(params) } } diff --git a/sdk/src/types/block/output/token_scheme/mod.rs b/sdk/src/types/block/output/token_scheme/mod.rs index 25ff493749..91303f0ea1 100644 --- a/sdk/src/types/block/output/token_scheme/mod.rs +++ b/sdk/src/types/block/output/token_scheme/mod.rs @@ -4,7 +4,10 @@ mod simple; pub use self::simple::SimpleTokenScheme; -use crate::types::block::Error; +use crate::types::block::{ + protocol::{WorkScore, WorkScoreParameters}, + Error, +}; /// #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, derive_more::From, packable::Packable)] @@ -35,3 +38,11 @@ impl TokenScheme { crate::def_is_as_opt!(TokenScheme: Simple); } + +impl WorkScore for TokenScheme { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + match self { + Self::Simple(simple) => simple.work_score(params), + } + } +} diff --git a/sdk/src/types/block/output/token_scheme/simple.rs b/sdk/src/types/block/output/token_scheme/simple.rs index 1a971d91c6..a66f38e62e 100644 --- a/sdk/src/types/block/output/token_scheme/simple.rs +++ b/sdk/src/types/block/output/token_scheme/simple.rs @@ -4,7 +4,7 @@ use packable::Packable; use primitive_types::U256; -use crate::types::block::Error; +use crate::types::block::{protocol::WorkScore, Error}; /// #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Packable)] @@ -70,6 +70,9 @@ impl SimpleTokenScheme { } } +// TODO: double check with TIP +impl WorkScore for SimpleTokenScheme {} + #[inline] fn verify_simple_token_scheme(token_scheme: &SimpleTokenScheme) -> Result<(), Error> { if VERIFY diff --git a/sdk/src/types/block/output/unlock_condition/mod.rs b/sdk/src/types/block/output/unlock_condition/mod.rs index 0c3e2d3d70..6bce0d21b6 100644 --- a/sdk/src/types/block/output/unlock_condition/mod.rs +++ b/sdk/src/types/block/output/unlock_condition/mod.rs @@ -26,7 +26,7 @@ pub use self::{ use crate::types::block::{ address::Address, output::{StorageScore, StorageScoreParameters}, - protocol::ProtocolParameters, + protocol::{ProtocolParameters, WorkScore, WorkScoreParameters}, slot::SlotIndex, Error, }; @@ -85,6 +85,13 @@ impl StorageScore for UnlockCondition { } } +impl WorkScore for UnlockCondition { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + // TODO: double-check with TIP + 0 + } +} + impl core::fmt::Debug for UnlockCondition { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { @@ -304,7 +311,13 @@ impl UnlockConditions { impl StorageScore for UnlockConditions { fn storage_score(&self, params: StorageScoreParameters) -> u64 { - self.iter().map(|uc| uc.storage_score(params)).sum::() + self.iter().map(|uc| uc.storage_score(params)).sum() + } +} + +impl WorkScore for UnlockConditions { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + self.iter().map(|uc| uc.work_score(params)).sum() } } diff --git a/sdk/src/types/block/payload/candidacy_announcement.rs b/sdk/src/types/block/payload/candidacy_announcement.rs index 87313d9bd2..5f2778a968 100644 --- a/sdk/src/types/block/payload/candidacy_announcement.rs +++ b/sdk/src/types/block/payload/candidacy_announcement.rs @@ -3,6 +3,8 @@ use packable::Packable; +use crate::types::block::protocol::WorkScore; + /// A payload which is used to indicate candidacy for committee selection for the next epoch. #[derive(Clone, Debug, Eq, PartialEq, Packable)] pub struct CandidacyAnnouncementPayload; @@ -11,3 +13,6 @@ impl CandidacyAnnouncementPayload { /// The [`Payload`](crate::types::block::payload::Payload) kind of a [`CandidacyAnnouncementPayload`]. pub const KIND: u8 = 2; } + +// # TODO: check with TIP +impl WorkScore for CandidacyAnnouncementPayload {} diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index 172a1915b3..3894980f85 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -81,15 +81,12 @@ impl Payload { } impl WorkScore for Payload { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { + fn work_score(&self, params: WorkScoreParameters) -> u32 { // 1 byte for the payload kind 1 + match self { - Self::SignedTransaction(signed_transaction) => signed_transaction.work_score(work_score_params), - Self::TaggedData(tagged_data) => tagged_data.work_score(work_score_params), - Self::CandidacyAnnouncement(candidacy_announcement) => { - // TODO: Issue #0000 - todo!("work score for candidacy announcement payload") - } + Self::SignedTransaction(signed_transaction) => signed_transaction.work_score(params), + Self::TaggedData(tagged_data) => tagged_data.work_score(params), + Self::CandidacyAnnouncement(candidacy_announcement) => candidacy_announcement.work_score(params), } } } diff --git a/sdk/src/types/block/payload/signed_transaction/mod.rs b/sdk/src/types/block/payload/signed_transaction/mod.rs index 9b7c65cd0c..a727f5bc54 100644 --- a/sdk/src/types/block/payload/signed_transaction/mod.rs +++ b/sdk/src/types/block/payload/signed_transaction/mod.rs @@ -49,10 +49,10 @@ impl SignedTransactionPayload { } impl WorkScore for SignedTransactionPayload { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - self.packed_len() as u32 * work_score_params.data_byte() - + self.transaction().work_score(work_score_params) - + self.unlocks().work_score(work_score_params) + fn work_score(&self, params: WorkScoreParameters) -> u32 { + self.packed_len() as u32 * params.data_byte() + + self.transaction().work_score(params) + + self.unlocks().work_score(params) } } diff --git a/sdk/src/types/block/payload/signed_transaction/transaction.rs b/sdk/src/types/block/payload/signed_transaction/transaction.rs index 914c975fce..50a1989edb 100644 --- a/sdk/src/types/block/payload/signed_transaction/transaction.rs +++ b/sdk/src/types/block/payload/signed_transaction/transaction.rs @@ -325,11 +325,11 @@ impl Transaction { } impl WorkScore for Transaction { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - self.inputs().len() as u32 * work_score_params.input() - + self.context_inputs().len() as u32 * work_score_params.context_input() - + self.outputs().work_score(work_score_params) - + self.mana_allotments().len() as u32 * work_score_params.allotment() + fn work_score(&self, params: WorkScoreParameters) -> u32 { + self.inputs().len() as u32 * params.input() + + self.context_inputs().len() as u32 * params.context_input() + + self.outputs().work_score(params) + + self.mana_allotments().len() as u32 * params.allotment() } } diff --git a/sdk/src/types/block/payload/tagged_data.rs b/sdk/src/types/block/payload/tagged_data.rs index 887eb776b0..4a5729c52f 100644 --- a/sdk/src/types/block/payload/tagged_data.rs +++ b/sdk/src/types/block/payload/tagged_data.rs @@ -60,8 +60,8 @@ impl TaggedDataPayload { } impl WorkScore for TaggedDataPayload { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - self.packed_len() as u32 * work_score_params.data_byte() + fn work_score(&self, params: WorkScoreParameters) -> u32 { + self.packed_len() as u32 * params.data_byte() } } diff --git a/sdk/src/types/block/protocol/work_score.rs b/sdk/src/types/block/protocol/work_score.rs index c60ca2e916..32f6f77b26 100644 --- a/sdk/src/types/block/protocol/work_score.rs +++ b/sdk/src/types/block/protocol/work_score.rs @@ -56,23 +56,25 @@ impl Default for WorkScoreParameters { /// A trait to facilitate the computation of the work score of a block, which is central to mana cost calculation. pub trait WorkScore { - /// Returns its work score. - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32; + /// Returns its work score. Defaults to 0. + fn work_score(&self, params: WorkScoreParameters) -> u32 { + 0 + } /// Returns the Mana cost given its work score. - fn mana_cost(&self, work_score_params: WorkScoreParameters, reference_mana_cost: u64) -> u64 { - reference_mana_cost * self.work_score(work_score_params) as u64 + fn mana_cost(&self, params: WorkScoreParameters, reference_mana_cost: u64) -> u64 { + reference_mana_cost * self.work_score(params) as u64 } } impl WorkScore for [T; N] { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - self.as_slice().work_score(work_score_params) + fn work_score(&self, params: WorkScoreParameters) -> u32 { + self.as_slice().work_score(params) } } impl WorkScore for [T] { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { - self.iter().map(|o| o.work_score(work_score_params)).sum() + fn work_score(&self, params: WorkScoreParameters) -> u32 { + self.iter().map(|o| o.work_score(params)).sum() } } diff --git a/sdk/src/types/block/signature/ed25519.rs b/sdk/src/types/block/signature/ed25519.rs index 69361c2309..d67abc4bb8 100644 --- a/sdk/src/types/block/signature/ed25519.rs +++ b/sdk/src/types/block/signature/ed25519.rs @@ -14,7 +14,11 @@ use packable::{ Packable, }; -use crate::types::block::{address::Ed25519Address, Error}; +use crate::types::block::{ + address::Ed25519Address, + protocol::{WorkScore, WorkScoreParameters}, + Error, +}; /// An Ed25519 signature. #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] @@ -104,6 +108,12 @@ impl fmt::Debug for Ed25519Signature { } } +impl WorkScore for Ed25519Signature { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.signature_ed25519() + } +} + impl Packable for Ed25519Signature { type UnpackError = Error; type UnpackVisitor = (); diff --git a/sdk/src/types/block/signature/mod.rs b/sdk/src/types/block/signature/mod.rs index b30e557298..740a8a8279 100644 --- a/sdk/src/types/block/signature/mod.rs +++ b/sdk/src/types/block/signature/mod.rs @@ -46,9 +46,9 @@ impl Signature { } impl WorkScore for Signature { - fn work_score(&self, workscore_structure: WorkScoreParameters) -> u32 { + fn work_score(&self, params: WorkScoreParameters) -> u32 { match self { - Self::Ed25519(_) => workscore_structure.signature_ed25519(), + Self::Ed25519(ed25519) => ed25519.work_score(params), } } } diff --git a/sdk/src/types/block/unlock/mod.rs b/sdk/src/types/block/unlock/mod.rs index 1f4ade5275..fcc56d930c 100644 --- a/sdk/src/types/block/unlock/mod.rs +++ b/sdk/src/types/block/unlock/mod.rs @@ -135,9 +135,9 @@ impl Unlocks { } impl WorkScore for Unlocks { - fn work_score(&self, work_score_params: WorkScoreParameters) -> u32 { + fn work_score(&self, params: WorkScoreParameters) -> u32 { self.iter() - .filter_map(|u| u.is_signature().then_some(work_score_params.signature_ed25519())) + .filter_map(|u| u.is_signature().then_some(params.signature_ed25519())) .sum() } } From 913a5b6c6417a05bfb829bcddb7b0a5165168ce4 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Tue, 21 Nov 2023 19:16:28 +0100 Subject: [PATCH 25/42] nit --- sdk/src/types/block/output/unlock_condition/mod.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sdk/src/types/block/output/unlock_condition/mod.rs b/sdk/src/types/block/output/unlock_condition/mod.rs index 6bce0d21b6..540d65a613 100644 --- a/sdk/src/types/block/output/unlock_condition/mod.rs +++ b/sdk/src/types/block/output/unlock_condition/mod.rs @@ -85,12 +85,8 @@ impl StorageScore for UnlockCondition { } } -impl WorkScore for UnlockCondition { - fn work_score(&self, params: WorkScoreParameters) -> u32 { - // TODO: double-check with TIP - 0 - } -} +// TODO: check with TIP +impl WorkScore for UnlockCondition {} impl core::fmt::Debug for UnlockCondition { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { From 87d56af32582f71cf192c5a79bfcb9735fb8bf3e Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Wed, 22 Nov 2023 17:01:00 +0100 Subject: [PATCH 26/42] default impl for all features --- sdk/src/types/block/output/feature/issuer.rs | 3 ++ .../types/block/output/feature/metadata.rs | 42 ++++++++++--------- sdk/src/types/block/output/feature/mod.rs | 37 +++++++++------- sdk/src/types/block/output/feature/sender.rs | 3 ++ sdk/src/types/block/output/feature/tag.rs | 40 +++++++++--------- 5 files changed, 71 insertions(+), 54 deletions(-) diff --git a/sdk/src/types/block/output/feature/issuer.rs b/sdk/src/types/block/output/feature/issuer.rs index fe96f195f0..fe929e0006 100644 --- a/sdk/src/types/block/output/feature/issuer.rs +++ b/sdk/src/types/block/output/feature/issuer.rs @@ -6,6 +6,7 @@ use derive_more::From; use crate::types::block::{ address::Address, output::{StorageScore, StorageScoreParameters}, + protocol::WorkScore, }; /// Identifies the validated issuer of the UTXO state machine. @@ -35,6 +36,8 @@ impl StorageScore for IssuerFeature { } } +impl WorkScore for IssuerFeature {} + #[cfg(feature = "serde")] mod dto { use serde::{Deserialize, Serialize}; diff --git a/sdk/src/types/block/output/feature/metadata.rs b/sdk/src/types/block/output/feature/metadata.rs index b198e8c9f2..434235ff5b 100644 --- a/sdk/src/types/block/output/feature/metadata.rs +++ b/sdk/src/types/block/output/feature/metadata.rs @@ -6,7 +6,7 @@ use core::{ops::RangeInclusive, str::FromStr}; use packable::{bounded::BoundedU16, prefix::BoxedSlicePrefix}; -use crate::types::block::{output::StorageScore, Error}; +use crate::types::block::{output::StorageScore, protocol::WorkScore, Error}; pub(crate) type MetadataFeatureLength = BoundedU16<{ *MetadataFeature::LENGTH_RANGE.start() }, { *MetadataFeature::LENGTH_RANGE.end() }>; @@ -19,8 +19,29 @@ pub struct MetadataFeature( pub(crate) BoxedSlicePrefix, ); +impl MetadataFeature { + /// The [`Feature`](crate::types::block::output::Feature) kind of [`MetadataFeature`]. + pub const KIND: u8 = 2; + /// Valid lengths for a [`MetadataFeature`]. + pub const LENGTH_RANGE: RangeInclusive = 1..=8192; + + /// Creates a new [`MetadataFeature`]. + #[inline(always)] + pub fn new(data: impl Into>) -> Result { + Self::try_from(data.into()) + } + + /// Returns the data. + #[inline(always)] + pub fn data(&self) -> &[u8] { + &self.0 + } +} + impl StorageScore for MetadataFeature {} +impl WorkScore for MetadataFeature {} + macro_rules! impl_from_vec { ($type:ty) => { impl TryFrom<$type> for MetadataFeature { @@ -68,25 +89,6 @@ impl FromStr for MetadataFeature { } } -impl MetadataFeature { - /// The [`Feature`](crate::types::block::output::Feature) kind of [`MetadataFeature`]. - pub const KIND: u8 = 2; - /// Valid lengths for a [`MetadataFeature`]. - pub const LENGTH_RANGE: RangeInclusive = 1..=8192; - - /// Creates a new [`MetadataFeature`]. - #[inline(always)] - pub fn new(data: impl Into>) -> Result { - Self::try_from(data.into()) - } - - /// Returns the data. - #[inline(always)] - pub fn data(&self) -> &[u8] { - &self.0 - } -} - impl core::fmt::Display for MetadataFeature { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{}", prefix_hex::encode(self.data())) diff --git a/sdk/src/types/block/output/feature/mod.rs b/sdk/src/types/block/output/feature/mod.rs index 85690bcc36..0b0c24ebed 100644 --- a/sdk/src/types/block/output/feature/mod.rs +++ b/sdk/src/types/block/output/feature/mod.rs @@ -80,13 +80,27 @@ impl Ord for Feature { impl StorageScore for Feature { fn storage_score(&self, params: StorageScoreParameters) -> u64 { match self { - Self::Sender(feature) => feature.storage_score(params), - Self::Issuer(feature) => feature.storage_score(params), - Self::Metadata(feature) => feature.storage_score(params), - Self::Tag(feature) => feature.storage_score(params), - Self::NativeToken(feature) => feature.storage_score(params), - Self::BlockIssuer(feature) => feature.storage_score(params), - Self::Staking(feature) => feature.storage_score(params), + Self::Sender(sender) => sender.storage_score(params), + Self::Issuer(issuer) => issuer.storage_score(params), + Self::Metadata(metadata) => metadata.storage_score(params), + Self::Tag(tag) => tag.storage_score(params), + Self::NativeToken(native_token) => native_token.storage_score(params), + Self::BlockIssuer(block_issuer) => block_issuer.storage_score(params), + Self::Staking(staking) => staking.storage_score(params), + } + } +} + +impl WorkScore for Feature { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + match self { + Self::Sender(sender) => sender.work_score(params), + Self::Issuer(issuer) => issuer.work_score(params), + Self::Metadata(metadata) => metadata.work_score(params), + Self::Tag(tag) => tag.work_score(params), + Self::NativeToken(native_token) => native_token.work_score(params), + Self::BlockIssuer(block_issuer) => block_issuer.work_score(params), + Self::Staking(staking) => staking.work_score(params), } } } @@ -265,14 +279,7 @@ impl StorageScore for Features { impl WorkScore for Features { fn work_score(&self, params: WorkScoreParameters) -> u32 { - self.iter() - .map(|f| match f { - Feature::BlockIssuer(block_issuer) => block_issuer.work_score(params), - Feature::NativeToken(native_token) => native_token.work_score(params), - Feature::Staking(staking) => staking.work_score(params), - _ => 0, - }) - .sum() + self.iter().map(|feature| feature.work_score(params)).sum() } } diff --git a/sdk/src/types/block/output/feature/sender.rs b/sdk/src/types/block/output/feature/sender.rs index f25ab1d97c..c53e70b7d7 100644 --- a/sdk/src/types/block/output/feature/sender.rs +++ b/sdk/src/types/block/output/feature/sender.rs @@ -6,6 +6,7 @@ use derive_more::From; use crate::types::block::{ address::Address, output::{storage_score::StorageScoreParameters, StorageScore}, + protocol::WorkScore, }; /// Identifies the validated sender of an output. @@ -35,6 +36,8 @@ impl StorageScore for SenderFeature { } } +impl WorkScore for SenderFeature {} + #[cfg(feature = "serde")] mod dto { use serde::{Deserialize, Serialize}; diff --git a/sdk/src/types/block/output/feature/tag.rs b/sdk/src/types/block/output/feature/tag.rs index 01c84d79cd..e150834d6f 100644 --- a/sdk/src/types/block/output/feature/tag.rs +++ b/sdk/src/types/block/output/feature/tag.rs @@ -6,7 +6,7 @@ use core::ops::RangeInclusive; use packable::{bounded::BoundedU8, prefix::BoxedSlicePrefix}; -use crate::types::block::{output::StorageScore, Error}; +use crate::types::block::{output::StorageScore, protocol::WorkScore, Error}; pub(crate) type TagFeatureLength = BoundedU8<{ *TagFeature::LENGTH_RANGE.start() }, { *TagFeature::LENGTH_RANGE.end() }>; @@ -19,24 +19,6 @@ pub struct TagFeature( pub(crate) BoxedSlicePrefix, ); -impl StorageScore for TagFeature {} - -impl TryFrom> for TagFeature { - type Error = Error; - - fn try_from(tag: Vec) -> Result { - tag.into_boxed_slice().try_into() - } -} - -impl TryFrom> for TagFeature { - type Error = Error; - - fn try_from(tag: Box<[u8]>) -> Result { - tag.try_into().map(Self).map_err(Error::InvalidTagFeatureLength) - } -} - impl TagFeature { /// The [`Feature`](crate::types::block::output::Feature) kind of an [`TagFeature`]. pub const KIND: u8 = 4; @@ -56,6 +38,26 @@ impl TagFeature { } } +impl StorageScore for TagFeature {} + +impl WorkScore for TagFeature {} + +impl TryFrom> for TagFeature { + type Error = Error; + + fn try_from(tag: Vec) -> Result { + tag.into_boxed_slice().try_into() + } +} + +impl TryFrom> for TagFeature { + type Error = Error; + + fn try_from(tag: Box<[u8]>) -> Result { + tag.try_into().map(Self).map_err(Error::InvalidTagFeatureLength) + } +} + impl core::fmt::Display for TagFeature { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{}", prefix_hex::encode(self.tag())) From 9861038d1b2aad1978eae684f4705914d3c9994c Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Wed, 22 Nov 2023 17:18:18 +0100 Subject: [PATCH 27/42] default impl for all unlocks --- .../block/output/unlock_condition/mod.rs | 14 ++--- sdk/src/types/block/unlock/account.rs | 20 +++---- sdk/src/types/block/unlock/anchor.rs | 20 +++---- sdk/src/types/block/unlock/empty.rs | 4 ++ sdk/src/types/block/unlock/mod.rs | 52 ++++++++++++------- sdk/src/types/block/unlock/multi.rs | 4 +- sdk/src/types/block/unlock/nft.rs | 20 +++---- sdk/src/types/block/unlock/reference.rs | 4 +- sdk/src/types/block/unlock/signature.rs | 11 +++- 9 files changed, 92 insertions(+), 57 deletions(-) diff --git a/sdk/src/types/block/output/unlock_condition/mod.rs b/sdk/src/types/block/output/unlock_condition/mod.rs index 540d65a613..dde97b7a0d 100644 --- a/sdk/src/types/block/output/unlock_condition/mod.rs +++ b/sdk/src/types/block/output/unlock_condition/mod.rs @@ -91,13 +91,13 @@ impl WorkScore for UnlockCondition {} impl core::fmt::Debug for UnlockCondition { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Self::Address(unlock_condition) => unlock_condition.fmt(f), - Self::StorageDepositReturn(unlock_condition) => unlock_condition.fmt(f), - Self::Timelock(unlock_condition) => unlock_condition.fmt(f), - Self::Expiration(unlock_condition) => unlock_condition.fmt(f), - Self::StateControllerAddress(unlock_condition) => unlock_condition.fmt(f), - Self::GovernorAddress(unlock_condition) => unlock_condition.fmt(f), - Self::ImmutableAccountAddress(unlock_condition) => unlock_condition.fmt(f), + Self::Address(uc) => uc.fmt(f), + Self::StorageDepositReturn(uc) => uc.fmt(f), + Self::Timelock(uc) => uc.fmt(f), + Self::Expiration(uc) => uc.fmt(f), + Self::StateControllerAddress(uc) => uc.fmt(f), + Self::GovernorAddress(uc) => uc.fmt(f), + Self::ImmutableAccountAddress(uc) => uc.fmt(f), } } } diff --git a/sdk/src/types/block/unlock/account.rs b/sdk/src/types/block/unlock/account.rs index f8f7872ac3..b33297478c 100644 --- a/sdk/src/types/block/unlock/account.rs +++ b/sdk/src/types/block/unlock/account.rs @@ -1,7 +1,7 @@ // Copyright 2020-2021 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use crate::types::block::{unlock::UnlockIndex, Error}; +use crate::types::block::{protocol::WorkScore, unlock::UnlockIndex, Error}; /// Points to the unlock of a consumed account output. #[derive(Clone, Debug, Eq, PartialEq, Hash, packable::Packable)] @@ -11,14 +11,6 @@ pub struct AccountUnlock( UnlockIndex, ); -impl TryFrom for AccountUnlock { - type Error = Error; - - fn try_from(index: u16) -> Result { - Self::new(index) - } -} - impl AccountUnlock { /// The [`Unlock`](crate::types::block::unlock::Unlock) kind of an [`AccountUnlock`]. pub const KIND: u8 = 2; @@ -36,6 +28,16 @@ impl AccountUnlock { } } +impl WorkScore for AccountUnlock {} + +impl TryFrom for AccountUnlock { + type Error = Error; + + fn try_from(index: u16) -> Result { + Self::new(index) + } +} + #[cfg(feature = "serde")] mod dto { use serde::{Deserialize, Serialize}; diff --git a/sdk/src/types/block/unlock/anchor.rs b/sdk/src/types/block/unlock/anchor.rs index aad3c49b78..1b0a7a43b2 100644 --- a/sdk/src/types/block/unlock/anchor.rs +++ b/sdk/src/types/block/unlock/anchor.rs @@ -1,7 +1,7 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use crate::types::block::{unlock::UnlockIndex, Error}; +use crate::types::block::{protocol::WorkScore, unlock::UnlockIndex, Error}; /// Points to the unlock of a consumed anchor output. #[derive(Clone, Debug, Eq, PartialEq, Hash, packable::Packable)] @@ -11,14 +11,6 @@ pub struct AnchorUnlock( UnlockIndex, ); -impl TryFrom for AnchorUnlock { - type Error = Error; - - fn try_from(index: u16) -> Result { - Self::new(index) - } -} - impl AnchorUnlock { /// The [`Unlock`](crate::types::block::unlock::Unlock) kind of an [`AnchorUnlock`]. pub const KIND: u8 = 3; @@ -36,6 +28,16 @@ impl AnchorUnlock { } } +impl WorkScore for AnchorUnlock {} + +impl TryFrom for AnchorUnlock { + type Error = Error; + + fn try_from(index: u16) -> Result { + Self::new(index) + } +} + #[cfg(feature = "serde")] mod dto { use serde::{Deserialize, Serialize}; diff --git a/sdk/src/types/block/unlock/empty.rs b/sdk/src/types/block/unlock/empty.rs index 2449e7668f..1778542695 100644 --- a/sdk/src/types/block/unlock/empty.rs +++ b/sdk/src/types/block/unlock/empty.rs @@ -1,6 +1,8 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use crate::types::block::protocol::WorkScore; + /// Used to maintain correct index relationship between addresses and signatures when unlocking a /// [`MultiAddress`](crate::types::block::address::MultiAddress) where not all addresses are unlocked. #[derive(Clone, Debug, Eq, PartialEq, Hash, packable::Packable)] @@ -11,6 +13,8 @@ impl EmptyUnlock { pub const KIND: u8 = 6; } +impl WorkScore for EmptyUnlock {} + #[cfg(feature = "serde")] mod dto { use serde::{Deserialize, Serialize}; diff --git a/sdk/src/types/block/unlock/mod.rs b/sdk/src/types/block/unlock/mod.rs index fcc56d930c..2c8fddc1cb 100644 --- a/sdk/src/types/block/unlock/mod.rs +++ b/sdk/src/types/block/unlock/mod.rs @@ -68,6 +68,37 @@ pub enum Unlock { Empty(EmptyUnlock), } +impl Unlock { + /// Returns the unlock kind of an [`Unlock`]. + pub fn kind(&self) -> u8 { + match self { + Self::Signature(_) => SignatureUnlock::KIND, + Self::Reference(_) => ReferenceUnlock::KIND, + Self::Account(_) => AccountUnlock::KIND, + Self::Anchor(_) => AnchorUnlock::KIND, + Self::Nft(_) => NftUnlock::KIND, + Self::Multi(_) => MultiUnlock::KIND, + Self::Empty(_) => EmptyUnlock::KIND, + } + } + + crate::def_is_as_opt!(Unlock: Signature, Reference, Account, Anchor, Nft, Multi, Empty); +} + +impl WorkScore for Unlock { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + match self { + Self::Signature(unlock) => unlock.work_score(params), + Self::Reference(unlock) => unlock.work_score(params), + Self::Account(unlock) => unlock.work_score(params), + Self::Anchor(unlock) => unlock.work_score(params), + Self::Nft(unlock) => unlock.work_score(params), + Self::Multi(unlock) => unlock.work_score(params), + Self::Empty(unlock) => unlock.work_score(params), + } + } +} + impl From for Unlock { fn from(value: SignatureUnlock) -> Self { Self::Signature(value.into()) @@ -88,23 +119,6 @@ impl core::fmt::Debug for Unlock { } } -impl Unlock { - /// Returns the unlock kind of an [`Unlock`]. - pub fn kind(&self) -> u8 { - match self { - Self::Signature(_) => SignatureUnlock::KIND, - Self::Reference(_) => ReferenceUnlock::KIND, - Self::Account(_) => AccountUnlock::KIND, - Self::Anchor(_) => AnchorUnlock::KIND, - Self::Nft(_) => NftUnlock::KIND, - Self::Multi(_) => MultiUnlock::KIND, - Self::Empty(_) => EmptyUnlock::KIND, - } - } - - crate::def_is_as_opt!(Unlock: Signature, Reference, Account, Anchor, Nft, Multi, Empty); -} - pub(crate) type UnlockCount = BoundedU16<{ *UNLOCK_COUNT_RANGE.start() }, { *UNLOCK_COUNT_RANGE.end() }>; /// A collection of unlocks. @@ -136,9 +150,7 @@ impl Unlocks { impl WorkScore for Unlocks { fn work_score(&self, params: WorkScoreParameters) -> u32 { - self.iter() - .filter_map(|u| u.is_signature().then_some(params.signature_ed25519())) - .sum() + self.iter().map(|unlock| unlock.work_score(params)).sum() } } diff --git a/sdk/src/types/block/unlock/multi.rs b/sdk/src/types/block/unlock/multi.rs index 7cf6dd66f1..b384afa77a 100644 --- a/sdk/src/types/block/unlock/multi.rs +++ b/sdk/src/types/block/unlock/multi.rs @@ -6,7 +6,7 @@ use alloc::boxed::Box; use derive_more::Deref; use packable::{prefix::BoxedSlicePrefix, Packable}; -use crate::types::block::{address::WeightedAddressCount, unlock::Unlock, Error}; +use crate::types::block::{address::WeightedAddressCount, protocol::WorkScore, unlock::Unlock, Error}; pub(crate) type UnlocksCount = WeightedAddressCount; @@ -38,6 +38,8 @@ impl MultiUnlock { } } +impl WorkScore for MultiUnlock {} + fn verify_unlocks(unlocks: &[Unlock]) -> Result<(), Error> { if VERIFY && unlocks.iter().any(Unlock::is_multi) { Err(Error::MultiUnlockRecursion) diff --git a/sdk/src/types/block/unlock/nft.rs b/sdk/src/types/block/unlock/nft.rs index 930b647824..cc7b6d4e79 100644 --- a/sdk/src/types/block/unlock/nft.rs +++ b/sdk/src/types/block/unlock/nft.rs @@ -1,7 +1,7 @@ // Copyright 2020-2021 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use crate::types::block::{unlock::UnlockIndex, Error}; +use crate::types::block::{protocol::WorkScore, unlock::UnlockIndex, Error}; /// Points to the unlock of a consumed NFT output. #[derive(Clone, Debug, Eq, PartialEq, Hash, packable::Packable)] @@ -11,14 +11,6 @@ pub struct NftUnlock( UnlockIndex, ); -impl TryFrom for NftUnlock { - type Error = Error; - - fn try_from(index: u16) -> Result { - Self::new(index) - } -} - impl NftUnlock { /// The [`Unlock`](crate::types::block::unlock::Unlock) kind of a [`NftUnlock`]. pub const KIND: u8 = 4; @@ -36,6 +28,16 @@ impl NftUnlock { } } +impl WorkScore for NftUnlock {} + +impl TryFrom for NftUnlock { + type Error = Error; + + fn try_from(index: u16) -> Result { + Self::new(index) + } +} + #[cfg(feature = "serde")] pub(crate) mod dto { use serde::{Deserialize, Serialize}; diff --git a/sdk/src/types/block/unlock/reference.rs b/sdk/src/types/block/unlock/reference.rs index dc6b76c5d5..feef4e55e5 100644 --- a/sdk/src/types/block/unlock/reference.rs +++ b/sdk/src/types/block/unlock/reference.rs @@ -1,7 +1,7 @@ // Copyright 2020-2021 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use crate::types::block::{unlock::UnlockIndex, Error}; +use crate::types::block::{protocol::WorkScore, unlock::UnlockIndex, Error}; /// An [`Unlock`](crate::types::block::unlock::Unlock) that refers to another unlock. #[derive(Clone, Debug, Eq, PartialEq, Hash, packable::Packable)] @@ -33,6 +33,8 @@ impl ReferenceUnlock { } } +impl WorkScore for ReferenceUnlock {} + #[cfg(feature = "serde")] pub(crate) mod dto { use serde::{Deserialize, Serialize}; diff --git a/sdk/src/types/block/unlock/signature.rs b/sdk/src/types/block/unlock/signature.rs index f5075361c2..2df40c4781 100644 --- a/sdk/src/types/block/unlock/signature.rs +++ b/sdk/src/types/block/unlock/signature.rs @@ -3,7 +3,10 @@ use derive_more::{Deref, From}; -use crate::types::block::signature::Signature; +use crate::types::block::{ + protocol::{WorkScore, WorkScoreParameters}, + signature::Signature, +}; /// An [`Unlock`](crate::types::block::unlock::Unlock) which is used to unlock a signature locked /// [`Input`](crate::types::block::input::Input). @@ -27,6 +30,12 @@ impl SignatureUnlock { } } +impl WorkScore for SignatureUnlock { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.signature_ed25519() + } +} + #[cfg(feature = "serde")] pub(crate) mod dto { use serde::{Deserialize, Serialize}; From d778512d04badb0e2269a6f951a689f6110a7c76 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Wed, 22 Nov 2023 18:18:49 +0100 Subject: [PATCH 28/42] self --- sdk/src/types/block/protocol/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/protocol/mod.rs b/sdk/src/types/block/protocol/mod.rs index c1c32bd675..042312112e 100644 --- a/sdk/src/types/block/protocol/mod.rs +++ b/sdk/src/types/block/protocol/mod.rs @@ -9,8 +9,8 @@ use core::borrow::Borrow; use crypto::hashes::{blake2b::Blake2b256, Digest}; use getset::{CopyGetters, Getters}; use packable::{prefix::StringPrefix, Packable, PackableExt}; -pub use work_score::{WorkScore, WorkScoreParameters}; +pub use self::work_score::{WorkScore, WorkScoreParameters}; use crate::{ types::block::{ address::Hrp, From 5d3d1e0c5bc09172f557da0766ebb4f9f526ec7b Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Thu, 23 Nov 2023 12:13:07 +0100 Subject: [PATCH 29/42] rm WorkScore impl for NativeTokens type --- sdk/src/types/block/output/native_token.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sdk/src/types/block/output/native_token.rs b/sdk/src/types/block/output/native_token.rs index ecd8cf6e32..6e48df309b 100644 --- a/sdk/src/types/block/output/native_token.rs +++ b/sdk/src/types/block/output/native_token.rs @@ -261,12 +261,6 @@ impl NativeTokens { } } -impl WorkScore for NativeTokens { - fn work_score(&self, params: WorkScoreParameters) -> u32 { - self.iter().map(|nt| nt.work_score(params)).sum() - } -} - #[inline] fn verify_unique_sorted(native_tokens: &[NativeToken]) -> Result<(), Error> { if VERIFY && !is_unique_sorted(native_tokens.iter().map(NativeToken::token_id)) { From d23fb61042b7cabb2523f61382bc7e9ae83ee502 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Thu, 23 Nov 2023 17:15:55 +0100 Subject: [PATCH 30/42] review suggestions --- .../context_input/block_issuance_credit.rs | 11 +++++- .../types/block/context_input/commitment.rs | 11 +++++- sdk/src/types/block/context_input/mod.rs | 35 ++++++++++++------ sdk/src/types/block/context_input/reward.rs | 11 +++++- sdk/src/types/block/mana/allotment.rs | 36 ++++++++++++------- .../block/payload/candidacy_announcement.rs | 13 +++++-- sdk/src/types/block/payload/mod.rs | 3 +- .../block/payload/signed_transaction/mod.rs | 3 +- .../payload/signed_transaction/transaction.rs | 12 +++++-- sdk/src/types/block/payload/tagged_data.rs | 3 +- 10 files changed, 103 insertions(+), 35 deletions(-) diff --git a/sdk/src/types/block/context_input/block_issuance_credit.rs b/sdk/src/types/block/context_input/block_issuance_credit.rs index eedde882b9..fececf43f9 100644 --- a/sdk/src/types/block/context_input/block_issuance_credit.rs +++ b/sdk/src/types/block/context_input/block_issuance_credit.rs @@ -3,7 +3,10 @@ use derive_more::{Display, From}; -use crate::types::block::output::AccountId; +use crate::types::block::{ + output::AccountId, + protocol::{WorkScore, WorkScoreParameters}, +}; /// A Block Issuance Credit (BIC) Context Input provides the VM with context for the value of /// the BIC vector of a specific slot. @@ -25,6 +28,12 @@ impl BlockIssuanceCreditContextInput { } } +impl WorkScore for BlockIssuanceCreditContextInput { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.context_input() + } +} + #[cfg(feature = "serde")] mod dto { use serde::{Deserialize, Serialize}; diff --git a/sdk/src/types/block/context_input/commitment.rs b/sdk/src/types/block/context_input/commitment.rs index 23b9bcffe2..c799e7dc3b 100644 --- a/sdk/src/types/block/context_input/commitment.rs +++ b/sdk/src/types/block/context_input/commitment.rs @@ -3,7 +3,10 @@ use derive_more::{Display, From}; -use crate::types::block::slot::SlotCommitmentId; +use crate::types::block::{ + protocol::{WorkScore, WorkScoreParameters}, + slot::SlotCommitmentId, +}; /// A Commitment Context Input references a commitment to a certain slot. #[derive(Clone, Copy, Display, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, From, packable::Packable)] @@ -24,6 +27,12 @@ impl CommitmentContextInput { } } +impl WorkScore for CommitmentContextInput { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.context_input() + } +} + #[cfg(feature = "serde")] mod dto { use serde::{Deserialize, Serialize}; diff --git a/sdk/src/types/block/context_input/mod.rs b/sdk/src/types/block/context_input/mod.rs index 016931f09d..c7972d6bea 100644 --- a/sdk/src/types/block/context_input/mod.rs +++ b/sdk/src/types/block/context_input/mod.rs @@ -14,7 +14,10 @@ pub use self::{ block_issuance_credit::BlockIssuanceCreditContextInput, commitment::CommitmentContextInput, reward::RewardContextInput, }; -use crate::types::block::Error; +use crate::types::block::{ + protocol::{WorkScore, WorkScoreParameters}, + Error, +}; /// The maximum number of context inputs of a transaction. pub const CONTEXT_INPUT_COUNT_MAX: u16 = 128; @@ -39,16 +42,6 @@ pub enum ContextInput { Reward(RewardContextInput), } -impl core::fmt::Debug for ContextInput { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - Self::Commitment(input) => input.fmt(f), - Self::BlockIssuanceCredit(input) => input.fmt(f), - Self::Reward(input) => input.fmt(f), - } - } -} - impl ContextInput { /// Returns the context input kind of a `ContextInput`. pub fn kind(&self) -> u8 { @@ -62,6 +55,26 @@ impl ContextInput { crate::def_is_as_opt!(ContextInput: Commitment, BlockIssuanceCredit, Reward); } +impl WorkScore for ContextInput { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + match self { + Self::Commitment(commitment) => commitment.work_score(params), + Self::BlockIssuanceCredit(bic) => bic.work_score(params), + Self::Reward(reward) => reward.work_score(params), + } + } +} + +impl core::fmt::Debug for ContextInput { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Commitment(input) => input.fmt(f), + Self::BlockIssuanceCredit(input) => input.fmt(f), + Self::Reward(input) => input.fmt(f), + } + } +} + #[cfg(test)] mod tests { use pretty_assertions::assert_eq; diff --git a/sdk/src/types/block/context_input/reward.rs b/sdk/src/types/block/context_input/reward.rs index 12fdb58f5c..347cdaa350 100644 --- a/sdk/src/types/block/context_input/reward.rs +++ b/sdk/src/types/block/context_input/reward.rs @@ -4,7 +4,10 @@ use packable::bounded::BoundedU16; use super::CONTEXT_INPUT_COUNT_RANGE; -use crate::types::block::Error; +use crate::types::block::{ + protocol::{WorkScore, WorkScoreParameters}, + Error, +}; pub(crate) type RewardContextInputIndex = BoundedU16<{ *CONTEXT_INPUT_COUNT_RANGE.start() }, { *CONTEXT_INPUT_COUNT_RANGE.end() }>; @@ -29,6 +32,12 @@ impl RewardContextInput { } } +impl WorkScore for RewardContextInput { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.context_input() + } +} + impl core::fmt::Display for RewardContextInput { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "RewardContextInput({})", self.index()) diff --git a/sdk/src/types/block/mana/allotment.rs b/sdk/src/types/block/mana/allotment.rs index 1069f9aace..dc9295c11d 100644 --- a/sdk/src/types/block/mana/allotment.rs +++ b/sdk/src/types/block/mana/allotment.rs @@ -3,7 +3,11 @@ use packable::Packable; -use crate::types::block::{output::AccountId, protocol::ProtocolParameters, Error}; +use crate::types::block::{ + output::AccountId, + protocol::{ProtocolParameters, WorkScore, WorkScoreParameters}, + Error, +}; /// An allotment of Mana which will be added upon commitment of the slot in which the containing transaction was issued, /// in the form of Block Issuance Credits to the account. @@ -16,18 +20,6 @@ pub struct ManaAllotment { pub(crate) mana: u64, } -impl PartialOrd for ManaAllotment { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for ManaAllotment { - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - self.account_id.cmp(&other.account_id) - } -} - impl ManaAllotment { pub fn new(account_id: AccountId, mana: u64, protocol_params: &ProtocolParameters) -> Result { verify_mana::(&mana, protocol_params)?; @@ -44,6 +36,24 @@ impl ManaAllotment { } } +impl PartialOrd for ManaAllotment { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for ManaAllotment { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.account_id.cmp(&other.account_id) + } +} + +impl WorkScore for ManaAllotment { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.allotment() + } +} + fn verify_mana(mana: &u64, params: &ProtocolParameters) -> Result<(), Error> { if VERIFY && *mana > params.mana_parameters().max_mana() { return Err(Error::InvalidManaValue(*mana)); diff --git a/sdk/src/types/block/payload/candidacy_announcement.rs b/sdk/src/types/block/payload/candidacy_announcement.rs index 5f2778a968..40856c249d 100644 --- a/sdk/src/types/block/payload/candidacy_announcement.rs +++ b/sdk/src/types/block/payload/candidacy_announcement.rs @@ -1,7 +1,7 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use packable::Packable; +use packable::{Packable, PackableExt}; use crate::types::block::protocol::WorkScore; @@ -15,4 +15,13 @@ impl CandidacyAnnouncementPayload { } // # TODO: check with TIP -impl WorkScore for CandidacyAnnouncementPayload {} +impl WorkScore for CandidacyAnnouncementPayload { + fn work_score(&self, params: crate::types::block::protocol::WorkScoreParameters) -> u32 { + // (1 + self.packed_len()) as u32 * params.data_byte() + todo!() + } + + fn mana_cost(&self, params: crate::types::block::protocol::WorkScoreParameters, reference_mana_cost: u64) -> u64 { + reference_mana_cost * self.work_score(params) as u64 + } +} diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index 3894980f85..47b08ff736 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -82,8 +82,7 @@ impl Payload { impl WorkScore for Payload { fn work_score(&self, params: WorkScoreParameters) -> u32 { - // 1 byte for the payload kind - 1 + match self { + match self { Self::SignedTransaction(signed_transaction) => signed_transaction.work_score(params), Self::TaggedData(tagged_data) => tagged_data.work_score(params), Self::CandidacyAnnouncement(candidacy_announcement) => candidacy_announcement.work_score(params), diff --git a/sdk/src/types/block/payload/signed_transaction/mod.rs b/sdk/src/types/block/payload/signed_transaction/mod.rs index a727f5bc54..41a983c453 100644 --- a/sdk/src/types/block/payload/signed_transaction/mod.rs +++ b/sdk/src/types/block/payload/signed_transaction/mod.rs @@ -50,7 +50,8 @@ impl SignedTransactionPayload { impl WorkScore for SignedTransactionPayload { fn work_score(&self, params: WorkScoreParameters) -> u32 { - self.packed_len() as u32 * params.data_byte() + // 1 byte for the payload kind + (1 + self.packed_len() as u32) * params.data_byte() + self.transaction().work_score(params) + self.unlocks().work_score(params) } diff --git a/sdk/src/types/block/payload/signed_transaction/transaction.rs b/sdk/src/types/block/payload/signed_transaction/transaction.rs index 50a1989edb..2a8ab48c08 100644 --- a/sdk/src/types/block/payload/signed_transaction/transaction.rs +++ b/sdk/src/types/block/payload/signed_transaction/transaction.rs @@ -327,9 +327,17 @@ impl Transaction { impl WorkScore for Transaction { fn work_score(&self, params: WorkScoreParameters) -> u32 { self.inputs().len() as u32 * params.input() - + self.context_inputs().len() as u32 * params.context_input() + + self + .context_inputs() + .iter() + .map(|ci| ci.work_score(params)) + .sum::() + self.outputs().work_score(params) - + self.mana_allotments().len() as u32 * params.allotment() + + self + .mana_allotments() + .iter() + .map(|ma| ma.work_score(params)) + .sum::() } } diff --git a/sdk/src/types/block/payload/tagged_data.rs b/sdk/src/types/block/payload/tagged_data.rs index 4a5729c52f..f99a2e280e 100644 --- a/sdk/src/types/block/payload/tagged_data.rs +++ b/sdk/src/types/block/payload/tagged_data.rs @@ -61,7 +61,8 @@ impl TaggedDataPayload { impl WorkScore for TaggedDataPayload { fn work_score(&self, params: WorkScoreParameters) -> u32 { - self.packed_len() as u32 * params.data_byte() + // 1 byte for the payload kind + (1 + self.packed_len() as u32) * params.data_byte() } } From 2fad3326ce0a8ab87e3c70f59f23ab9c10c5aa71 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 24 Nov 2023 09:39:05 +0100 Subject: [PATCH 31/42] align and improve --- sdk/src/types/block/input/mod.rs | 13 +++++++++++- sdk/src/types/block/input/utxo.rs | 13 +++++++++++- sdk/src/types/block/output/account.rs | 5 ++++- sdk/src/types/block/output/anchor.rs | 5 ++++- sdk/src/types/block/output/basic.rs | 2 +- sdk/src/types/block/output/delegation.rs | 2 +- sdk/src/types/block/output/foundry.rs | 8 ++++---- sdk/src/types/block/output/nft.rs | 5 ++++- .../types/block/output/token_scheme/simple.rs | 8 ++++++-- .../block/payload/candidacy_announcement.rs | 4 ++-- .../payload/signed_transaction/transaction.rs | 14 +++---------- sdk/src/types/block/protocol/work_score.rs | 20 +++++++++---------- 12 files changed, 63 insertions(+), 36 deletions(-) diff --git a/sdk/src/types/block/input/mod.rs b/sdk/src/types/block/input/mod.rs index cf65e8b967..0c586bee7b 100644 --- a/sdk/src/types/block/input/mod.rs +++ b/sdk/src/types/block/input/mod.rs @@ -8,7 +8,10 @@ use core::ops::RangeInclusive; use derive_more::From; pub use self::utxo::UtxoInput; -use crate::types::block::Error; +use crate::types::block::{ + protocol::{WorkScore, WorkScoreParameters}, + Error, +}; /// The maximum number of inputs of a transaction. pub const INPUT_COUNT_MAX: u16 = 128; @@ -30,6 +33,14 @@ pub enum Input { Utxo(UtxoInput), } +impl WorkScore for Input { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + match self { + Self::Utxo(utxo) => utxo.work_score(params), + } + } +} + impl core::fmt::Debug for Input { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { diff --git a/sdk/src/types/block/input/utxo.rs b/sdk/src/types/block/input/utxo.rs index 613effb9bc..24f4bcb8ee 100644 --- a/sdk/src/types/block/input/utxo.rs +++ b/sdk/src/types/block/input/utxo.rs @@ -5,7 +5,12 @@ use core::str::FromStr; use derive_more::From; -use crate::types::block::{output::OutputId, payload::signed_transaction::TransactionId, Error}; +use crate::types::block::{ + output::OutputId, + payload::signed_transaction::TransactionId, + protocol::{WorkScore, WorkScoreParameters}, + Error, +}; /// Represents an input referencing an output. #[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, From, packable::Packable)] @@ -26,6 +31,12 @@ impl UtxoInput { } } +impl WorkScore for UtxoInput { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + params.input() + } +} + impl FromStr for UtxoInput { type Err = Error; diff --git a/sdk/src/types/block/output/account.rs b/sdk/src/types/block/output/account.rs index b7b40f9d74..7ed6167793 100644 --- a/sdk/src/types/block/output/account.rs +++ b/sdk/src/types/block/output/account.rs @@ -507,7 +507,10 @@ impl StorageScore for AccountOutput { impl WorkScore for AccountOutput { fn work_score(&self, params: WorkScoreParameters) -> u32 { - params.output() + self.features().work_score(params) + self.immutable_features().work_score(params) + params.output() + + self.unlock_conditions.work_score(params) + + self.features.work_score(params) + + self.immutable_features.work_score(params) } } diff --git a/sdk/src/types/block/output/anchor.rs b/sdk/src/types/block/output/anchor.rs index 43a5605217..ddf81a8a36 100644 --- a/sdk/src/types/block/output/anchor.rs +++ b/sdk/src/types/block/output/anchor.rs @@ -507,7 +507,10 @@ impl StorageScore for AnchorOutput { impl WorkScore for AnchorOutput { fn work_score(&self, params: WorkScoreParameters) -> u32 { - params.output() + self.features().work_score(params) + self.immutable_features().work_score(params) + params.output() + + self.unlock_conditions.work_score(params) + + self.features.work_score(params) + + self.immutable_features.work_score(params) } } diff --git a/sdk/src/types/block/output/basic.rs b/sdk/src/types/block/output/basic.rs index cc391f7e5e..05fd6ee74b 100644 --- a/sdk/src/types/block/output/basic.rs +++ b/sdk/src/types/block/output/basic.rs @@ -370,7 +370,7 @@ impl StorageScore for BasicOutput { impl WorkScore for BasicOutput { fn work_score(&self, params: WorkScoreParameters) -> u32 { - params.output() + self.features().work_score(params) + params.output() + self.unlock_conditions.work_score(params) + self.features.work_score(params) } } diff --git a/sdk/src/types/block/output/delegation.rs b/sdk/src/types/block/output/delegation.rs index 7ddc1a3c7d..61bdb1464a 100644 --- a/sdk/src/types/block/output/delegation.rs +++ b/sdk/src/types/block/output/delegation.rs @@ -392,7 +392,7 @@ impl StorageScore for DelegationOutput { impl WorkScore for DelegationOutput { fn work_score(&self, params: WorkScoreParameters) -> u32 { - params.output() + params.output() + self.unlock_conditions.work_score(params) } } diff --git a/sdk/src/types/block/output/foundry.rs b/sdk/src/types/block/output/foundry.rs index 08fc8aa84d..218c526979 100644 --- a/sdk/src/types/block/output/foundry.rs +++ b/sdk/src/types/block/output/foundry.rs @@ -513,10 +513,10 @@ impl StorageScore for FoundryOutput { impl WorkScore for FoundryOutput { fn work_score(&self, params: WorkScoreParameters) -> u32 { params.output() - + self.token_scheme().work_score(params) - + self.unlock_conditions().work_score(params) - + self.features().work_score(params) - + self.immutable_features().work_score(params) + + self.token_scheme.work_score(params) + + self.unlock_conditions.work_score(params) + + self.features.work_score(params) + + self.immutable_features.work_score(params) } } diff --git a/sdk/src/types/block/output/nft.rs b/sdk/src/types/block/output/nft.rs index 9248ba1215..f8462da2a9 100644 --- a/sdk/src/types/block/output/nft.rs +++ b/sdk/src/types/block/output/nft.rs @@ -453,7 +453,10 @@ impl StorageScore for NftOutput { impl WorkScore for NftOutput { fn work_score(&self, params: WorkScoreParameters) -> u32 { - params.output() + self.features().work_score(params) + self.immutable_features().work_score(params) + params.output() + + self.unlock_conditions.work_score(params) + + self.features.work_score(params) + + self.immutable_features.work_score(params) } } diff --git a/sdk/src/types/block/output/token_scheme/simple.rs b/sdk/src/types/block/output/token_scheme/simple.rs index a66f38e62e..f27e33dfce 100644 --- a/sdk/src/types/block/output/token_scheme/simple.rs +++ b/sdk/src/types/block/output/token_scheme/simple.rs @@ -70,8 +70,12 @@ impl SimpleTokenScheme { } } -// TODO: double check with TIP -impl WorkScore for SimpleTokenScheme {} +// TODO: double check with TIP whetehr this is still correct +impl WorkScore for SimpleTokenScheme { + fn work_score(&self, params: crate::types::block::protocol::WorkScoreParameters) -> u32 { + params.native_token() + } +} #[inline] fn verify_simple_token_scheme(token_scheme: &SimpleTokenScheme) -> Result<(), Error> { diff --git a/sdk/src/types/block/payload/candidacy_announcement.rs b/sdk/src/types/block/payload/candidacy_announcement.rs index 40856c249d..597b6a0356 100644 --- a/sdk/src/types/block/payload/candidacy_announcement.rs +++ b/sdk/src/types/block/payload/candidacy_announcement.rs @@ -17,8 +17,8 @@ impl CandidacyAnnouncementPayload { // # TODO: check with TIP impl WorkScore for CandidacyAnnouncementPayload { fn work_score(&self, params: crate::types::block::protocol::WorkScoreParameters) -> u32 { - // (1 + self.packed_len()) as u32 * params.data_byte() - todo!() + // 1 byte for the payload kind + (1 + self.packed_len()) as u32 * params.data_byte() } fn mana_cost(&self, params: crate::types::block::protocol::WorkScoreParameters, reference_mana_cost: u64) -> u64 { diff --git a/sdk/src/types/block/payload/signed_transaction/transaction.rs b/sdk/src/types/block/payload/signed_transaction/transaction.rs index 2a8ab48c08..798a7dc307 100644 --- a/sdk/src/types/block/payload/signed_transaction/transaction.rs +++ b/sdk/src/types/block/payload/signed_transaction/transaction.rs @@ -326,18 +326,10 @@ impl Transaction { impl WorkScore for Transaction { fn work_score(&self, params: WorkScoreParameters) -> u32 { - self.inputs().len() as u32 * params.input() - + self - .context_inputs() - .iter() - .map(|ci| ci.work_score(params)) - .sum::() + self.inputs().work_score(params) + + self.context_inputs().work_score(params) + self.outputs().work_score(params) - + self - .mana_allotments() - .iter() - .map(|ma| ma.work_score(params)) - .sum::() + + self.mana_allotments().work_score(params) } } diff --git a/sdk/src/types/block/protocol/work_score.rs b/sdk/src/types/block/protocol/work_score.rs index 32f6f77b26..cb4f862505 100644 --- a/sdk/src/types/block/protocol/work_score.rs +++ b/sdk/src/types/block/protocol/work_score.rs @@ -15,25 +15,25 @@ use crate::types::block::Error; #[packable(unpack_error = Error)] #[getset(get_copy = "pub")] pub struct WorkScoreParameters { - /// Modifier for network traffic per byte. + /// Accounts for the network traffic per byte. data_byte: u32, - /// Modifier for work done to process a block. + /// Accounts for work done to process a block in the node software. block: u32, - /// Modifier for loading UTXOs and performing mana calculations. + /// Accounts for loading the UTXO from the database and performing the mana balance check. input: u32, - /// Modifier for loading and checking the context input. + /// Accounts for loading and checking the context input. context_input: u32, - /// Modifier for storing UTXOs. + /// Accounts for storing the UTXO in the database. output: u32, - /// Modifier for calculations using native token features. + /// Accounts for native token balance checks which use big integers. native_token: u32, - /// Modifier for storing staking features. + /// Accounts for the cost of updating the staking vector when a staking feature is present. staking: u32, - /// Modifier for storing block issuer features. + /// Accounts for the cost of updating the block issuer keys when a block issuer feature is present. block_issuer: u32, - /// Modifier for accessing the account-based ledger to transform mana to Block Issuance Credits. + /// Accounts for accessing the account based ledger to transform the allotted mana to block issuance credits. allotment: u32, - /// Modifier for the block signature check. + /// Accounts for an Ed25519 signature check. signature_ed25519: u32, } From 52dc638bb0b2d54911e7dc494671f3531598b4b0 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 24 Nov 2023 09:44:39 +0100 Subject: [PATCH 32/42] cleanup --- sdk/src/types/block/output/token_scheme/simple.rs | 7 +++++-- sdk/src/types/block/payload/candidacy_announcement.rs | 4 ++-- sdk/src/types/block/unlock/mod.rs | 6 ------ 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/sdk/src/types/block/output/token_scheme/simple.rs b/sdk/src/types/block/output/token_scheme/simple.rs index f27e33dfce..677b7bd780 100644 --- a/sdk/src/types/block/output/token_scheme/simple.rs +++ b/sdk/src/types/block/output/token_scheme/simple.rs @@ -4,7 +4,10 @@ use packable::Packable; use primitive_types::U256; -use crate::types::block::{protocol::WorkScore, Error}; +use crate::types::block::{ + protocol::{WorkScore, WorkScoreParameters}, + Error, +}; /// #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Packable)] @@ -72,7 +75,7 @@ impl SimpleTokenScheme { // TODO: double check with TIP whetehr this is still correct impl WorkScore for SimpleTokenScheme { - fn work_score(&self, params: crate::types::block::protocol::WorkScoreParameters) -> u32 { + fn work_score(&self, params: WorkScoreParameters) -> u32 { params.native_token() } } diff --git a/sdk/src/types/block/payload/candidacy_announcement.rs b/sdk/src/types/block/payload/candidacy_announcement.rs index 597b6a0356..c5bea62d7e 100644 --- a/sdk/src/types/block/payload/candidacy_announcement.rs +++ b/sdk/src/types/block/payload/candidacy_announcement.rs @@ -3,7 +3,7 @@ use packable::{Packable, PackableExt}; -use crate::types::block::protocol::WorkScore; +use crate::types::block::protocol::{WorkScore, WorkScoreParameters}; /// A payload which is used to indicate candidacy for committee selection for the next epoch. #[derive(Clone, Debug, Eq, PartialEq, Packable)] @@ -16,7 +16,7 @@ impl CandidacyAnnouncementPayload { // # TODO: check with TIP impl WorkScore for CandidacyAnnouncementPayload { - fn work_score(&self, params: crate::types::block::protocol::WorkScoreParameters) -> u32 { + fn work_score(&self, params: WorkScoreParameters) -> u32 { // 1 byte for the payload kind (1 + self.packed_len()) as u32 * params.data_byte() } diff --git a/sdk/src/types/block/unlock/mod.rs b/sdk/src/types/block/unlock/mod.rs index 2c8fddc1cb..8dbbef2cf4 100644 --- a/sdk/src/types/block/unlock/mod.rs +++ b/sdk/src/types/block/unlock/mod.rs @@ -148,12 +148,6 @@ impl Unlocks { } } -impl WorkScore for Unlocks { - fn work_score(&self, params: WorkScoreParameters) -> u32 { - self.iter().map(|unlock| unlock.work_score(params)).sum() - } -} - /// Verifies the consistency of non-multi unlocks. /// Will error on multi unlocks as they can't be nested. fn verify_non_multi_unlock<'a>( From 01906c0dc78ef3335a66a679f156d81547d6112a Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 24 Nov 2023 09:51:44 +0100 Subject: [PATCH 33/42] cleanup 2 --- sdk/src/types/block/output/feature/mod.rs | 6 ------ sdk/src/types/block/output/unlock_condition/mod.rs | 6 ------ 2 files changed, 12 deletions(-) diff --git a/sdk/src/types/block/output/feature/mod.rs b/sdk/src/types/block/output/feature/mod.rs index 0b0c24ebed..bcff97711b 100644 --- a/sdk/src/types/block/output/feature/mod.rs +++ b/sdk/src/types/block/output/feature/mod.rs @@ -277,12 +277,6 @@ impl StorageScore for Features { } } -impl WorkScore for Features { - fn work_score(&self, params: WorkScoreParameters) -> u32 { - self.iter().map(|feature| feature.work_score(params)).sum() - } -} - #[inline] fn verify_unique_sorted(features: &[Feature]) -> Result<(), Error> { if VERIFY && !is_unique_sorted(features.iter().map(Feature::kind)) { diff --git a/sdk/src/types/block/output/unlock_condition/mod.rs b/sdk/src/types/block/output/unlock_condition/mod.rs index dde97b7a0d..b154860ce9 100644 --- a/sdk/src/types/block/output/unlock_condition/mod.rs +++ b/sdk/src/types/block/output/unlock_condition/mod.rs @@ -311,12 +311,6 @@ impl StorageScore for UnlockConditions { } } -impl WorkScore for UnlockConditions { - fn work_score(&self, params: WorkScoreParameters) -> u32 { - self.iter().map(|uc| uc.work_score(params)).sum() - } -} - #[inline] fn verify_unique_sorted(unlock_conditions: &[UnlockCondition]) -> Result<(), Error> { if VERIFY && !is_unique_sorted(unlock_conditions.iter().map(UnlockCondition::kind)) { From 3a303e0cd1529a83e8f47b13a9619ad74ea81c0c Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 24 Nov 2023 09:54:44 +0100 Subject: [PATCH 34/42] forward work score in NativeTokenFeature --- sdk/src/types/block/output/feature/native_token.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/output/feature/native_token.rs b/sdk/src/types/block/output/feature/native_token.rs index 1cf0b766ba..932f536e01 100644 --- a/sdk/src/types/block/output/feature/native_token.rs +++ b/sdk/src/types/block/output/feature/native_token.rs @@ -30,7 +30,7 @@ impl StorageScore for NativeTokenFeature {} impl WorkScore for NativeTokenFeature { fn work_score(&self, params: WorkScoreParameters) -> u32 { - params.native_token() + self.0.work_score(params) } } From 3fa452a2ae6c84a70920808b3e3adb60342f183f Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 24 Nov 2023 09:59:09 +0100 Subject: [PATCH 35/42] cleanup 3 --- sdk/src/types/block/core/validation.rs | 2 +- sdk/src/types/block/output/unlock_condition/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/src/types/block/core/validation.rs b/sdk/src/types/block/core/validation.rs index 137bccf1ec..d96d4c9af1 100644 --- a/sdk/src/types/block/core/validation.rs +++ b/sdk/src/types/block/core/validation.rs @@ -5,7 +5,7 @@ use packable::Packable; use crate::types::block::{ core::{parent::verify_parents_sets, BlockBody, Parents}, - protocol::{ProtocolParameters, ProtocolParametersHash, WorkScore, WorkScoreParameters}, + protocol::{ProtocolParameters, ProtocolParametersHash, WorkScore}, Error, }; diff --git a/sdk/src/types/block/output/unlock_condition/mod.rs b/sdk/src/types/block/output/unlock_condition/mod.rs index b154860ce9..3791fcdf49 100644 --- a/sdk/src/types/block/output/unlock_condition/mod.rs +++ b/sdk/src/types/block/output/unlock_condition/mod.rs @@ -26,7 +26,7 @@ pub use self::{ use crate::types::block::{ address::Address, output::{StorageScore, StorageScoreParameters}, - protocol::{ProtocolParameters, WorkScore, WorkScoreParameters}, + protocol::{ProtocolParameters, WorkScore}, slot::SlotIndex, Error, }; From d002ed18c3457b71f79fb56125e0af9cd06d2b84 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 24 Nov 2023 10:04:04 +0100 Subject: [PATCH 36/42] forward 2 --- sdk/src/types/block/unlock/multi.rs | 13 +++++++++++-- sdk/src/types/block/unlock/signature.rs | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/sdk/src/types/block/unlock/multi.rs b/sdk/src/types/block/unlock/multi.rs index b384afa77a..3109645c4f 100644 --- a/sdk/src/types/block/unlock/multi.rs +++ b/sdk/src/types/block/unlock/multi.rs @@ -6,7 +6,12 @@ use alloc::boxed::Box; use derive_more::Deref; use packable::{prefix::BoxedSlicePrefix, Packable}; -use crate::types::block::{address::WeightedAddressCount, protocol::WorkScore, unlock::Unlock, Error}; +use crate::types::block::{ + address::WeightedAddressCount, + protocol::{WorkScore, WorkScoreParameters}, + unlock::Unlock, + Error, +}; pub(crate) type UnlocksCount = WeightedAddressCount; @@ -38,7 +43,11 @@ impl MultiUnlock { } } -impl WorkScore for MultiUnlock {} +impl WorkScore for MultiUnlock { + fn work_score(&self, params: WorkScoreParameters) -> u32 { + self.0.work_score(params) + } +} fn verify_unlocks(unlocks: &[Unlock]) -> Result<(), Error> { if VERIFY && unlocks.iter().any(Unlock::is_multi) { diff --git a/sdk/src/types/block/unlock/signature.rs b/sdk/src/types/block/unlock/signature.rs index 2df40c4781..bb9687a883 100644 --- a/sdk/src/types/block/unlock/signature.rs +++ b/sdk/src/types/block/unlock/signature.rs @@ -32,7 +32,7 @@ impl SignatureUnlock { impl WorkScore for SignatureUnlock { fn work_score(&self, params: WorkScoreParameters) -> u32 { - params.signature_ed25519() + self.0.work_score(params) } } From f5ee525389b562461741f50ab931c71b31641393 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 24 Nov 2023 10:14:27 +0100 Subject: [PATCH 37/42] let's see if we're faster than thibault --- sdk/src/types/block/payload/candidacy_announcement.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sdk/src/types/block/payload/candidacy_announcement.rs b/sdk/src/types/block/payload/candidacy_announcement.rs index c5bea62d7e..3c349bba04 100644 --- a/sdk/src/types/block/payload/candidacy_announcement.rs +++ b/sdk/src/types/block/payload/candidacy_announcement.rs @@ -20,8 +20,4 @@ impl WorkScore for CandidacyAnnouncementPayload { // 1 byte for the payload kind (1 + self.packed_len()) as u32 * params.data_byte() } - - fn mana_cost(&self, params: crate::types::block::protocol::WorkScoreParameters, reference_mana_cost: u64) -> u64 { - reference_mana_cost * self.work_score(params) as u64 - } } From f19d7dc430391748a1ad7c416a647b6320abf780 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 24 Nov 2023 10:22:44 +0100 Subject: [PATCH 38/42] unnecessary import --- sdk/src/types/block/payload/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index 47b08ff736..1d4f8b2bed 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -8,7 +8,7 @@ pub mod signed_transaction; pub mod tagged_data; use alloc::boxed::Box; -use core::{mem::size_of, ops::Deref}; +use core::ops::Deref; use derive_more::From; use packable::{ From 80d2f383c216e050a721e742859fe6066486f18c Mon Sep 17 00:00:00 2001 From: /alex/ Date: Fri, 24 Nov 2023 10:33:54 +0100 Subject: [PATCH 39/42] underscore Co-authored-by: Thibault Martinez --- sdk/src/types/block/protocol/work_score.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/protocol/work_score.rs b/sdk/src/types/block/protocol/work_score.rs index cb4f862505..2eaee50023 100644 --- a/sdk/src/types/block/protocol/work_score.rs +++ b/sdk/src/types/block/protocol/work_score.rs @@ -57,7 +57,7 @@ impl Default for WorkScoreParameters { /// A trait to facilitate the computation of the work score of a block, which is central to mana cost calculation. pub trait WorkScore { /// Returns its work score. Defaults to 0. - fn work_score(&self, params: WorkScoreParameters) -> u32 { + fn work_score(&self, _params: WorkScoreParameters) -> u32 { 0 } From 787067c5d01c01f48c51c41c7222d8e2260fcbe4 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 24 Nov 2023 13:46:40 +0100 Subject: [PATCH 40/42] final touches --- sdk/src/types/block/payload/mod.rs | 2 +- .../block/payload/signed_transaction/transaction.rs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index 1d4f8b2bed..64c45788d0 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -77,7 +77,7 @@ impl Payload { } } - crate::def_is_as_opt!(Payload: SignedTransaction, TaggedData); + crate::def_is_as_opt!(Payload: TaggedData, SignedTransaction, CandidacyAnnouncement); } impl WorkScore for Payload { diff --git a/sdk/src/types/block/payload/signed_transaction/transaction.rs b/sdk/src/types/block/payload/signed_transaction/transaction.rs index 798a7dc307..c9e6842add 100644 --- a/sdk/src/types/block/payload/signed_transaction/transaction.rs +++ b/sdk/src/types/block/payload/signed_transaction/transaction.rs @@ -261,7 +261,7 @@ impl Transaction { } /// Returns the [`ManaAllotment`]s of a [`Transaction`]. - pub fn mana_allotments(&self) -> &[ManaAllotment] { + pub fn allotments(&self) -> &[ManaAllotment] { &self.allotments } @@ -326,10 +326,10 @@ impl Transaction { impl WorkScore for Transaction { fn work_score(&self, params: WorkScoreParameters) -> u32 { - self.inputs().work_score(params) - + self.context_inputs().work_score(params) + self.context_inputs().work_score(params) + + self.inputs().work_score(params) + + self.allotments().work_score(params) + self.outputs().work_score(params) - + self.mana_allotments().work_score(params) } } @@ -562,7 +562,7 @@ pub(crate) mod dto { creation_slot: value.creation_slot(), context_inputs: value.context_inputs().to_vec(), inputs: value.inputs().to_vec(), - allotments: value.mana_allotments().iter().map(Into::into).collect(), + allotments: value.allotments().iter().map(Into::into).collect(), capabilities: value.capabilities().clone(), payload: match value.payload() { Some(p @ Payload::TaggedData(_)) => Some(p.into()), From ab6501ea004a8db1f39558ae8cdcfa30d09b4952 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Fri, 24 Nov 2023 14:47:27 +0100 Subject: [PATCH 41/42] remove todo --- sdk/src/types/block/output/token_scheme/simple.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/src/types/block/output/token_scheme/simple.rs b/sdk/src/types/block/output/token_scheme/simple.rs index 677b7bd780..328adf80c5 100644 --- a/sdk/src/types/block/output/token_scheme/simple.rs +++ b/sdk/src/types/block/output/token_scheme/simple.rs @@ -73,7 +73,6 @@ impl SimpleTokenScheme { } } -// TODO: double check with TIP whetehr this is still correct impl WorkScore for SimpleTokenScheme { fn work_score(&self, params: WorkScoreParameters) -> u32 { params.native_token() From 9f751e02d721ce021f7da7f627c1d909cd83f4ae Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Mon, 27 Nov 2023 09:24:57 +0100 Subject: [PATCH 42/42] rm mana_cost fn from work score trait --- sdk/src/types/block/payload/mod.rs | 2 +- sdk/src/types/block/protocol/work_score.rs | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/sdk/src/types/block/payload/mod.rs b/sdk/src/types/block/payload/mod.rs index 64c45788d0..f72f633450 100644 --- a/sdk/src/types/block/payload/mod.rs +++ b/sdk/src/types/block/payload/mod.rs @@ -83,8 +83,8 @@ impl Payload { impl WorkScore for Payload { fn work_score(&self, params: WorkScoreParameters) -> u32 { match self { - Self::SignedTransaction(signed_transaction) => signed_transaction.work_score(params), Self::TaggedData(tagged_data) => tagged_data.work_score(params), + Self::SignedTransaction(signed_transaction) => signed_transaction.work_score(params), Self::CandidacyAnnouncement(candidacy_announcement) => candidacy_announcement.work_score(params), } } diff --git a/sdk/src/types/block/protocol/work_score.rs b/sdk/src/types/block/protocol/work_score.rs index 2eaee50023..fc96021a64 100644 --- a/sdk/src/types/block/protocol/work_score.rs +++ b/sdk/src/types/block/protocol/work_score.rs @@ -56,15 +56,9 @@ impl Default for WorkScoreParameters { /// A trait to facilitate the computation of the work score of a block, which is central to mana cost calculation. pub trait WorkScore { - /// Returns its work score. Defaults to 0. fn work_score(&self, _params: WorkScoreParameters) -> u32 { 0 } - - /// Returns the Mana cost given its work score. - fn mana_cost(&self, params: WorkScoreParameters, reference_mana_cost: u64) -> u64 { - reference_mana_cost * self.work_score(params) as u64 - } } impl WorkScore for [T; N] {