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

hash (features|commitment) in output mmr #615

Merged
merged 57 commits into from
Jan 17, 2018

Conversation

antiochp
Copy link
Member

@antiochp antiochp commented Jan 15, 2018

This PR solves #559 by extending the output pmmr to include the output features in the hash.

The proposed solution is described here in more detail - #597

Replaces #215 (which attempted to encode lock_height in the switch commit)

tl;dr

  1. Getting rid of the indexes ensures we never see the "wrong" version of an output (due to a fork).
    Specifically we never see (and use) the wrong lock_height (which can and will break consensus).
  2. We now include output features in the output mmr. This ensures a miner cannot lie about coinbase vs non-coinbase (we can be sure we are checking lock_height as necessary)
  3. We derive lock_height by looking at the full block (we do not rely on the old index) so we know lock_height is being correctly handed

The combination of these changes should ensure we handle the spending of coinbase outputs correctly even under adverse conditions (chain forks and miners reusing wallet keys, creating duplicate commitments).


  • SumCommit takes OutputFeatures & Commitment
    • the hash is now (features|commit)
    • this ensures a given output in the MMR is known to be a coinbase or not (and miner cannot lie)
  • introduce OutputIdentifier so we don't need to pass a SumCommit around everywhere
    • we now need an OutputIdentifier to check is_unspent via the MMR (by comparing the hash)
  • to spend an output we also need to specify the block hash in the Input
    • we can determine lock_height based on height of block + 1,000
    • miner cannot lie about lock_height (also cannot lie about coinbase vs non-coinbase)
  • removed "header by commit" index
    • sender needs to provide block hash
    • wallet maintains block hash of outputs
    • this ensures we never mis-attribute an output in the presence of a chain fork
  • removed "output by commit" index
    • if we need the full output we need to go back to the full block (via block hash)
  • get utxo api endpoint now just returns a commitment (output mmr data only)
  • rework wallet refresh and restore to handle output mmr changes and need to maintain block hashes

TODO -

  • many tests failing (tests failing to build)
  • many build warnings, lack of docs, unused imports etc.
  • cleanup verbose debug logging
  • make block hash optional on an input (only necessary for spending coinbase outputs)

workaround this for wallet refresh and wallet restore
switch commit hash key encodes lock_height
cleanup output by commit index (currently broken...)
utxos come from the sumtrees (and only the sumtrees, limited info)
outputs come from blocks (and we need to look them up via block height)
this uses sumtree in a consistent way
@antiochp
Copy link
Member Author

@ignopeverell this should be in a reasonable place for an early review.
Tests are still failing... and there are a lot of build warnings... but the approach outlined in #597 is implemented (and works locally).
If we are happy with this and think this is worth continuing with then I'll continue to clean it up and get the tests reworked/fixed up.

// edge case here - we may be spending an output with zero-confirmations
// and it just got included in a block.
// The wallet may not know about this new block yet (not yet refreshed).
// Is it safe to assume this the tx was included in the latest block?

This comment was marked as spam.

This comment was marked as spam.

// If we are spending a coinbase output then go find the block
// and check the coinbase maturity rule is being met.
if input.features.contains(COINBASE_OUTPUT) {
// edge case here - we may be spending an output with zero-confirmations

This comment was marked as spam.

@@ -176,6 +183,23 @@ fn test_coinbase_maturity() {

let prev = chain.head_header().unwrap();

<<<<<<< HEAD

This comment was marked as spam.

This comment was marked as spam.

@ignopeverell
Copy link
Contributor

Minor comments but looks good to me overall!

@antiochp antiochp changed the title [WIP] hash (features|commitment) in output mmr hash (features|commitment) in output mmr Jan 16, 2018
@antiochp
Copy link
Member Author

@ignopeverell this should be good to go now if you want to give it a final review?
(3rd time lucky - but this feels like the "right" solution now). 😀

@ignopeverell
Copy link
Contributor

Looking good, ship it!

@antiochp
Copy link
Member Author

antiochp commented Jan 16, 2018

Soon as travis sorts out its infra... multiple builds stuck for a couple of hours. Just kicked off a new one.
Edit: still waiting. Looks like they have a huge backlog of linux builds queued up...

@antiochp
Copy link
Member Author

Merging - travis is still working through its backlog...

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