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

defer selection improvement in coin selection #493

Merged
merged 5 commits into from
Jul 1, 2019

Conversation

paweljakubas
Copy link
Contributor

Issue Number

#461

Overview

  • I have implemented random algo with input selection for each output and then improvement
  • I have extended coin selection errors by adding ErrInputsDepleted

Comments

@paweljakubas paweljakubas requested a review from KtorZ July 1, 2019 10:20
@paweljakubas paweljakubas force-pushed the paweljakubas/461/defer-selection-improvement branch from cda4ea8 to be5e08a Compare July 1, 2019 10:25
, txOutputs = 40 :| [1]
}

coinSelectionUnitTest
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is one of very interesting cases. Occassionally, random is better than this if for 41 it chooses [20,20,5] and for 6 output 10. largestFirst gives ErrInputsDepleted here deterministically. random can give non-error. If the dices are against us here in case of random we have fallback to largestFirst. Saying that, at this moment, I see only one additional property - there are cases when largestFirst give deterministically error, but in such cases, random can in non-deterministic way choose valid inputs. The question for me is if we want to add such a property

Copy link
Member

Choose a reason for hiding this comment

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

It'd be hard to express such property actually 🤔 ... Have you "rough" idea in mind already of what this could look like ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

agree here. it is very specific case, but I believe it is going to pop up someday. We need additional coin to select to cover one output, and there are two coins left, both can cover the output. But we have also last output to cover, and here only larger one coin can cover it. in largestFirst we are doing always this bad choice ending up in error. In case of random we have 50% chance to do it right (if we are already facing this last random pick). And here random shows its precedence. So in order to provide property like this we need to prepare very specific Coin Selection generator emulating such last choice....

Copy link
Member

@KtorZ KtorZ left a comment

Choose a reason for hiding this comment

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

Looks good overall, some remarks about readability of type signatures mainly ?

(improveTxOut opt)
(utxo1, mempty)
(reverse res)
return (selection, utxo2)
Copy link
Member

Choose a reason for hiding this comment

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

If we swap the arguments of improveTxOut, we can simplify this expression a bit and avoid the naming 0, 1, and 2:

Just (utxo', res) -> 
    lift $ foldM 
        (improveTxOut opt)
        (mempty, utxo')
        (reverse res)

processTxOut (CoinSelectionOptions maxNumInputs) (utxo0, selection) txout = do
attempt <- coverRandomly ([], utxo0)
(inps, utxo') <- lift (improve attempt)
-> MaybeT m (UTxO, [([(TxIn, TxOut)], TxOut)])
Copy link
Member

Choose a reason for hiding this comment

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

Why did we get rid of the CoinSelection type here? Because we do this in two steps, the type shouldn't be much different since the second step is somewhat similar to (UTxO, CoinSelection) -> (UTxO, CoinSelection).

It becomes very noisy quickly with all the TxIn and TxOut sums and products. So if nothing justifies it strongly, I'd rather stay with a simpler type-signature 👍

Copy link
Contributor Author

@paweljakubas paweljakubas Jul 1, 2019

Choose a reason for hiding this comment

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

in the first phase, we are constructing selections for all outputs, also draggng along utxo that is diminished by doing so. basically, in the phase two we start for each output with the selected inputs and try to improve with the current utxo. only then we construct coin selection (in which also change is computed). So, for me, it was easier to operate in phase one and as an input to phase two with type having just already selected inputs for each output plus current UTxO. Probably we can use CoinSelection here - I need a while to think about it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see one obstacle to use CoinSelection at phase 1. If I use <> when processing outputs, I will coalesce all inputs from different outputs. We have :

72 data CoinSelection = CoinSelection                                                                                                                                                         
73     { inputs  :: [(TxIn, TxOut)]                                                                                                                                                           
74       -- ^ Picked inputs                                                                                                                                                                   
75     , outputs :: [TxOut]                                                                                                                                                                   
76       -- ^ Picked outputs                                                                                                                                                                  
77     , change  :: [Coin]                                                                                                                                                                    
78       -- ^ Resulting changes                                                                                                                                                               
79     } deriving (Generic, Show, Eq) 

And then I will not have this knowledge at stage 2 (when doing improvement). And here I need exact inputs per output. So using coin selection at phase 1 somewhat blur boundaries upon <> Maybe I am missing something...

Copy link
Contributor Author

@paweljakubas paweljakubas Jul 1, 2019

Choose a reason for hiding this comment

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

Nevertheless, [([(TxIn, TxOut)], TxOut)] may look cryptic, although this represents the list of (inps, txout) ie., list of all inps selected for a given txout. For me very natural, and very closely reflecting the nature of the algorithm we used

Copy link
Member

Choose a reason for hiding this comment

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

🤔 ... hmmm. Since we treat each output independently, would it make sense to actually consider [CoinSelection] at this stage, with "singleton" selections? This way, we preserve the relationship between inputs/outputs and we still get a rather readable type ?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah. I am just grooming hoping to find something slightly better, but it's not like it's totally cryptic. In the end, as you said, it's quite natural and understandable from the context.

}
)
where
theTarget = mkTargetRange txout
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
theTarget = mkTargetRange txout
target = mkTargetRange txout

, txOutputs = 40 :| [1]
}

coinSelectionUnitTest
Copy link
Member

Choose a reason for hiding this comment

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

It'd be hard to express such property actually 🤔 ... Have you "rough" idea in mind already of what this could look like ?

@paweljakubas paweljakubas force-pushed the paweljakubas/461/defer-selection-improvement branch from dfd5e1e to 40a4280 Compare July 1, 2019 12:56
@KtorZ KtorZ merged commit 0129cb2 into master Jul 1, 2019
@KtorZ KtorZ deleted the paweljakubas/461/defer-selection-improvement branch July 1, 2019 13:58
@KtorZ KtorZ added this to the Review Coin Selection milestone Jul 2, 2019
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.

2 participants