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

Don't create change when it isn't necessary. #898

Closed
wants to merge 2 commits into from

Conversation

dooglus
Copy link
Contributor

@dooglus dooglus commented Feb 25, 2012

If we have three 50BTC outputs and try to spend 100BTC, we should use only two of the outputs. Previously we were using all three. Similarly if we have outputs of 50, 50, and 0.01 and want to spend 100BTC, we shouldn't include the 0.01 in the transaction.

http://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf shows a transaction where MtGox (edit, Feb 2014: I've no idea what caused me to think this was MtGox) was trying to consolidate ten 50k outputs into a single 500k output. The wallet had at least 11 50k outputs in it. Because of this code in wallet.cpp:
if (nTotalLower >= nTargetValue + CENT)
nTargetValue += CENT;
the target value was increased from 500k to 500k plus a cent, which couldn't be found using just ten 50k outputs, and so an eleventh 50k output became involved, to avoid sub-cent change. There was no need for any change at all. (I notice the 50k change hasn't yet been redeemed. I hope it isn't lost!)

These transactions show other common cases where extra 0.01 coins are tacked on to both sides of transactions for no good reason:

http://blockexplorer.com/tx/a9d50d41be42beb278f5830d75aee06216b0a9c93d5eb5a62b6d30bec8c272f3
http://blockexplorer.com/tx/a2f748139f90b5063aace9ab18cb0ceb011a440a5a51888e0ec6c7b71a12aed6

(Sorry for the repeat pull request. I still don't know how to work github properly...)

@gavinandresen
Copy link
Contributor

Too big/dangerous a change for 0.6, I think.

It'd be really spiffy if there were unit tests for the SelectCoins code to test all the edge cases (I know they're not trivial to write, but maybe a little refactoring of SelectCoins would help).

@dooglus
Copy link
Contributor Author

dooglus commented Feb 26, 2012

@gavinandresen I'd be happy to write some unit tests for SelectCoins but it seems to depend on the whole blockchain which isn't available to the unit tests. Is that what you are referring to with the refactoring of SelectCoins? I'm sure with a little help I could get this done.

@gavinandresen
Copy link
Contributor

@dooglus : yes, off the top of my head something like splitting it into two methods, the first of which creates an array of pointers to available outputs (or maybe tuples of (output, nConfirmations, size) or something) and the second of which runs the actual "figure out which outputs to use" algorithm. Making SelectCoins strictly a function that chooses a subset of items passed in should make it much easier to both test and modify in the future.

@dooglus
Copy link
Contributor Author

dooglus commented Feb 27, 2012

@gavinandresen Is it acceptable to use a vector of pair<nConfirmations,pair<nSize,pair<tx,output_number> > > or is that too ugly?

@sipa
Copy link
Member

sipa commented Feb 27, 2012

Tip: use COutPoint instead of pair(tx,output_number). But as soon as there is more than one argument you want to tie to it, I'd add a smallish class.

@dooglus
Copy link
Contributor Author

dooglus commented Feb 27, 2012

@sipa COutPoint has a hash, rather than a transaction, whereas I already have the transactions.

I used a new smallish class anyway because it makes things tidier.

AvailableCoins() makes a vector of available outputs which is then passed to SelectCoinsMinConf().  This allows unit tests to test the coin selection algorithm without having the whole blockchain available.
@luke-jr
Copy link
Member

luke-jr commented Feb 27, 2012

I didn't see the test for this case:

  • Available outputs: 0.0005, 0.01, 1
  • Desired amount: 1.0001
  • Correct solution: 0.01, 1

In this case, the 0.0005 coin should never be chosen, because that would have 0.0004 BTC left over incurring a fee.

@dooglus
Copy link
Contributor Author

dooglus commented Feb 27, 2012

@luke-jr Your "correct solution" adds up to 1.01. Subtracting the desired amount leaves 0.0099. That's sub-cent change, which we're trying to avoid.

Wouldn't it be better to chose all 3 coins, leaving 0.0104 change and no fee?

I guess you made a typo somewhere, but I can't work out what you meant.

If we have three 50BTC outputs and try to spend 100BTC, we should use only two of the outputs.  Previously we were using all three.  Similarly if we have outputs of 50, 50, and 0.01 and want to spend 100BTC, we shouldn't include the 0.01 in the transaction.

Move the stochastic approximation code into a new function and call it once or twice: first for <target> and then for <target+cent> if we weren't able to find a subset of coins that sum to exactly <target>.

Updated the unit tests to no longer conditionally compile out the tests which used to fail.
@dooglus
Copy link
Contributor Author

dooglus commented Feb 27, 2012

Changing the desired amount to 0.999 gives a situation where we should leave the smallest coin. I've added corresponding test cases, thanks.

@sipa
Copy link
Member

sipa commented Jun 12, 2012

Is this pull request superceded or not? I think we want this change for sure, while there are still implementation issues with coin selections.

@luke-jr
Copy link
Member

luke-jr commented Jun 12, 2012

#1416 is the latest rebased iteration of this

@sipa
Copy link
Member

sipa commented Jun 14, 2012

Merged under #1416.

@sipa sipa closed this Jun 14, 2012
@dooglus
Copy link
Contributor Author

dooglus commented Jun 14, 2012

I don't see this (or coin control) in #1416.

@dooglus
Copy link
Contributor Author

dooglus commented Aug 23, 2012

This fix still isn't merged, somehow. The master branch is still doing this:

if (nTotalLower >= nTargetValue + CENT)
    nTargetValue += CENT;

and consequently adds change when it isn't needed.

@gmaxwell
Copy link
Contributor

@dooglus Can you explain why the test case passes? https://github.com/bitcoin/bitcoin/blob/master/src/test/wallet_tests.cpp#L210

Can you suggest a test case that fails?

I suspect you have an unclean clone that has been merged 'nTargetValue +=' doesn't appear anywhere in the codebase as far as I can tell.

@luke-jr
Copy link
Member

luke-jr commented Aug 24, 2012

I also can confirm that code does not exist in master...

@jwillerth
Copy link

Take me off this list

Regards,

Joseph Willerth

Sent from my iPhone

On Aug 23, 2012, at 9:25 PM, Gregory Maxwell notifications@github.com wrote:

@dooglus Can you explain why the test case passes? https://github.com/bitcoin/bitcoin/blob/master/src/test/wallet_tests.cpp#L210

Can you suggest a test case that fails?


Reply to this email directly or view it on GitHub.

@luke-jr
Copy link
Member

luke-jr commented Aug 24, 2012

This isn't a list, it's an issue. To remove yourself from notifications (nobody else can do it for you), do this:

@dooglus
Copy link
Contributor Author

dooglus commented Aug 24, 2012

You're right. I was looking at a cached copy of master. Apologies.

suprnurd pushed a commit to chaincoin-legacy/chaincoin that referenced this pull request Dec 5, 2017
ptschip added a commit to ptschip/bitcoin that referenced this pull request Jan 11, 2018
* Dispaly either the label or the address

If the user is entering a label it is clear they do not
want to see the address. This is the whole point of labelling
and address for the list of transactions.

* Fix the editing of an entry in the Transaction list view.

Previously when trying to edit an entry that had already
been edited, the "enter new address" dialog would appear
rather than the "edit address" dialog.  This was caused by
the the label being returned rather than the address and
as a result the address would not be found in the list, causing
the wrong dialog to open.

* Remove unnecessary boost includes and foreach loops
ptschip pushed a commit to ptschip/bitcoin that referenced this pull request Jan 19, 2018
lateminer pushed a commit to lateminer/bitcoin that referenced this pull request Oct 30, 2019
4e8f46a [Qt] Fixup duplicate label names (Fuzzbawls)

Tree-SHA512: 6cee761fae0d6d387523d286ddbc8fa6f61ef702ec406aa9108dedaccb1b8a0f343b7c01778f9d86be7e76e437d390e468c2593f2514c47350415da696744609
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants