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

Code - FIFO #12

Closed
wants to merge 37 commits into from
Closed

Code - FIFO #12

wants to merge 37 commits into from

Conversation

jkciw
Copy link
Contributor

@jkciw jkciw commented Mar 15, 2024

Code to implement coin selection using first in first out (FIFO) algorithm.

src/lib.rs Outdated
) -> Result<SelectionOutput, SelectionError> {
unimplemented!()
/* Using the value of the input as an identifier for the selected inputs, as the index of the vec<outputgroup> can't be used because the vector itself is sorted first. Ideally, txid of the input can serve as an unique identifier */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong. The indices of the Vec has to be the identifier. You can create a Vec<usize, OutGroup> first and then sort that Vec, this will track which OutGroup belongs to which index.
Mulltiple UTXOs can have same OutGroup value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Removed the comment.

src/lib.rs Outdated
@@ -8,7 +8,7 @@ use rand::{seq::SliceRandom, thread_rng};
/// single UTXO, or a group of UTXOs that should be spent together.
/// The library user is responsible for crafting this structure correctly. Incorrect representation of this
/// structure will cause incorrect selection result.
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple UTXOs can have same OutGroup, so deriving Equality doesn't make sense here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. However, I need the PartialEq trait as I use it to compare the sorted and original OutputGroup vectors to extract the indices from the original OutputGroup vector.

Copy link
Collaborator

@delcin-raj delcin-raj Mar 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But that's not semantically right, and your algorithm is running in O(n^2) while it should be optimally run in O(n logn) due to sorting.
You have to collect the elements with their indices using enumeration before you sort then later sort them according to the creation_sequence, so even after sorting each outputgroup will be associated with it's index in the inputs as given by the user.
You can check how I did that in SRD.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. Made relevant changes and pushed a commit

Copy link
Contributor Author

@jkciw jkciw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes:

  • Removed redundant Eq trait derived for OutputGroup
  • Removed comments regarding use of 'value' instead of 'index' to keep track of OutputGroup vector elements.

src/lib.rs Outdated
@@ -8,7 +8,7 @@ use rand::{seq::SliceRandom, thread_rng};
/// single UTXO, or a group of UTXOs that should be spent together.
/// The library user is responsible for crafting this structure correctly. Incorrect representation of this
/// structure will cause incorrect selection result.
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. However, I need the PartialEq trait as I use it to compare the sorted and original OutputGroup vectors to extract the indices from the original OutputGroup vector.

src/lib.rs Outdated
) -> Result<SelectionOutput, SelectionError> {
unimplemented!()
/* Using the value of the input as an identifier for the selected inputs, as the index of the vec<outputgroup> can't be used because the vector itself is sorted first. Ideally, txid of the input can serve as an unique identifier */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Removed the comment.

src/lib.rs Outdated
/// Return NoSolutionFound, if no solution exists.

pub fn select_coin_fifo(
inputs: Vec<OutputGroup>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please merge from main.

src/lib.rs Outdated

for i in sortedinputs.iter() {
for (index, inputs) in sorted_inputs {
estimated_fees = (accumulated_weight as f32 * options.target_feerate).ceil() as u64;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use calculate_fee function here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

src/lib.rs Outdated
}
accumulated_value += inputs.value;
accumulated_weight += inputs.weight;
selected_inputs.push(index);
}
if accumulated_value < options.target_value + estimated_fees + options.min_drain_value {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There could be cases where estimated_fees < min_absolute_fee, refer SRD to fix this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right.

src/lib.rs Outdated
}
accumulated_value += inputs.value;
accumulated_weight += inputs.weight;
selected_inputs.push(index);
}
if accumulated_value < options.target_value + estimated_fees + options.min_drain_value {
Err(SelectionError::NoSolutionFound)
} else {
let mut waste_score: u64 = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't calculate waste manually, use calculate_waste function

src/lib.rs Outdated
}
accumulated_value += inputs.value;
accumulated_weight += inputs.weight;
selected_inputs.push(index);
}
if accumulated_value < options.target_value + estimated_fees + options.min_drain_value {
Err(SelectionError::NoSolutionFound)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InsufficientFunds will be the appropriate error for FIFO, as it tries to include all UTXOs until the desired target is met.
Because if sufficient fund exists fifo will give you a solution. This is not the case of BNB and Knapsack for example..

src/lib.rs Outdated
for (index, inputs) in sorted_inputs {
estimated_fees = calculate_fee(accumulated_weight, options.target_feerate);
if accumulated_value
>= (options.target_value
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 2 * options.target_value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a typo.

src/lib.rs Outdated
>= (options.target_value
+ options.target_value
+ estimated_fees
+ options.min_drain_value)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have to make sure that the accumulated_value has sufficient fee also, estimated_fee.max(options.min_absolute_fee)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right.

Copy link
Collaborator

@delcin-raj delcin-raj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, looks good!

rajarshimaitra and others added 22 commits April 9, 2024 07:56
Merged with main according to updates
* Added FIFO

* Added changes to use value of the input as identifier for FIFO algorithm

* Added changes to use sort_by_key method and check for conditions including feerate and weight calculation

* Removed Partial Imp and added one test case for fifo

* Removed custom implementations of ordering

* Added FIFO

Merged with main according to updates

* Added changes to use sort_by_key method and check for conditions including feerate and weight calculation

* Removed Partial Imp and added one test case for fifo

* Removed custom implementations of ordering

* Performed fmt checks

* Addressed issues raised by clippy and checked fmt
* Single Random Draw rough implementation

* fmt changes

* Tests for SRD

* fmt changes

* Clippy suggestions

* check for not empty

* Spelling corrections and merge from upstream/main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants