Skip to content

Conversation

@morcos
Copy link
Contributor

@morcos morcos commented Nov 8, 2016

This makes ModifyNewCoins more conservative in when it marks newly created outputs as FRESH. The usage of ModifyNewCoins in the code base doesn't actually require this because its only ever used on a new cache, however I think its dangerous code that is just asking for a consensus mistake to be used in the future. The comments in the code hopefully clarify a bit better the proper assumptions that need to be made going forward.

EDIT: The changes to the unit test are a bit complicated, but they demonstrate the problem. They fail without the prior commit.

@laanwj
Copy link
Member

laanwj commented Nov 21, 2016

Concept ACK, thanks for improving documentation around this code.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

Tested ACK 3572fea7dce3c20bfca237a53353cdf97c0f3669.

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: "ids" instead of "txs" would be more consistent with other names

Copy link
Contributor

Choose a reason for hiding this comment

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

Arg could be const reference

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this special case actually needed? Seems like origcoins/oldcoins will be empty in this case anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems cleaner to me to not be messing with tx.vin of coinbases

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion: Maybe move the utxoset updates here and elsewhere next to the result updates, since utxoset is essentially just a list of the keys present in the result map. If somebody is changing one of these, they probably need to update the other too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm.. I'll move this above the alltxs insert, but I was trying to keep the order the same for each set of changes.

  • update expected result
  • modify cache the same way the production code does
    (these first two things are what we will compare against each other)
  • modify state used to run the test (which includes utxoset)

@sipa
Copy link
Member

sipa commented Dec 1, 2016

utACK 743009682111aef5c4aab84c0cb5189e4afa4f06
Care to squash?

@morcos morcos force-pushed the saferModifyNewCoins branch from 7430096 to c9270c9 Compare December 1, 2016 02:37
@morcos
Copy link
Contributor Author

morcos commented Dec 1, 2016

Squashed
identical code to 7430096
only nits and minor changes to address test comments from 3572fea

src/coins.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

I hate bip numbers...any chance you can also/or only state what this actually means?

Copy link
Contributor

Choose a reason for hiding this comment

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

(I think you did for 30, but not for 34)

@TheBlueMatt
Copy link
Contributor

While you're at it, can you add a comment to coins.cpp:200 (last else branch in BatchWrite) noting that it is very important that we are only swapping the coins itself, and keeping the flags set on the parent cache.

@TheBlueMatt
Copy link
Contributor

utACK code changes in c9270c96e2ff1676eb87a94ef9b872bea3653804, though I'd prefer more comments. Didnt review tests, but did spend a bunch of time looking at this with @morcos when he was deciding the best route to go for changes.

@morcos
Copy link
Contributor Author

morcos commented Dec 1, 2016

@TheBlueMatt tell me if this is what you had in mind? I'm not sure it's worth it, but don't mind squashing the additional comments if you want them. The whole design of coins would be broken if we were copying all the flags over, but I tried to flag the confusing case.

@TheBlueMatt
Copy link
Contributor

Yea, looks good to me.

@morcos morcos force-pushed the saferModifyNewCoins branch from f166b1f to 8174c1d Compare December 2, 2016 00:40
@morcos
Copy link
Contributor Author

morcos commented Dec 2, 2016

squashed in additional comments

src/coins.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a suggestion, but I think another way you could write this section might be:

    if (!coinbase) {
        // New coins must not already exist.
        assert(ret.first->second.coins.IsPruned());

        if (!(ret.first->second.flags & CCoinsCacheEntry::DIRTY)) {
            // If the coin is known to be pruned (have no unspent outputs) in
            // the current view and the cache entry is not dirty, we know the
            // coin also must be pruned in the base view as well, so it is safe
            // to mark this fresh.
            ret.first->second.flags |= CCoinsCacheEntry::FRESH;
        }
    }

Differences from above:

  • Assert is broader and more prominent.
  • Comments are inline, which I think make this more understandable.
  • FRESH flag will continue to be set in the case of the non-dirty existing cache entry.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

heh. i'll want to think about that 100 times, but that sounds right to me

@morcos morcos force-pushed the saferModifyNewCoins branch from 8174c1d to bd5d189 Compare December 3, 2016 14:13
@morcos
Copy link
Contributor Author

morcos commented Dec 3, 2016

dancing the dance of a clean rebase on the grave of main.cpp

will address @ryanofsky's suggestion separately

@morcos
Copy link
Contributor Author

morcos commented Dec 5, 2016

@sipa @TheBlueMatt Can you guys take a look one more time at the new logic. I'll squash to one commit after you ACK.

@fanquake Can you milestone for 0.14.0

Copy link
Member

@sipa sipa left a comment

Choose a reason for hiding this comment

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

utACK e5f93783cd4c55a4a040719a9006e897e44509a3

src/coins.cpp Outdated
Copy link
Member

Choose a reason for hiding this comment

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

This line could move into an else branch.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Which line? The Clear()? Isn't that needed for the historical coinbase overwrite cases?

@sipa
Copy link
Member

sipa commented Jan 4, 2017 via email

@morcos
Copy link
Contributor Author

morcos commented Jan 4, 2017

oh yes, confused myself..
i can change it if you think thats clearer, or a potential performance improvement?

@ryanofsky
Copy link
Contributor

Test fixes are here: https://github.com/ryanofsky/bitcoin/commits/pr/morcos-saferModifyNewCoins (in the two squash commits) if you see failures after rebasing.

@sipa
Copy link
Member

sipa commented Jan 4, 2017

@morcos No strong opinion, just pointing it out. I don't think it will have a noticable performance impact.

We were marking coins FRESH before being sure they were not overwriting dirty undo data. This condition was never reached in existing code because undo data was always flushed before UpdateCoins was called with new transactions, but could have been exposed in an otherwise safe refactor.
Clarify in the comments the assumptions made in ModifyNewCoins.
Add ability to undo transactions to UpdateCoins unit test.
Thanks to Russ Yanofsky for suggestion on how to make logic clearer and fixing up the ccoins_modify_new test cases.
@morcos morcos force-pushed the saferModifyNewCoins branch from e5f9378 to b50cd7a Compare January 4, 2017 16:40
@morcos
Copy link
Contributor Author

morcos commented Jan 4, 2017

Rebased and squashed

Ignored @sipa's suggestion (sorry)
Included @ryanofsky's updates to the tests and switched the assert to throw std::logic_error so we could non-noisily test that code path.

Diff is here:
https://0bin.net/paste/RH2QCOc8C7lq505F#67QWes6s2d2bttLu6KXZqcKb7YJqEHzmY8pFv9+BV-M

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

utACK b50cd7a

@sipa
Copy link
Member

sipa commented Jan 4, 2017

utACK b50cd7a

@sipa sipa merged commit b50cd7a into bitcoin:master Jan 4, 2017
sipa added a commit that referenced this pull request Jan 4, 2017
b50cd7a Fix dangerous condition in ModifyNewCoins. (Alex Morcos)
@sipa
Copy link
Member

sipa commented Jan 4, 2017

I ran the simulation test 1000x longer than the normal unit tests do.

codablock pushed a commit to codablock/dash that referenced this pull request Oct 23, 2017
b50cd7a Fix dangerous condition in ModifyNewCoins. (Alex Morcos)
random-zebra added a commit to PIVX-Project/PIVX that referenced this pull request Aug 18, 2020
cdbb1a6 Remove unused variable in test, fixing warning. (Russell Yanofsky)
03031a5 Check FRESH validity in CCoinsViewCache::BatchWrite (Russell Yanofsky)
3fb3e03 Fix dangerous condition in ModifyNewCoins. (random-zebra)
228d6bc [test] Add CCoinsViewCache Access/Modify/Write tests (random-zebra)

Pull request description:

  Going on with the coins view cache update work (started with #1774 and #1777).
  This backports the following upstream PRs (adapting them with the assumption that duplicate coinbase transactions are not possible):

  - bitcoin#9308 - [test] Add CCoinsViewCache Access/Modify/Write tests
  - bitcoin#9107 - Safer modify new coins
  - bitcoin#9310 - Assert FRESH validity in CCoinsViewCache::BatchWrite
  - bitcoin#9435 - Removed unused variable in test, fixing warning.

  Note: Will rebase #1773 on top of this one (to change `ApplyTxInUndo` return value in the unit test too).

ACKs for top commit:
  furszy:
    pretty nice one, ACK cdbb1a6
  Fuzzbawls:
    ACK cdbb1a6

Tree-SHA512: 69c534da1083c3c4a535923e98da7750474c6698bb45e042778b539a27fab0455d78aaf670bed9485522f9d2ee25e4ad57fa7d35632523fe7376fe5f5febb1e5
@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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants