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

Commit

Permalink
Wrong extension node: expected RLC computation fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
miha-stopar committed Apr 12, 2024
1 parent 89c3bbb commit f41a249
Show file tree
Hide file tree
Showing 7 changed files with 605 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2361,7 +2361,7 @@ func TestStorageWrongExtensionNode(t *testing.T) {
statedb.IntermediateRoot(false)

// Returns extension node
key3 := common.HexToHash("0x1200000000000000000000000000000000000000000000000000000000000000")
key3 := common.HexToHash("0x1277000000000000000000000000000000000000000000000000000000000000")

val := common.BigToHash(big.NewInt(int64(17)))
trieMod := TrieModification{
Expand All @@ -2376,3 +2376,45 @@ func TestStorageWrongExtensionNode(t *testing.T) {

oracle.PreventHashingInSecureTrie = false
}

func TestStorageWrongExtensionNode1(t *testing.T) {
blockNum := 0
blockNumberParent := big.NewInt(int64(blockNum))
blockHeaderParent := oracle.PrefetchBlock(blockNumberParent, true, nil)
database := state.NewDatabase(blockHeaderParent)
statedb, _ := state.New(blockHeaderParent.Root, database, nil)
addr := common.HexToAddress("0x40efbf12580138bc623c95757286df4e24eb81c9")

statedb.DisableLoadingRemoteAccounts()
oracle.PreventHashingInSecureTrie = true // to store the unchanged key

statedb.CreateAccount(addr)
statedb.IntermediateRoot(false)

key1 := common.HexToHash("0x01230000000000000000000000000000000000000000000000000000000000000")
key2 := common.HexToHash("0x01231000000000000000000000000000000000000000000000000000000000000")

val1 := common.HexToHash("0xCE9F6C9634165F91E22E58B90E3EDE393D959E47")
val2 := common.HexToHash("0xEC9F6C9634165F91E22E58B90E3EDE393D959E47")

statedb.SetState(addr, key1, val1)
statedb.SetState(addr, key2, val2)

statedb.IntermediateRoot(false)

// Returns extension node
key3 := common.HexToHash("0x01277000000000000000000000000000000000000000000000000000000000000")

val := common.BigToHash(big.NewInt(int64(17)))
trieMod := TrieModification{
Type: StorageDoesNotExist,
Key: key3,
Value: val,
Address: addr,
}
trieModifications := []TrieModification{trieMod}

prepareWitness("StorageWrongExtensionNode1", trieModifications, statedb)

oracle.PreventHashingInSecureTrie = false
}
6 changes: 3 additions & 3 deletions geth-utils/gethutil/mpt/witness/prepare_witness.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func obtainAccountProofAndConvertToWitness(tMod TrieModification, statedb *state
cRoot := statedb.GetTrie().Hash()

accountProof1, aNeighbourNode2, aExtNibbles2, isLastLeaf2, aIsNeighbourNodeHashed2, err := statedb.GetProof(addr)
check(err)
check(err)

if tMod.Type == AccountDoesNotExist && len(accountProof) == 0 {
// If there is only one account in the state trie and we want to prove for some
Expand Down Expand Up @@ -524,9 +524,9 @@ func convertProofToWitness(statedb *state.StateDB, addr common.Address, addrh []
keyAfter = append(keyAfter, trie.HexToCompact(nibblesAfter)...)

isExtension := true
// Dummy branch. The constraint of the branch being in the extension node and the constraint of the
// Dummy branch with no empty nodes. The constraint of the branch being in the extension node and the constraint of the
// leaf being in the branch need to be disabled for this case.
branchRlp := []byte{248, 81, 160, 244, 245, 0, 27, 233, 28, 128, 158, 163, 228, 185, 193, 250, 228, 226, 205, 233, 119, 98, 15, 183, 171, 187, 182, 172, 113, 115, 190, 167, 217, 33, 211, 160, 72, 229, 31, 123, 46, 26, 63, 24, 242, 142, 183, 252, 47, 111, 99, 255, 0, 118, 149, 196, 125, 165, 118, 4, 189, 149, 202, 221, 129, 141, 240, 209, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128};
branchRlp := []byte{249, 2, 17, 160, 215, 178, 43, 142, 72, 221, 147, 48, 230, 157, 99, 126, 109, 240, 144, 184, 54, 167, 1, 19, 157, 71, 126, 226, 97, 100, 220, 221, 118, 5, 202, 114, 160, 195, 19, 38, 251, 242, 179, 135, 46, 118, 82, 177, 213, 78, 156, 167, 171, 134, 95, 6, 233, 153, 168, 219, 176, 131, 34, 215, 213, 95, 252, 168, 165, 160, 242, 119, 75, 182, 209, 50, 158, 172, 168, 239, 218, 202, 172, 144, 155, 94, 44, 154, 149, 92, 253, 83, 150, 12, 4, 176, 33, 46, 25, 36, 170, 225, 160, 156, 18, 160, 254, 15, 159, 132, 100, 9, 112, 178, 98, 98, 93, 76, 54, 189, 166, 63, 219, 45, 193, 25, 238, 218, 78, 235, 150, 206, 67, 252, 253, 160, 100, 75, 99, 34, 122, 170, 85, 172, 143, 62, 172, 142, 154, 219, 40, 105, 162, 136, 113, 194, 41, 38, 129, 211, 105, 114, 94, 62, 145, 244, 97, 170, 160, 229, 94, 177, 9, 226, 34, 180, 156, 33, 249, 119, 163, 74, 194, 218, 172, 92, 90, 13, 44, 22, 231, 5, 100, 72, 203, 19, 192, 62, 46, 34, 34, 160, 15, 175, 179, 52, 244, 84, 197, 105, 112, 43, 252, 115, 186, 76, 237, 251, 88, 5, 62, 201, 157, 9, 7, 153, 100, 224, 202, 249, 250, 183, 125, 248, 160, 14, 229, 239, 45, 75, 116, 39, 109, 41, 89, 200, 43, 18, 94, 204, 133, 62, 175, 23, 200, 68, 93, 170, 95, 36, 226, 233, 183, 66, 98, 37, 184, 160, 6, 197, 49, 201, 57, 39, 248, 81, 26, 196, 11, 167, 230, 243, 100, 223, 97, 38, 20, 1, 226, 39, 180, 161, 172, 204, 67, 80, 173, 223, 89, 42, 160, 3, 131, 195, 206, 124, 22, 207, 14, 142, 91, 216, 135, 77, 202, 69, 1, 53, 115, 223, 85, 52, 95, 43, 227, 237, 82, 138, 95, 93, 70, 227, 232, 160, 98, 109, 64, 32, 201, 140, 205, 221, 164, 1, 209, 57, 84, 209, 249, 108, 87, 101, 70, 12, 37, 160, 114, 139, 27, 145, 104, 130, 62, 183, 150, 108, 160, 91, 17, 33, 207, 142, 243, 30, 99, 20, 173, 20, 129, 191, 59, 158, 186, 174, 22, 77, 226, 131, 140, 56, 74, 194, 53, 68, 176, 249, 189, 108, 176, 160, 39, 24, 29, 240, 236, 191, 237, 195, 74, 255, 251, 61, 19, 232, 218, 181, 111, 83, 69, 125, 70, 208, 135, 182, 81, 0, 125, 85, 38, 21, 25, 11, 160, 191, 249, 76, 252, 217, 172, 58, 95, 133, 138, 144, 243, 9, 87, 191, 253, 23, 150, 215, 186, 153, 214, 27, 17, 128, 10, 154, 202, 202, 43, 193, 173, 160, 238, 147, 22, 82, 116, 71, 41, 238, 84, 0, 62, 40, 0, 153, 205, 90, 194, 234, 61, 255, 205, 197, 55, 0, 41, 239, 197, 174, 219, 163, 6, 130, 160, 22, 99, 129, 222, 131, 163, 115, 40, 32, 94, 210, 97, 181, 141, 77, 173, 9, 184, 214, 164, 50, 44, 139, 113, 241, 255, 7, 213, 43, 8, 145, 41, 128}

extNode := proof2[len(proof2)-1] // Let's name it E1
bNode := prepareBranchNode(branchRlp, branchRlp, extNode, extNode, extListRlpBytes, extValues,
Expand Down
59 changes: 48 additions & 11 deletions zkevm-circuits/src/mpt_circuit/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,7 @@ impl<F: Field> WrongLeafGadget<F> {
#[derive(Clone, Debug, Default)]
pub struct WrongExtNodeGadget<F> {
is_key_equal: IsEqualGadget<F>,
mult_without_branch_nibble: Cell<F>,
}

impl<F: Field> WrongExtNodeGadget<F> {
Expand All @@ -1338,17 +1339,31 @@ impl<F: Field> WrongExtNodeGadget<F> {
let mut config = WrongExtNodeGadget::default();
circuit!([meta, cb.base], {
ifx! {is_wrong_ext_case => {
config.mult_without_branch_nibble = cb.query_cell();

// We have a key split into three parts,
// meaning that the first part parity doesn't
// tell us about the parity of the second part (depends on the third part as well).

let data0 = [wrong_ext_middle.clone(), wrong_ext_middle_nibbles.clone()];

// key_data.is_odd (and key_data.num_nibbles) takes into account also the branch nibble and we do not want this,
// the actual value we need is not!(key_data.is_odd)

// key_data.is_odd (and key_data.num_nibbles) takes into account also the branch nibble and we do not want this,
// the actual value we need is !key_data.is_odd
// key_data_prev.is_odd = true, key_data.is_odd = true -> is_key_part_odd = true
// key_data_prev.is_odd = true, key_data.is_odd = false -> is_key_part_odd = false
// key_data_prev.is_odd = false, key_data.is_odd = true -> is_key_part_odd = false
// key_data_prev.is_odd = false, key_data.is_odd = false -> is_key_part_odd = true
let is_key_part_odd = not!(xor::expr(key_data_prev.is_odd.expr(), key_data.is_odd.expr()));

let after_middle_rlc = key_data_prev.rlc.expr()
+ ext_key_rlc_expr(
cb,
wrong_ext_middle.clone(),
key_data_prev.mult.expr(),
key_data.is_odd.expr(),
is_key_part_odd,
key_data_prev.is_odd.expr(),
data0
.iter()
Expand All @@ -1359,22 +1374,25 @@ impl<F: Field> WrongExtNodeGadget<F> {
&cb.key_r.expr(),
);

// odd odd -> even
// odd even -> odd
// even odd -> odd
// even even -> even
let after_two_parts_is_odd =
xor::expr(key_data_prev.is_odd.expr(), key_data.is_odd.expr());
let after_two_parts_is_odd = not!(key_data.is_odd.expr());

// The total number of nibbles is odd, thus:
let third_part_is_odd = after_two_parts_is_odd.clone();

// We cannot use key_data.mult because it takes into account also the branch nibble.
let mult = config.mult_without_branch_nibble.expr();
ifx! {key_data.is_odd => {
require!(mult => key_data.mult.expr());
} elsex {
require!(mult.clone() * cb.key_r.expr() => key_data.mult.expr());
}}

let data1 = [wrong_ext_after.clone(), wrong_ext_after_nibbles.clone()];
let rlc = after_middle_rlc.clone()
+ ext_key_rlc_expr(
cb,
wrong_ext_after.clone(),
key_data.mult.expr(),
mult.clone(),
third_part_is_odd,
after_two_parts_is_odd,
data1
Expand Down Expand Up @@ -1411,10 +1429,18 @@ impl<F: Field> WrongExtNodeGadget<F> {
key_data_prev: KeyDataWitness<F>,
) {
let items = [wrong_ext_middle.clone(), wrong_ext_middle_nibbles];
let (after_middle_rlc, _) = ext_key_rlc_calc_value(

// key_data.is_odd (and key_data.num_nibbles) takes into account also the branch nibble and we do not want this,
// the actual value we need is !key_data.is_odd
// key_data_prev.is_odd = true, key_data.is_odd = true -> is_key_part_odd = true
// key_data_prev.is_odd = true, key_data.is_odd = false -> is_key_part_odd = false
// key_data_prev.is_odd = false, key_data.is_odd = true -> is_key_part_odd = false
// key_data_prev.is_odd = false, key_data.is_odd = false -> is_key_part_odd = true
let is_key_part_odd = key_data_prev.is_odd == key_data.is_odd;
let after_middle_rlc = key_data_prev.rlc + ext_key_rlc_calc_value(
wrong_ext_middle,
key_data_prev.mult,
key_data.is_odd,
is_key_part_odd,
key_data_prev.is_odd,
items
.iter()
Expand All @@ -1423,7 +1449,18 @@ impl<F: Field> WrongExtNodeGadget<F> {
.try_into()
.unwrap(),
region.key_r,
);
).0;

let mut mult = key_data.mult;
if !key_data.is_odd {
let iters = (key_data.num_nibbles - 1 - 1) / 2; // -1 because of the branch nibble, -1 because of being odd
mult = F::one();

for _ in 0..iters {
mult = mult * region.key_r;
}
}
let _ = self.mult_without_branch_nibble.assign(region, offset, mult);

let _ = self.is_key_equal.assign(
region,
Expand Down
3 changes: 3 additions & 0 deletions zkevm-circuits/src/mpt_circuit/storage_leaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ impl<F: Field> StorageLeafConfig<F> {

let is_wrong_leaf_case = and::expr(&[config.is_non_existing_storage_proof.expr(), not!(config.parent_data[1].is_extension), not!(config.is_placeholder_leaf[1].expr())]);

require!(is_wrong_leaf_case => 0.expr());
require!(config.is_placeholder_leaf[1].expr() => 0.expr());

// When non-existing-proof, it needs to be one of the following cases:
// (1) wrong leaf, (2) wrong extension node, (3) nil leaf - we need to check the sum of these
// three cases is 1.
Expand Down
Loading

0 comments on commit f41a249

Please sign in to comment.