-
Notifications
You must be signed in to change notification settings - Fork 990
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
Merkle Proofs #716
Merkle Proofs #716
Conversation
todo - we hit a peak, then we need to get to the root somehow - actually get the hashes to build the proof
need to test on test case with multiple peaks
@ignopeverell I keep getting tripped up with MMR rewind... I think I have managed to (finally) convince myself that we cannot use So am I right in thinking the Merkle proof can only be created at the time the block itself is created (we cannot reliable regenerate the exact same utxo_root otherwise)? |
I think you're correct. Note that you should be able to rewind to that position for a little while, even in presence of pruning. But when the local storage gets compacted then actual data you would need gets removed. So we could wait 10-20 blocks to avoid storing data that could be useless in the common 1-block reorg case, but beyond that you're taking a chance. Note that waiting a bit sounds like a premature optimization to me at this point, just mentioning it as an example. |
there are cases where it does not...
need to fix the tests up now and cleanup the code and add docs for functions etc.
@ignopeverell After fixing Planning to investigate if this works as-is with a pruned tree or if we need to modify the tree compacting behavior to retain leaf siblings to keep Merkle proofs working post-compaction step on the output PMMR. I think we're getting close to landing this PR (hopefully). |
made nonce for short_ids explicit to help with this
This is ready for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! Mostly commented on the numerous leftovoer TODOs :-)
api/src/types.rs
Outdated
state.serialize_field("output_type", &self.output_type)?; | ||
state.serialize_field("commit", &util::to_hex(self.commit.0.to_vec()))?; | ||
state.serialize_field("switch_commit_hash", &self.switch_commit_hash.to_hex())?; | ||
state.serialize_field("spent", &self.spent)?; | ||
state.serialize_field("proof", &self.proof)?; | ||
state.serialize_field("proof_hash", &self.proof_hash)?; | ||
|
||
// TODO - rework this |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
core/src/core/block.rs
Outdated
@@ -660,6 +662,30 @@ impl Block { | |||
Ok(()) | |||
} | |||
|
|||
// TODO - how do we verify Merkle Proof here? |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
core/src/core/transaction.rs
Outdated
@@ -470,14 +480,38 @@ impl Transaction { | |||
self.kernels.verify_sort_order()?; | |||
Ok(()) | |||
} | |||
|
|||
// TODO - how do we verify Merkle Proof here? |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
wallet/src/sender.rs
Outdated
let merkle_proof = coin.merkle_proof.clone(); | ||
let merkle_proof = merkle_proof.unwrap().merkle_proof(); | ||
|
||
// TODO - we need a Merkle Proof here to spend a coinbase output |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
} else { | ||
println!("MISMATCH BECAUSE THE BLOODY THING MISMATCHES"); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Cannot find fault here.. really well done. Ensuring siblings still exist on compaction is a fairly trivial implementation detail, all we need to do is ensure the top peak in the prune list isn't actually excluded (just everything underneath it. |
@yeastplume yeah I'm planning to go take a look at the compaction stuff later today I think. @ignopeverell thanks for that - I'd kind of skipped that last pass through all those... working through them now. |
Just waiting for final travis run then I'll merge. |
* family_branch() to recursively call family() up the branch todo - we hit a peak, then we need to get to the root somehow - actually get the hashes to build the proof * wip * some additional testing around merkle tree branches * track left/right branch for each sibling as we build the merkle path up * MerkleProof and basic (incomplete) verify fn * I think a MerkleProof verifies correctly now need to test on test case with multiple peaks * basic pmmr merkle proof working * MerkleProof now serializable/deserializable * coinbase maturity via merkle proof basically working * ser/deser merkle proof into hex in api and wallet.dat * cleanup * wip - temporarily saving merkle proofs to the commit index * assert merkle proof in store matches the rewound version there are cases where it does not... * commit * commit * can successfully rewind the output PMMR and generate a Merkle proof need to fix the tests up now and cleanup the code and add docs for functions etc. * core tests passing * fixup chain tests using merkle proofs * pool tests working with merkle proofs * api tests working with merkle proof * fix the broken comapct block hashing behavior made nonce for short_ids explicit to help with this * cleanup and comment as necessary * cleanup variety of TODOs
Functionality to generate a Merkle proof for a given entry in the output MMR.
Merkle proof consists of the following -
A Merkle proof allows us to -
API serializes/deserializes Merkle proofs as hex
Wallet maintains Merkle proof (and corresponding block hash) for each unspent coinbase output
Spending a coinbase output requires the block hash and Merkle proof to be provided in the input
TODO -
Cannot userewind
to put the MMR back into a state where we can create an old Merkle proof (because of pruning?) - confirm we can only create a Merkle proof at the same time the block is originally created?We can now successfully generate a Merkle proof via
sumtree.rewind()
.This definitely works for a full archival node.
This will in principle work for a pruned non-archive node - but we need to confirm this.
We uncovered a subtle bug in our
sumtree.rewind()
logic - #727 (FIXED).