Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.

Feat/#1752 fix witness generation - adding testing #1784

Merged
merged 4 commits into from
Mar 7, 2024

Conversation

KimiWu123
Copy link
Contributor

@KimiWu123 KimiWu123 commented Feb 27, 2024

Description

closed #1752

  • Adding different numbers of txs to test different trie status (e.g. one leaf only, one ext. , one branch and one leaf ...etc)
  • Fixing GetProof (if input is an ext node, it always assign first child of the root ext. node, st.children[0])
  • Fixing getNodeFromBranchRLP (if input is an leaf, it could throw an exception)
  • Refactoring getNodeFromBranchRLP

Issue Link

#1752

Type of change

  • Bug fix (non-breaking change which fixes an issue)

@github-actions github-actions bot added the crate-geth-utils Issues related to the geth-utils workspace member label Feb 27, 2024
@KimiWu123 KimiWu123 force-pushed the feat/#1752-fix-witness-generation-test branch from 4c239d8 to 05f358f Compare February 27, 2024 09:18
@@ -628,7 +635,7 @@ func (st *StackTrie) UpdateAndGetProofs(db ethdb.KeyValueReader, list types.Deri
// order that `list` provides hashes in. This insertion sequence ensures that the
// order is correct.
var indexBuf []byte
for i := 1; i < list.Len() && i <= 0x7f; i++ {
for i := 0; i < list.Len() && i <= 0x7f; i++ {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @miha-stopar , have a question regarding the starting index.
Why doest the for loop start from 1 instead of 0? I saw the case of index 0 was handled in L649-L654. But there is only Update being called, no GetProof. Wondering what will happen if I change to start from 0 and comment out the L649-L654? There is also a simliar case in L655, there is no GetProof after index is 0x80. Wondering the reason why separate into many parts.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, good question :). I tried to remember, but can't say for sure. I guess there was some bug in GetProof and I was debugging it. I think the index can start with 0 and we can delete these two if blocks.

Copy link
Collaborator

@miha-stopar miha-stopar Mar 4, 2024

Choose a reason for hiding this comment

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

I had another look and I was wrong in my previous comment - it has to start with 1. The original code has it this way too: https://github.com/ethereum/go-ethereum/blob/00905f7dc406cfb67f64cd74113777044fb886d8/core/types/hashing.go#L118.

The reason for this is that for i = 0, we get indexBuf = [128] and the following line

k := KeybytesToHex(key)

gives us k = 8. So with i = 0, we insert the leaf into the branch at position 8.

Then, when we are inserting the transaction number 128 we again try to insert the leaf at position 8 (in this case k = [8, 0, 16], but it was already hashed and we cannot do this.

This is why the index 0 is skipped and it starts with 1. And it's why the following two blocks are needed:

if list.Len() > 0 {
	indexBuf = rlp.AppendUint64(indexBuf[:0], 0)
	value := encodeForDerive(list, 0, valueBuf)
	hasher.Update(indexBuf, value)
}
for i := 0x80; i < list.Len(); i++ {
	indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(i))
	value := encodeForDerive(list, i, valueBuf)
	hasher.Update(indexBuf, value)
}

Sorry for the confusion!

Copy link
Contributor Author

@KimiWu123 KimiWu123 Mar 5, 2024

Choose a reason for hiding this comment

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

Do you mean it inserts at position 8 when i = 0? If so, which position will be inserted into when i = 128?

Copy link
Collaborator

Choose a reason for hiding this comment

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

For i = 128, we have key = [8, 1, 8, 0], that means it's inserted in the branch at position 8 (which is a branch that has the transaction with i = 0 at the position 0 - it was added in the block if list.Len() > 0). The second nibble is 1, so it's inserted at position 1 in the branch.

The state after i = 128 is:

  • top level is a branch with branches at positions 0 - 7 (all these branches are fully filled),
  • at position 8 in a top level branch we have a branch with two children at positions 0 (i = 0) and 1 (i = 128).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for detailed explanation again and I think I know how it works 🤞

Copy link
Collaborator

@miha-stopar miha-stopar left a comment

Choose a reason for hiding this comment

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

LGTM!

@KimiWu123 KimiWu123 requested a review from miha-stopar March 6, 2024 02:25
@KimiWu123 KimiWu123 changed the title [WIP] Feat/#1752 fix witness generation - adding testing Feat/#1752 fix witness generation - adding testing Mar 6, 2024
@KimiWu123 KimiWu123 self-assigned this Mar 6, 2024
@KimiWu123 KimiWu123 marked this pull request as ready for review March 6, 2024 02:32
@KimiWu123
Copy link
Contributor Author

Hey @miha-stopar , I think I fixed everything. Could you please give it a quick review again.

st.children[idx].keyOffset = st.keyOffset + 1
st.children[idx] = newLeaf(st.keyOffset+1, key, value, st.db)
} else {
st.children[idx].insert(key, value)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure what's the reason for this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, I just followed how geth implemented it (https://github.com/ethereum/go-ethereum/blob/00905f7dc406cfb67f64cd74113777044fb886d8/trie/stacktrie.go#L211-L215). Besides, it looks more self-explanation for me, one case is to new a leaf and the other is to insert a node. The original one seems too optimized and not easy to understand.

@ChihChengLiang ChihChengLiang self-requested a review March 6, 2024 08:41
Copy link
Collaborator

@ChihChengLiang ChihChengLiang left a comment

Choose a reason for hiding this comment

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

LGTM. Great fix, refactors, and adding tests.

@@ -631,33 +662,40 @@ func (st *StackTrie) UpdateAndGetProofs(db ethdb.KeyValueReader, list types.Deri
for i := 1; i < list.Len() && i <= 0x7f; i++ {
Copy link
Collaborator

Choose a reason for hiding this comment

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

No change is requested here. I just comment to inform the future reviewers.

I saw the duplicated code chunks in L662's loop body, L674's condition body, and L684's loop body.
I was wondering why the duplication but the I saw your comment on L651, which says Geth is also implemented in the same style.

@KimiWu123 KimiWu123 added this pull request to the merge queue Mar 7, 2024
Merged via the queue into main with commit b82ea41 Mar 7, 2024
28 checks passed
@KimiWu123 KimiWu123 deleted the feat/#1752-fix-witness-generation-test branch March 7, 2024 11:09
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
crate-geth-utils Issues related to the geth-utils workspace member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[MPT - stack trie] fix witness generation
3 participants