Skip to content

Commit

Permalink
Increase auto transitioned outputs amount to the minimum if it is low…
Browse files Browse the repository at this point in the history
…er (#2060)

* Increase auto transitioned outputs amount to the minimum if it is lower

* rename tests

* better tests

* Update sdk/src/types/block/output/basic.rs

* Update sdk/src/types/block/output/foundry.rs

* nits

* Add a TODO

---------

Co-authored-by: Thibault Martinez <[email protected]>
  • Loading branch information
DaughterOfMars and thibault-martinez authored Feb 26, 2024
1 parent 56b19d4 commit 0eb252e
Show file tree
Hide file tree
Showing 11 changed files with 506 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ impl InputSelection {
let features = input.features().iter().filter(|feature| !feature.is_sender()).cloned();

let mut builder = AccountOutputBuilder::from(input)
.with_amount_or_minimum(input.amount(), self.protocol_parameters.storage_score_parameters())
.with_account_id(account_id)
.with_foundry_counter(u32::max(highest_foundry_serial_number, input.foundry_counter()))
.with_features(features);
Expand Down Expand Up @@ -102,6 +103,7 @@ impl InputSelection {
let features = input.features().iter().filter(|feature| !feature.is_sender()).cloned();

let output = NftOutputBuilder::from(input)
.with_amount_or_minimum(input.amount(), self.protocol_parameters.storage_score_parameters())
.with_nft_id(nft_id)
.with_features(features)
.finish_output()?;
Expand Down Expand Up @@ -139,7 +141,9 @@ impl InputSelection {
return Ok(None);
}

let output = FoundryOutputBuilder::from(input).finish_output()?;
let output = FoundryOutputBuilder::from(input)
.with_amount_or_minimum(input.amount(), self.protocol_parameters.storage_score_parameters())
.finish_output()?;

log::debug!("Automatic transition of {output_id:?}/{foundry_id:?}");

Expand Down
13 changes: 13 additions & 0 deletions sdk/src/types/block/output/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ impl AccountOutputBuilder {
Self::new(OutputBuilderAmount::Amount(amount), account_id)
}

/// Creates an [`AccountOutputBuilder`] with a provided amount, unless it is below the minimum.
pub fn new_with_amount_or_minimum(amount: u64, account_id: AccountId, params: StorageScoreParameters) -> Self {
Self::new(OutputBuilderAmount::AmountOrMinimum(amount, params), account_id)
}

/// Creates an [`AccountOutputBuilder`] with provided storage score parameters.
/// The amount will be set to the minimum required amount of the resulting output.
pub fn new_with_minimum_amount(params: StorageScoreParameters, account_id: AccountId) -> Self {
Expand All @@ -98,6 +103,13 @@ impl AccountOutputBuilder {
self
}

/// Sets the amount to the provided value, unless it is below the minimum.
#[inline(always)]
pub fn with_amount_or_minimum(mut self, amount: u64, params: StorageScoreParameters) -> Self {
self.amount = OutputBuilderAmount::AmountOrMinimum(amount, params);
self
}

/// Sets the amount to the minimum required amount.
#[inline(always)]
pub fn with_minimum_amount(mut self, params: StorageScoreParameters) -> Self {
Expand Down Expand Up @@ -246,6 +258,7 @@ impl AccountOutputBuilder {

output.amount = match self.amount {
OutputBuilderAmount::Amount(amount) => amount,
OutputBuilderAmount::AmountOrMinimum(amount, params) => output.minimum_amount(params).max(amount),
OutputBuilderAmount::MinimumAmount(params) => output.minimum_amount(params),
};

Expand Down
13 changes: 13 additions & 0 deletions sdk/src/types/block/output/anchor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ impl AnchorOutputBuilder {
Self::new(OutputBuilderAmount::Amount(amount), anchor_id)
}

/// Creates an [`AnchorOutputBuilder`] with a provided amount, unless it is below the minimum.
pub fn new_with_amount_or_minimum(amount: u64, anchor_id: AnchorId, params: StorageScoreParameters) -> Self {
Self::new(OutputBuilderAmount::AmountOrMinimum(amount, params), anchor_id)
}

/// Creates an [`AnchorOutputBuilder`] with provided storage score parameters.
/// The amount will be set to the minimum required amount of the resulting output.
#[inline(always)]
Expand All @@ -131,6 +136,13 @@ impl AnchorOutputBuilder {
self
}

/// Sets the amount to the provided value, unless it is below the minimum.
#[inline(always)]
pub fn with_amount_or_minimum(mut self, amount: u64, params: StorageScoreParameters) -> Self {
self.amount = OutputBuilderAmount::AmountOrMinimum(amount, params);
self
}

/// Sets the amount to the minimum required amount.
#[inline(always)]
pub fn with_minimum_amount(mut self, params: StorageScoreParameters) -> Self {
Expand Down Expand Up @@ -277,6 +289,7 @@ impl AnchorOutputBuilder {

output.amount = match self.amount {
OutputBuilderAmount::Amount(amount) => amount,
OutputBuilderAmount::AmountOrMinimum(amount, params) => output.minimum_amount(params).max(amount),
OutputBuilderAmount::MinimumAmount(params) => output.minimum_amount(params),
};

Expand Down
14 changes: 14 additions & 0 deletions sdk/src/types/block/output/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ impl BasicOutputBuilder {
Self::new(OutputBuilderAmount::Amount(amount))
}

/// Creates a [`BasicOutputBuilder`] with a provided amount, unless it is below the minimum.
pub fn new_with_amount_or_minimum(amount: u64, params: StorageScoreParameters) -> Self {
Self::new(OutputBuilderAmount::AmountOrMinimum(amount, params))
}

/// Creates an [`BasicOutputBuilder`] with provided storage score parameters.
/// The amount will be set to the minimum required amount of the resulting output.
#[inline(always)]
Expand All @@ -61,6 +66,13 @@ impl BasicOutputBuilder {
self
}

/// Sets the amount to the provided value, unless it is below the minimum.
#[inline(always)]
pub fn with_amount_or_minimum(mut self, amount: u64, params: StorageScoreParameters) -> Self {
self.amount = OutputBuilderAmount::AmountOrMinimum(amount, params);
self
}

/// Sets the amount to the minimum required amount.
#[inline(always)]
pub fn with_minimum_amount(mut self, params: StorageScoreParameters) -> Self {
Expand Down Expand Up @@ -182,6 +194,7 @@ impl BasicOutputBuilder {
self
}
}
OutputBuilderAmount::AmountOrMinimum(_, _) => self,
OutputBuilderAmount::MinimumAmount(_) => self,
})
}
Expand Down Expand Up @@ -211,6 +224,7 @@ impl BasicOutputBuilder {

output.amount = match self.amount {
OutputBuilderAmount::Amount(amount) => amount,
OutputBuilderAmount::AmountOrMinimum(amount, params) => output.minimum_amount(params).max(amount),
OutputBuilderAmount::MinimumAmount(params) => output.minimum_amount(params),
};

Expand Down
61 changes: 40 additions & 21 deletions sdk/src/types/block/output/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,20 @@ impl DelegationId {
}
}

// TODO maybe can be removed as part of https://github.com/iotaledger/iota-sdk/issues/1938
#[derive(Copy, Clone)]
pub enum DelegatedAmount {
Amount(u64),
MinimumAmount(StorageScoreParameters),
}

/// Builder for a [`DelegationOutput`].
#[derive(Clone)]
#[must_use]
pub struct DelegationOutputBuilder {
// TODO https://github.com/iotaledger/iota-sdk/issues/1938
amount: Option<OutputBuilderAmount>,
delegated_amount: OutputBuilderAmount,
delegated_amount: DelegatedAmount,
delegation_id: DelegationId,
validator_address: AccountAddress,
start_epoch: EpochIndex,
Expand All @@ -59,7 +66,19 @@ impl DelegationOutputBuilder {
/// Creates a [`DelegationOutputBuilder`] with a provided amount.
/// Will set the delegated amount field to match.
pub fn new_with_amount(amount: u64, delegation_id: DelegationId, validator_address: AccountAddress) -> Self {
Self::new(OutputBuilderAmount::Amount(amount), delegation_id, validator_address)
Self::new(DelegatedAmount::Amount(amount), delegation_id, validator_address)
}

/// Creates a [`DelegationOutputBuilder`] with a provided amount, unless it is below the minimum.
/// Will set the delegated amount field to match.
pub fn new_with_amount_or_minimum(
amount: u64,
delegation_id: DelegationId,
validator_address: AccountAddress,
params: StorageScoreParameters,
) -> Self {
Self::new(DelegatedAmount::Amount(amount), delegation_id, validator_address)
.with_amount_or_minimum(amount, params)
}

/// Creates a [`DelegationOutputBuilder`] with provided storage score parameters.
Expand All @@ -69,18 +88,10 @@ impl DelegationOutputBuilder {
delegation_id: DelegationId,
validator_address: AccountAddress,
) -> Self {
Self::new(
OutputBuilderAmount::MinimumAmount(params),
delegation_id,
validator_address,
)
Self::new(DelegatedAmount::MinimumAmount(params), delegation_id, validator_address)
}

fn new(
delegated_amount: OutputBuilderAmount,
delegation_id: DelegationId,
validator_address: AccountAddress,
) -> Self {
fn new(delegated_amount: DelegatedAmount, delegation_id: DelegationId, validator_address: AccountAddress) -> Self {
Self {
amount: None,
delegated_amount,
Expand All @@ -98,9 +109,16 @@ impl DelegationOutputBuilder {
self
}

/// Sets the amount to the provided value, unless it is below the minimum.
#[inline(always)]
pub fn with_amount_or_minimum(mut self, amount: u64, params: StorageScoreParameters) -> Self {
self.amount = Some(OutputBuilderAmount::AmountOrMinimum(amount, params));
self
}

/// Sets the amount to the minimum required amount.
pub fn with_minimum_amount(mut self, params: StorageScoreParameters) -> Self {
if matches!(self.delegated_amount, OutputBuilderAmount::MinimumAmount(_)) {
if matches!(self.delegated_amount, DelegatedAmount::MinimumAmount(_)) {
self.amount = None;
} else {
self.amount = Some(OutputBuilderAmount::MinimumAmount(params));
Expand Down Expand Up @@ -181,21 +199,22 @@ impl DelegationOutputBuilder {
};

match self.delegated_amount {
OutputBuilderAmount::Amount(amount) => {
DelegatedAmount::Amount(amount) => {
output.delegated_amount = amount;
output.amount = self.amount.map_or(amount, |builder_amount| match builder_amount {
OutputBuilderAmount::Amount(amount) => amount,
OutputBuilderAmount::AmountOrMinimum(amount, params) => output.minimum_amount(params).max(amount),
OutputBuilderAmount::MinimumAmount(params) => output.minimum_amount(params),
});
}
OutputBuilderAmount::MinimumAmount(params) => {
DelegatedAmount::MinimumAmount(params) => {
let min = output.minimum_amount(params);
output.delegated_amount = min;
output.amount = if let Some(OutputBuilderAmount::Amount(amount)) = self.amount {
amount
} else {
min
};
output.amount = self.amount.map_or(min, |builder_amount| match builder_amount {
OutputBuilderAmount::Amount(amount) => amount,
OutputBuilderAmount::AmountOrMinimum(amount, params) => output.minimum_amount(params).max(amount),
OutputBuilderAmount::MinimumAmount(params) => output.minimum_amount(params),
});
}
}

Expand All @@ -212,7 +231,7 @@ impl From<&DelegationOutput> for DelegationOutputBuilder {
fn from(output: &DelegationOutput) -> Self {
Self {
amount: Some(OutputBuilderAmount::Amount(output.amount)),
delegated_amount: OutputBuilderAmount::Amount(output.delegated_amount),
delegated_amount: DelegatedAmount::Amount(output.delegated_amount),
delegation_id: output.delegation_id,
validator_address: *output.validator_address.as_account(),
start_epoch: output.start_epoch,
Expand Down
22 changes: 22 additions & 0 deletions sdk/src/types/block/output/foundry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,20 @@ impl FoundryOutputBuilder {
Self::new(OutputBuilderAmount::Amount(amount), serial_number, token_scheme)
}

/// Creates a [`FoundryOutputBuilder`] with a provided amount, unless it is below the minimum.
pub fn new_with_amount_or_minimum(
amount: u64,
serial_number: u32,
token_scheme: TokenScheme,
params: StorageScoreParameters,
) -> Self {
Self::new(
OutputBuilderAmount::AmountOrMinimum(amount, params),
serial_number,
token_scheme,
)
}

/// Creates a [`FoundryOutputBuilder`] with provided storage score parameters.
/// The amount will be set to the minimum required amount of the resulting output.
pub fn new_with_minimum_amount(
Expand Down Expand Up @@ -125,6 +139,13 @@ impl FoundryOutputBuilder {
self
}

/// Sets the amount to the provided value, unless it is below the minimum.
#[inline(always)]
pub fn with_amount_or_minimum(mut self, amount: u64, params: StorageScoreParameters) -> Self {
self.amount = OutputBuilderAmount::AmountOrMinimum(amount, params);
self
}

/// Sets the amount to the minimum required amount.
#[inline(always)]
pub fn with_minimum_amount(mut self, params: StorageScoreParameters) -> Self {
Expand Down Expand Up @@ -265,6 +286,7 @@ impl FoundryOutputBuilder {

output.amount = match self.amount {
OutputBuilderAmount::Amount(amount) => amount,
OutputBuilderAmount::AmountOrMinimum(amount, params) => output.minimum_amount(params).max(amount),
OutputBuilderAmount::MinimumAmount(params) => output.minimum_amount(params),
};

Expand Down
1 change: 1 addition & 0 deletions sdk/src/types/block/output/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ pub const OUTPUT_INDEX_RANGE: RangeInclusive<u16> = 0..=OUTPUT_INDEX_MAX; // [0.
#[derive(Copy, Clone)]
pub enum OutputBuilderAmount {
Amount(u64),
AmountOrMinimum(u64, StorageScoreParameters),
MinimumAmount(StorageScoreParameters),
}

Expand Down
14 changes: 14 additions & 0 deletions sdk/src/types/block/output/nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ impl NftOutputBuilder {
Self::new(OutputBuilderAmount::Amount(amount), nft_id)
}

/// Creates an [`NftOutputBuilder`] with a provided amount, unless it is below the minimum.
pub fn new_with_amount_or_minimum(amount: u64, nft_id: NftId, params: StorageScoreParameters) -> Self {
Self::new(OutputBuilderAmount::AmountOrMinimum(amount, params), nft_id)
}

/// Creates an [`NftOutputBuilder`] with provided storage score parameters.
/// The amount will be set to the minimum required amount of the resulting output.
pub fn new_with_minimum_amount(params: StorageScoreParameters, nft_id: NftId) -> Self {
Expand All @@ -96,6 +101,13 @@ impl NftOutputBuilder {
self
}

/// Sets the amount to the provided value, unless it is below the minimum.
#[inline(always)]
pub fn with_amount_or_minimum(mut self, amount: u64, params: StorageScoreParameters) -> Self {
self.amount = OutputBuilderAmount::AmountOrMinimum(amount, params);
self
}

/// Sets the amount to the minimum required amount.
#[inline(always)]
pub fn with_minimum_amount(mut self, params: StorageScoreParameters) -> Self {
Expand Down Expand Up @@ -245,6 +257,7 @@ impl NftOutputBuilder {
self
}
}
OutputBuilderAmount::AmountOrMinimum(_, _) => self,
OutputBuilderAmount::MinimumAmount(_) => self,
})
}
Expand Down Expand Up @@ -275,6 +288,7 @@ impl NftOutputBuilder {

output.amount = match self.amount {
OutputBuilderAmount::Amount(amount) => amount,
OutputBuilderAmount::AmountOrMinimum(amount, params) => output.minimum_amount(params).max(amount),
OutputBuilderAmount::MinimumAmount(params) => output.minimum_amount(params),
};

Expand Down
Loading

0 comments on commit 0eb252e

Please sign in to comment.