Skip to content

Conversation

@junha1
Copy link

@junha1 junha1 commented Feb 4, 2020

Here I implemented a high-level abstraction of cryptographical proof, with an instantiation of the our TrieDB. I didn't implement malicious case of unit test.

I'll make a new issue to add some malicious case of unit test after this PR get merged

Closes #10

@junha1 junha1 requested review from majecty and sgkim126 February 4, 2020 01:50
Copy link

@sgkim126 sgkim126 left a comment

Choose a reason for hiding this comment

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

Check clippy.

@junha1
Copy link
Author

junha1 commented Feb 4, 2020

@sgkim126 I fixed all the mentioned points

@junha1 junha1 requested a review from sgkim126 February 4, 2020 03:22
@junha1
Copy link
Author

junha1 commented Feb 4, 2020

@majecty @sgkim126 Please check. I refactored the code into concrete way. All the abstractions stay in my forked repo.

@junha1 junha1 requested review from majecty and sgkim126 February 4, 2020 07:55
src/proof.rs Outdated
None => proof.len() == 1,
}
}
_ => false,
Copy link

Choose a reason for hiding this comment

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

None => false,

src/triedb.rs Outdated
None => Ok((None, Vec::new())), // empty trie
}
}
let x = make_proof_upto(self.db, &NibbleSlice::new(&key), self.root())?;
Copy link

Choose a reason for hiding this comment

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

        let (value, proof) = make_proof_upto(self.db, &NibbleSlice::new(&key), self.root())?;
        let unit = Unit {
            hash: *self.root(),
            key: *key,
            value,
        };
        Ok((unit, CryptoProof(proof)))

x.0 is already an Option<Bytes>.
and you don't need 0: ... to create a new type.

src/triedb.rs Outdated
let left_path = path.mid(partial.len() + 1);
match children[path.mid(partial.len()).at(0) as usize] {
Some(x) => {
let r = make_proof_upto(db, &left_path, &x)?;
Copy link

Choose a reason for hiding this comment

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

This code creates two unnecessary vectors per branch.

let (value, mut reversed_proof) = make_proof_upto(db, &left_path, &x)?;
reversed_proof.push(node_rlp);
Ok((r.0, reversed_proof))

If you make make_proof_upto returns a reversed proof, you can make it more efficient.

src/triedb.rs Outdated
}
let x = make_proof_upto(self.db, &NibbleSlice::new(&key), self.root())?;

let value: Option<Bytes> = x.0.map(|x| x.to_vec());
Copy link

Choose a reason for hiding this comment

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

You just need to reverse the proof once here.

@junha1 junha1 force-pushed the proof branch 2 times, most recently from 6486560 to 0e3fe01 Compare February 4, 2020 10:15
@junha1 junha1 requested a review from sgkim126 February 4, 2020 10:22
@junha1
Copy link
Author

junha1 commented Feb 5, 2020

@sgkim126 @majecty please check the changes and #15 (comment)

@junha1 junha1 force-pushed the proof branch 3 times, most recently from 9fb12a5 to 8d09ab4 Compare February 6, 2020 04:25
@majecty majecty requested a review from ScarletBlue February 6, 2020 04:54
src/triedb.rs Outdated
Comment on lines 153 to 163
/// A proof creation logic for TrieDB.
/// A proof is basically a list of serialized trie nodes, Vec<Bytes>.
/// It starts from the one closest to the root, and to the leaf. (It may not reach the leaf in absence case)
/// Each node can be decoded with RLP. (Note that RLP doesn't guarantee format detail, so you must check our serialization code)
/// In case of precense, the list will contain path from the root to the leaf with the key.
/// In case of absence, the list will contain path to the last node that matches the key.
//
// (A: [nil])
// / \
// (B, g) \
// / \ \
// (C, iant) (D, mail) (E, clang)
//
// Here proof of key 'gmail' will be [(RLP encoding of A), (RLP encoding of B), (RLP encoding of D)]
// proof of key 'galbi' (absence) will be [(RLP encoding of A), (RLP encoding of B)]
Copy link
Contributor

Choose a reason for hiding this comment

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

@ScarletBlue Could you review this comment?
Also, please review other comments in code.

match children[path.mid(partial.len()).at(0) as usize] {
Some(x) => {
let (value, mut reversed_proof) = make_proof_upto(db, &left_path, &x)?;
reversed_proof.push(node_rlp);
Copy link
Contributor

Choose a reason for hiding this comment

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

It's good to use the name reversed_proof!

@majecty
Copy link
Contributor

majecty commented Feb 6, 2020

Let's wait the Seungwoo's review.

src/proof.rs Outdated
}
}

// here proof is created manually

Choose a reason for hiding this comment

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

proof is created manually here

src/triedb.rs Outdated
impl<'db> CryptoStructure for TrieDB<'db> {
/// A proof creation logic for TrieDB.
/// A proof is basically a list of serialized trie nodes, Vec<Bytes>.
/// It starts from the one closest to the root, and to the leaf. (It may not reach the leaf in absence case)

Choose a reason for hiding this comment

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

It starts from the one closest to the root and to the leaf. (It may not reach the leaf in absence case.)

src/triedb.rs Outdated
/// A proof creation logic for TrieDB.
/// A proof is basically a list of serialized trie nodes, Vec<Bytes>.
/// It starts from the one closest to the root, and to the leaf. (It may not reach the leaf in absence case)
/// Each node can be decoded with RLP. (Note that RLP doesn't guarantee format detail, so you must check our serialization code)

Choose a reason for hiding this comment

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

Each node can be decoded with RLP. (Note that RLP doesn't guarantee format detail, so you must check our serialization code.)

src/triedb.rs Outdated
/// A proof is basically a list of serialized trie nodes, Vec<Bytes>.
/// It starts from the one closest to the root, and to the leaf. (It may not reach the leaf in absence case)
/// Each node can be decoded with RLP. (Note that RLP doesn't guarantee format detail, so you must check our serialization code)
/// In case of precense, the list will contain path from the root to the leaf with the key.

Choose a reason for hiding this comment

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

In case of precense, the list will contain a path from the root to the leaf with the key.

src/triedb.rs Outdated
/// It starts from the one closest to the root, and to the leaf. (It may not reach the leaf in absence case)
/// Each node can be decoded with RLP. (Note that RLP doesn't guarantee format detail, so you must check our serialization code)
/// In case of precense, the list will contain path from the root to the leaf with the key.
/// In case of absence, the list will contain path to the last node that matches the key.

Choose a reason for hiding this comment

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

In case of absence, the list will contain a path to the last node that matches the key.

src/triedb.rs Outdated
// / \ \
// (C, iant) (D, mail) (E, clang)
//
// Here proof of key 'gmail' will be [(RLP encoding of A), (RLP encoding of B), (RLP encoding of D)]

Choose a reason for hiding this comment

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

Here, the proof of key 'gmail' will be [(RLP encoding of A), (RLP encoding of B), (RLP encoding of D)]

src/triedb.rs Outdated
// (C, iant) (D, mail) (E, clang)
//
// Here proof of key 'gmail' will be [(RLP encoding of A), (RLP encoding of B), (RLP encoding of D)]
// proof of key 'galbi' (absence) will be [(RLP encoding of A), (RLP encoding of B)]

Choose a reason for hiding this comment

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

Here, the proof of key 'galbi' (absence) will be [(RLP encoding of A), (RLP encoding of B)]

src/triedb.rs Outdated
// Here proof of key 'gmail' will be [(RLP encoding of A), (RLP encoding of B), (RLP encoding of D)]
// proof of key 'galbi' (absence) will be [(RLP encoding of A), (RLP encoding of B)]
fn make_proof(&self, key: &H256) -> crate::Result<(CryptoProofUnit, CryptoProof)> {
// it makes reversed proof for sake of efficency on push() operation

Choose a reason for hiding this comment

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

it creates a reversed proof for the sake of a more efficient push() operation.

src/proof.rs Outdated
/// A verification logic of TrieDB's Merkle proof.
/// For the format of proof, check the make_proof() function.
/// It verifies the proof with a given unit of test.
/// It should never abort or fail, but only return 'false' as result of getting invalid or ill-formed proof.

Choose a reason for hiding this comment

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

It should never abort or fail, but only return 'false' as a result of getting an invalid or ill-formed proof.

@majecty
Copy link
Contributor

majecty commented Feb 6, 2020

@junha1 Please tell me when your PR is ready to be merged.

Here I implemented creation / verification logic of Merkle proof, with o
ur TrieDB. It includes some massive iterative unit tests for some not-ma
licious cases.
@majecty majecty merged commit e41cc11 into CodeChain-io:master Feb 6, 2020
@majecty majecty mentioned this pull request Feb 13, 2020
11 tasks
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.

Implement Merkle proof

4 participants