Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 10 commits into from
Feb 26, 2024
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 {
thibault-martinez marked this conversation as resolved.
Show resolved Hide resolved
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
Loading