Skip to content

Commit

Permalink
Merge branch '2.0' into nodejs-unlocks
Browse files Browse the repository at this point in the history
  • Loading branch information
thibault-martinez authored Nov 16, 2023
2 parents d84639d + 383b8a7 commit 5da1822
Show file tree
Hide file tree
Showing 37 changed files with 488 additions and 994 deletions.
358 changes: 171 additions & 187 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions bindings/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@ iota-crypto = { version = "0.23.0", default-features = false, features = [
"bip44",
] }
log = { version = "0.4.20", default-features = false }
packable = { version = "0.8.3", default-features = false }
packable = { version = "0.9.0", default-features = false }
prefix-hex = { version = "0.7.1", default-features = false }
primitive-types = { version = "0.12.2", default-features = false }
serde = { version = "1.0.188", default-features = false }
serde_json = { version = "1.0.107", default-features = false }
thiserror = { version = "1.0.49", default-features = false }
tokio = { version = "1.33.0", default-features = false }
url = { version = "2.4.1", default-features = false, features = [
"serde",
] }
url = { version = "2.4.1", default-features = false, features = ["serde"] }
zeroize = { version = "1.6.0", default-features = false }

[dev-dependencies]
pretty_assertions = { version = "1.4.0", default-features = false, features = [ "alloc" ] }
pretty_assertions = { version = "1.4.0", default-features = false, features = [
"alloc",
] }

[features]
events = ["iota-sdk/events"]
Expand Down
6 changes: 1 addition & 5 deletions bindings/core/src/method_handler/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM
unlock_conditions,
features,
immutable_features,
client.get_token_supply().await?,
)?);

Response::Output(OutputDto::from(&output))
Expand All @@ -101,7 +100,6 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM
native_tokens,
unlock_conditions,
features,
client.get_token_supply().await?,
)?);

Response::Output(OutputDto::from(&output))
Expand All @@ -127,7 +125,6 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM
unlock_conditions,
features,
immutable_features,
client.get_token_supply().await?,
)?);

Response::Output(OutputDto::from(&output))
Expand All @@ -153,7 +150,6 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM
unlock_conditions,
features,
immutable_features,
client.get_token_supply().await?,
)?);

Response::Output(OutputDto::from(&output))
Expand Down Expand Up @@ -296,7 +292,7 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM
Response::Bech32Address(client.hex_public_key_to_bech32_address(&hex, bech32_hrp).await?)
}
ClientMethod::ComputeMinimumOutputAmount { output } => {
let output = Output::try_from_dto_with_params(output, client.get_token_supply().await?)?;
let output = Output::try_from(output)?;
let storage_score_params = client.get_storage_score_parameters().await?;

Response::OutputAmount(output.minimum_amount(storage_score_params))
Expand Down
4 changes: 2 additions & 2 deletions bindings/core/src/method_handler/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub(crate) fn call_utils_method_internal(method: UtilsMethod) -> Result<Response
output,
storage_score_parameters: storage_params,
} => {
let out = Output::try_from_dto(output)?;
let out = Output::try_from(output)?;
Response::OutputAmount(out.minimum_amount(storage_params))
}
UtilsMethod::VerifyMnemonic { mnemonic } => {
Expand Down Expand Up @@ -105,7 +105,7 @@ pub(crate) fn call_utils_method_internal(method: UtilsMethod) -> Result<Response
UtilsMethod::OutputIdToUtxoInput { output_id } => Response::Input(UtxoInput::from(output_id)),
UtilsMethod::ComputeSlotCommitmentId { slot_commitment } => Response::SlotCommitmentId(slot_commitment.id()),
UtilsMethod::OutputHexBytes { output } => {
let output = Output::try_from_dto(output)?;
let output = Output::try_from(output)?;
Response::HexBytes(prefix_hex::encode(output.pack_to_vec()))
}
};
Expand Down
14 changes: 6 additions & 8 deletions bindings/core/src/method_handler/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ use iota_sdk::{
wallet::{types::TransactionWithMetadataDto, OutputDataDto, PreparedCreateNativeTokenTransactionDto, Wallet},
};

use crate::{method::WalletMethod, response::Response, Result};
use crate::{method::WalletMethod, response::Response};

/// Call a wallet method.
pub(crate) async fn call_wallet_method_internal(wallet: &Wallet, method: WalletMethod) -> Result<Response> {
pub(crate) async fn call_wallet_method_internal(wallet: &Wallet, method: WalletMethod) -> crate::Result<Response> {
let response = match method {
WalletMethod::Accounts => {
let accounts = wallet.accounts().await;
Expand Down Expand Up @@ -297,13 +297,12 @@ pub(crate) async fn call_wallet_method_internal(wallet: &Wallet, method: WalletM
Response::PreparedTransaction(PreparedTransactionDataDto::from(&data))
}
WalletMethod::PrepareTransaction { outputs, options } => {
let token_supply = wallet.client().get_token_supply().await?;
let data = wallet
.prepare_transaction(
outputs
.into_iter()
.map(|o| Ok(Output::try_from_dto_with_params(o, token_supply)?))
.collect::<Result<Vec<Output>>>()?,
.map(Output::try_from)
.collect::<Result<Vec<Output>, _>>()?,
options,
)
.await?;
Expand Down Expand Up @@ -342,13 +341,12 @@ pub(crate) async fn call_wallet_method_internal(wallet: &Wallet, method: WalletM
Response::SentTransaction(TransactionWithMetadataDto::from(&transaction))
}
WalletMethod::SendOutputs { outputs, options } => {
let token_supply = wallet.client().get_token_supply().await?;
let transaction = wallet
.send_outputs(
outputs
.into_iter()
.map(|o| Ok(Output::try_from_dto_with_params(o, token_supply)?))
.collect::<iota_sdk::wallet::Result<Vec<Output>>>()?,
.map(Output::try_from)
.collect::<Result<Vec<Output>, _>>()?,
options,
)
.await?;
Expand Down
2 changes: 1 addition & 1 deletion sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ iota-crypto = { version = "0.23.0", default-features = false, features = [
"secp256k1",
] }
iterator-sorted = { version = "0.1.0", default-features = false }
packable = { version = "0.8.3", default-features = false, features = [
packable = { version = "0.9.0", default-features = false, features = [
"primitive-types",
] }
paste = { version = "1.0.14", default-features = false }
Expand Down
16 changes: 2 additions & 14 deletions sdk/examples/client/output/build_basic_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//! ```
use iota_sdk::{
client::{Client, Result},
client::Result,
types::block::{
address::Address,
output::{
Expand All @@ -30,14 +30,6 @@ async fn main() -> Result<()> {
// This example uses secrets in environment variables for simplicity which should not be done in production.
dotenvy::dotenv().ok();

// Create a node client.
let client = Client::builder()
.with_node(&std::env::var("NODE_URL").unwrap())?
.finish()
.await?;

let token_supply = client.get_token_supply().await?;

let address = std::env::args()
.nth(1)
.unwrap_or("rms1qpllaj0pyveqfkwxmnngz2c488hfdtmfrj3wfkgxtk4gtyrax0jaxzt70zy".to_string());
Expand All @@ -57,11 +49,7 @@ async fn main() -> Result<()> {
// with storage deposit return
basic_output_builder
.clone()
.add_unlock_condition(StorageDepositReturnUnlockCondition::new(
address.clone(),
1_000_000,
token_supply,
)?)
.add_unlock_condition(StorageDepositReturnUnlockCondition::new(address.clone(), 1_000_000))
.finish_output()?,
// with expiration
basic_output_builder
Expand Down
7 changes: 1 addition & 6 deletions sdk/examples/how_tos/outputs/unlock_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ async fn main() -> Result<()> {
// Create a client instance.
let client = Client::builder().with_node(&node_url)?.finish().await?;

let token_supply = client.get_token_supply().await?;
let storage_score_params = client.get_storage_score_parameters().await?;

let address = Address::try_from_bech32("rms1qpllaj0pyveqfkwxmnngz2c488hfdtmfrj3wfkgxtk4gtyrax0jaxzt70zy")?;
Expand All @@ -51,11 +50,7 @@ async fn main() -> Result<()> {
// with storage deposit return unlock condition
basic_output_builder
.clone()
.add_unlock_condition(StorageDepositReturnUnlockCondition::new(
address.clone(),
1000000,
token_supply,
)?)
.add_unlock_condition(StorageDepositReturnUnlockCondition::new(address.clone(), 1000000))
.finish_output()?,
// with timeout unlock condition
basic_output_builder
Expand Down
18 changes: 8 additions & 10 deletions sdk/src/client/api/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,13 @@ impl TryFromDto for PreparedTransactionData {
inputs_data: dto
.inputs_data
.into_iter()
.map(|i| InputSigningData::try_from_dto_with_params(i, &params))
.map(|i| InputSigningData::try_from(i))
.collect::<crate::client::Result<Vec<InputSigningData>>>()
.map_err(|_| Error::InvalidField("input_data"))?,
remainder: match dto.remainder {
Some(remainder) => Some(
RemainderData::try_from_dto_with_params(remainder, &params)
.map_err(|_| Error::InvalidField("remainder"))?,
),
Some(remainder) => {
Some(RemainderData::try_from(remainder).map_err(|_| Error::InvalidField("remainder"))?)
}
None => None,
},
})
Expand Down Expand Up @@ -121,7 +120,7 @@ impl TryFromDto for SignedTransactionData {
inputs_data: dto
.inputs_data
.into_iter()
.map(|i| InputSigningData::try_from_dto_with_params(i, &params))
.map(|i| InputSigningData::try_from(i))
.collect::<crate::client::Result<Vec<InputSigningData>>>()
.map_err(|_| Error::InvalidField("inputs_data"))?,
})
Expand Down Expand Up @@ -151,13 +150,12 @@ pub struct RemainderDataDto {
pub address: Address,
}

impl TryFromDto for RemainderData {
type Dto = RemainderDataDto;
impl TryFrom<RemainderDataDto> for RemainderData {
type Error = Error;

fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result<Self, Self::Error> {
fn try_from(dto: RemainderDataDto) -> Result<Self, Self::Error> {
Ok(Self {
output: Output::try_from_dto_with_params_inner(dto.output, params)?,
output: Output::try_from(dto.output)?,
chain: dto.chain,
address: dto.address,
})
Expand Down
7 changes: 3 additions & 4 deletions sdk/src/client/node_api/core/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,9 @@ impl ClientInner {
pub async fn get_output(&self, output_id: &OutputId) -> Result<Output> {
let path = &format!("api/core/v3/outputs/{output_id}");

let output = self.get_request::<OutputDto>(path, None, false, true).await?;
let token_supply = self.get_token_supply().await?;

Ok(Output::try_from_dto_with_params(output, token_supply)?)
Ok(Output::try_from(
self.get_request::<OutputDto>(path, None, false, true).await?,
)?)
}

/// Finds an output by its ID and returns it as raw bytes.
Expand Down
12 changes: 4 additions & 8 deletions sdk/src/client/secret/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ use crypto::keys::bip44::Bip44;
use serde::{Deserialize, Serialize};

use crate::{
types::{
block::output::{dto::OutputDto, Output, OutputId, OutputMetadata},
TryFromDto, ValidationParams,
},
types::block::output::{dto::OutputDto, Output, OutputId, OutputMetadata},
utils::serde::bip44::option_bip44,
};

Expand Down Expand Up @@ -167,13 +164,12 @@ pub struct InputSigningDataDto {
pub chain: Option<Bip44>,
}

impl TryFromDto for InputSigningData {
type Dto = InputSigningDataDto;
impl TryFrom<InputSigningDataDto> for InputSigningData {
type Error = crate::client::Error;

fn try_from_dto_with_params_inner(dto: Self::Dto, params: ValidationParams<'_>) -> Result<Self, Self::Error> {
fn try_from(dto: InputSigningDataDto) -> Result<Self, Self::Error> {
Ok(Self {
output: Output::try_from_dto_with_params_inner(dto.output, params)?,
output: Output::try_from(dto.output)?,
output_metadata: dto.output_metadata,
chain: dto.chain,
})
Expand Down
66 changes: 15 additions & 51 deletions sdk/src/types/block/address/multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,7 @@ use core::{fmt, ops::RangeInclusive};

use derive_more::{AsRef, Deref, Display, From};
use iterator_sorted::is_unique_sorted;
use packable::{
bounded::BoundedU8,
error::{UnpackError, UnpackErrorExt},
packer::Packer,
prefix::BoxedSlicePrefix,
unpacker::Unpacker,
Packable,
};
use packable::{bounded::BoundedU8, prefix::BoxedSlicePrefix, Packable};

use crate::types::block::{address::Address, output::StorageScore, Error};

Expand Down Expand Up @@ -77,12 +70,17 @@ fn verify_weight<const VERIFY: bool>(weight: &u8, _visitor: &()) -> Result<(), E
/// 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.
#[derive(Clone, Debug, Deref, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[derive(Clone, Debug, Deref, Eq, PartialEq, Ord, PartialOrd, Hash, Packable)]
#[packable(unpack_error = Error)]
#[packable(verify_with = verify_multi_address)]
pub struct MultiAddress {
/// The weighted unlocked addresses.
#[deref]
#[packable(verify_with = verify_addresses)]
#[packable(unpack_error_with = |e| e.unwrap_item_err_or_else(|p| Error::InvalidWeightedAddressCount(p.into())))]
addresses: BoxedSlicePrefix<WeightedAddress, WeightedAddressCount>,
/// The threshold that needs to be reached by the unlocked addresses in order to unlock the multi address.
#[packable(verify_with = verify_threshold)]
threshold: u16,
}

Expand All @@ -103,9 +101,11 @@ impl MultiAddress {
let addresses = BoxedSlicePrefix::<WeightedAddress, WeightedAddressCount>::try_from(addresses)
.map_err(Error::InvalidWeightedAddressCount)?;

verify_cumulative_weight::<true>(&addresses, &threshold, &())?;
let multi_address = Self { addresses, threshold };

Ok(Self { addresses, threshold })
verify_multi_address::<true>(&multi_address, &())?;

Ok(multi_address)
}

/// Returns the addresses of a [`MultiAddress`].
Expand All @@ -121,38 +121,6 @@ impl MultiAddress {
}
}

impl Packable for MultiAddress {
type UnpackError = Error;
type UnpackVisitor = ();

#[inline]
fn pack<P: Packer>(&self, packer: &mut P) -> Result<(), P::Error> {
self.addresses.pack(packer)?;
self.threshold.pack(packer)?;

Ok(())
}

#[inline]
fn unpack<U: Unpacker, const VERIFY: bool>(
unpacker: &mut U,
visitor: &Self::UnpackVisitor,
) -> Result<Self, UnpackError<Self::UnpackError, U::Error>> {
let addresses =
BoxedSlicePrefix::<WeightedAddress, WeightedAddressCount>::unpack::<_, VERIFY>(unpacker, visitor)
.map_packable_err(|e| e.unwrap_item_err_or_else(|e| Error::InvalidWeightedAddressCount(e.into())))?;

verify_addresses::<VERIFY>(&addresses, &()).map_err(UnpackError::Packable)?;

let threshold = u16::unpack::<_, VERIFY>(unpacker, visitor).coerce()?;

verify_threshold::<VERIFY>(&threshold, &()).map_err(UnpackError::Packable)?;
verify_cumulative_weight::<VERIFY>(&addresses, &threshold, &()).map_err(UnpackError::Packable)?;

Ok(Self { addresses, threshold })
}
}

fn verify_addresses<const VERIFY: bool>(addresses: &[WeightedAddress], _visitor: &()) -> Result<(), Error> {
if VERIFY && !is_unique_sorted(addresses.iter().map(WeightedAddress::address)) {
return Err(Error::WeightedAddressesNotUniqueSorted);
Expand All @@ -169,18 +137,14 @@ fn verify_threshold<const VERIFY: bool>(threshold: &u16, _visitor: &()) -> Resul
}
}

fn verify_cumulative_weight<const VERIFY: bool>(
addresses: &[WeightedAddress],
threshold: &u16,
_visitor: &(),
) -> Result<(), Error> {
fn verify_multi_address<const VERIFY: bool>(address: &MultiAddress, _visitor: &()) -> Result<(), Error> {
if VERIFY {
let cumulative_weight = addresses.iter().map(|address| address.weight as u16).sum::<u16>();
let cumulative_weight = address.iter().map(|address| address.weight as u16).sum::<u16>();

if cumulative_weight < *threshold {
if cumulative_weight < address.threshold {
return Err(Error::InvalidMultiAddressCumulativeWeight {
cumulative_weight,
threshold: *threshold,
threshold: address.threshold,
});
}
}
Expand Down
Loading

0 comments on commit 5da1822

Please sign in to comment.