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

Extension into branch #1756

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
af3fd83
getDriftedPosition fix; test added
miha-stopar Feb 5, 2024
dd04ccc
Fix in equipLeafWithModExtensionNode; go fmt
miha-stopar Feb 6, 2024
39a8743
reapplying changes from PR #1724
miha-stopar Feb 9, 2024
45582d1
Changes in witness.rs
miha-stopar Feb 14, 2024
78899ef
Only storage keys which change
miha-stopar Feb 15, 2024
77b2a73
params increased
miha-stopar Feb 15, 2024
4414c85
Wrong extension node test; adapting witness generator for wrong exten…
miha-stopar Feb 21, 2024
bd82e59
Preparing witness for wrong extension node
miha-stopar Feb 22, 2024
a90ae32
Construct placeholder leaf for wrong extension node case
miha-stopar Feb 27, 2024
ca7e2d5
is_extension added to ParentData (for wrong extension data handling);…
miha-stopar Feb 28, 2024
f70cace
WrongGadget supports wrong extension nodes now
miha-stopar Mar 6, 2024
12d6b1d
Fix in account_leaf key data witness load
miha-stopar Mar 6, 2024
ae39a6a
Test for account wrong extension node; statedb: prevent address hashing
miha-stopar Mar 6, 2024
13a7759
Account wrong extension node test
miha-stopar Mar 8, 2024
edb7a56
extNibbles returned by getProof has the same number as the proof now
miha-stopar Mar 11, 2024
87724d3
Fixing handling the accounts without hashing in the trie
miha-stopar Mar 12, 2024
06fb0ca
Fix in account address hashing prevention
miha-stopar Mar 13, 2024
3195338
PreventHashing split into storage/account PreventHashing
miha-stopar Mar 13, 2024
acb8b23
Implementing accout wrong extension node witness
miha-stopar Mar 15, 2024
87f469e
Non existing account: wrong extension node fix
miha-stopar Mar 18, 2024
1385527
removing remnants
miha-stopar Mar 25, 2024
d6c896a
Working on wrong extension node
miha-stopar Mar 26, 2024
8fccf9c
Wrong extension node: three parts of the key adds up to key rlc
miha-stopar Mar 28, 2024
46627dd
WrongExtNodeGadget introduced
miha-stopar Mar 29, 2024
8ef1481
is_key_equal added to WrongExtNodeGadget
miha-stopar Mar 29, 2024
9817e1d
Adding info whether ext. node is in the last level
miha-stopar Apr 1, 2024
91325b9
branching for non-existing proof
miha-stopar Apr 2, 2024
133d8b2
Wrong extension node case - constraints that don't apply ignored
miha-stopar Apr 9, 2024
89c3bbb
Wrong extension node: selector constraints; wrong extension node gadg…
miha-stopar Apr 10, 2024
f41a249
Wrong extension node: expected RLC computation fixed
miha-stopar Apr 12, 2024
b1c8824
Debugging constraints removed
miha-stopar Apr 12, 2024
d10281f
Fixing problems introduced by adding wrong extension node gadget
miha-stopar Apr 16, 2024
b2063d6
WrongExtensionGadget implemented; tests pass
miha-stopar Apr 17, 2024
b38ab98
gofmt
miha-stopar Apr 17, 2024
8b98187
cargo fmt
miha-stopar Apr 17, 2024
38af861
ailing test ignored (debugging)
miha-stopar Apr 18, 2024
612a026
Test reenabled
miha-stopar Apr 18, 2024
cba233e
Merge branch 'main' into extension-into-branch
miha-stopar Apr 18, 2024
d325bf5
Failing test commented out
miha-stopar Apr 18, 2024
7e2c7c3
Merge branch 'extension-into-branch' of https://github.com/privacy-sc…
miha-stopar Apr 18, 2024
1dd4008
Test reenabled
miha-stopar Apr 18, 2024
ab17509
clippy fixes
miha-stopar Apr 19, 2024
641ef3d
cargo fmt
miha-stopar Apr 19, 2024
b7b8aa1
Removed constructedLeaf; some cleaning
miha-stopar Apr 23, 2024
dd04884
gofmt
miha-stopar Apr 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion bin/mpt-test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ This tool aims to verify mainnet blocks for the MPT circuit.

## Running tests

Set the environment variable `WEB3_PROVIDER_URL` to a mainnet JSON-RPC provider, for example:
```
export WEB3_PROVIDER_URL=https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161
```

Just run `./test_mainnet_blocks.sh`

NOTE: this run the tests with keccak testing disabled, because it takes SO MUCH to test with keccaks enables. If you want to run them with keccak, just run `cargo run --release --no-default-features`.
Expand All @@ -13,7 +18,6 @@ NOTE: this run the tests with keccak testing disabled, because it takes SO MUCH
In order to add more blocks to prove you have to:

- Add new entry in the `access-lists` folder
- Set the environment variable `WEB3_SERVICE_PROVIDER` to a mainnet JSON-RPC provider
- Run the tests again
- You will have to upload the cache file again (web3_rpc_cache.bin) and update the `test_mainnet_blocks.sh` file

Expand Down
72 changes: 51 additions & 21 deletions bin/mpt-test/src/circuit/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,48 @@ impl<F: Field> Witness<F> {
let mut initial_values = Vec::new();
let mut changed_values = Vec::new();

// Put the read proofs first:
if include_initial_values {
for entry in access_list.clone().0 {
let AccessListItem {
address,
storage_keys,
} = entry;

let old = provider
.get_proof(
address,
storage_keys.clone(),
Some(BlockId::Number(BlockNumber::Number(block_no - 1))),
)
.await?;

// Skip if the account doesn't exist in the old block.
if old.balance.is_zero()
&& old.code_hash.is_zero()
&& old.nonce.is_zero()
&& old.storage_hash.is_zero()
{
continue;
}

initial_values.push(TrieModification::balance(address, old.balance));
initial_values.push(TrieModification::nonce(address, old.nonce));
initial_values.push(TrieModification::codehash(address, old.code_hash));

for key in storage_keys.iter() {
let old = old.storage_proof.iter().find(|p| p.key == *key).unwrap();
if old.value == U256::zero() {
initial_values.push(TrieModification::storage_does_not_exist(
address, *key, old.value,
));
} else {
initial_values.push(TrieModification::storage(address, *key, old.value));
}
}
}
}

for entry in access_list.0 {
let AccessListItem {
address,
Expand Down Expand Up @@ -252,42 +294,30 @@ impl<F: Field> Witness<F> {
continue;
}

if include_initial_values {
initial_values.push(TrieModification::balance(address, old.balance));
initial_values.push(TrieModification::nonce(address, old.nonce));
initial_values.push(TrieModification::codehash(address, old.code_hash));

for key in storage_keys.iter() {
let old = old.storage_proof.iter().find(|p| p.key == *key).unwrap();
if old.value == U256::zero() {
initial_values.push(TrieModification::storage_does_not_exist(
address, *key, old.value,
));
} else {
initial_values.push(TrieModification::storage(address, *key, old.value));
}
}
}

// check for this address changes
if old.nonce != new.nonce {
changed_values.push(TrieModification::nonce(address, new.nonce));
}
if old.balance != new.balance {
changed_values.push(TrieModification::balance(address, new.balance));
}
if old.code_hash != new.code_hash
// && new.code_hash != *DEFAULT_CODE_HASH
{

if old.code_hash != new.code_hash && new.code_hash != *DEFAULT_CODE_HASH {
changed_values.push(TrieModification::codehash(address, new.code_hash));
}

for key in storage_keys {
let new = new.storage_proof.iter().find(|p| p.key == key).unwrap();
changed_values.push(TrieModification::storage(address, key, new.value));
let old = old.storage_proof.iter().find(|p| p.key == key).unwrap();
if !(old.value == U256::zero() && new.value == U256::zero()) {
changed_values.push(TrieModification::storage(address, key, new.value));
}
}
}

println!("initial_values.len(): {}", initial_values.len());
println!("changed_values.len(): {}", changed_values.len());

let mut trie_modifications = initial_values;
trie_modifications.append(&mut changed_values);

Expand Down
7 changes: 4 additions & 3 deletions bin/mpt-test/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,20 @@ async fn mock_prove(block_no: u64, access_list: &str) -> Result<()> {

let access_list: AccessList = serde_json::from_str(access_list)?;
let proof_count = 2 * access_list.0.len() * 3
+ access_list
+ 2 * access_list
.0
.iter()
.map(|k| k.storage_keys.len())
.sum::<usize>();

let max_nodes = 40000;
let max_nodes = 1000000;
let degree = 20;

let witness = Witness::<Fr>::build(provider_url, U64::from(block_no), Some(access_list), true)
.await?
.unwrap();

let circuit = StateUpdateCircuit::new(witness, 16, max_nodes, proof_count + 10)?;
let circuit = StateUpdateCircuit::new(witness, degree, max_nodes, proof_count + 10)?;
circuit.assert_satisfied();
Ok(())
}
Expand Down
33 changes: 33 additions & 0 deletions geth-utils/gethutil/mpt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# MPT witness generator

## Generate witnesses

To generate witnesses for the MPT circuit, execute

```
go test -v ./...
```

To generate the tests that use a local blockchain you need a local `geth`. You would
need to run something like:
```
geth --dev --http --ipcpath ~/Library/Ethereum/geth.ipc

```
The local `geth` is used to generate some tests that have a small number of accounts so that
these accounts appear in the first or second level of the trie. You might need to remove the
database if you already have some accounts:

```
geth removedb
```

The witness files will appear in generated_witnesses folder.

## Format the code

To format the code use:

```
gofmt -w ./*
```
3 changes: 2 additions & 1 deletion geth-utils/gethutil/mpt/oracle/prefetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ var RemoteUrl = "https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161"
var LocalUrl = "http://localhost:8545"

// For generating special tests for MPT circuit:
var PreventHashingInSecureTrie = false
var PreventHashingInSecureTrie = false // storage
var AccountPreventHashingInSecureTrie = false

func toFilename(key string) string {
return fmt.Sprintf("/tmp/eth/json_%s", key)
Expand Down
4 changes: 2 additions & 2 deletions geth-utils/gethutil/mpt/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (db *Database) CopyTrie(t Trie) Trie {

// OpenTrie opens the main account trie at a specific root hash.
func (db *Database) OpenTrie(root common.Hash) (Trie, error) {
tr, err := trie.NewSecure(root, db.db)
tr, err := trie.NewSecure(root, db.db, false)
if err != nil {
return nil, err
}
Expand All @@ -62,7 +62,7 @@ func (db *Database) OpenTrie(root common.Hash) (Trie, error) {
// OpenStorageTrie opens the storage trie of an account.
func (db *Database) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
//return SimpleTrie{db.BlockNumber, root, true, addrHash}, nil
tr, err := trie.NewSecure(root, db.db)
tr, err := trie.NewSecure(root, db.db, true)
if err != nil {
return nil, err
}
Expand Down
28 changes: 23 additions & 5 deletions geth-utils/gethutil/mpt/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,12 @@ func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash {

// GetProof returns the Merkle proof for a given account.
func (s *StateDB) GetProof(addr common.Address) ([][]byte, []byte, [][]byte, bool, bool, error) {
return s.GetProofByHash(crypto.Keccak256Hash(addr.Bytes()))
newAddr := crypto.Keccak256Hash(addr.Bytes())
if oracle.AccountPreventHashingInSecureTrie {
bytes := append(addr.Bytes(), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}...)
newAddr = common.BytesToHash(bytes)
}
return s.GetProofByHash(newAddr)
}

// GetProofByHash returns the Merkle proof for a given account.
Expand All @@ -311,7 +316,13 @@ func (s *StateDB) GetProofByHash(addrHash common.Hash) ([][]byte, []byte, [][]by
// GetStorageProof returns the Merkle proof for given storage slot.
func (s *StateDB) GetStorageProof(a common.Address, key common.Hash) ([][]byte, []byte, [][]byte, bool, bool, error) {
var proof proofList
trie := s.StorageTrie(a)
newAddr := a
if oracle.AccountPreventHashingInSecureTrie {
bytes := append(a.Bytes(), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}...)
newAddr = common.BytesToAddress(bytes)
}

trie := s.StorageTrie(newAddr)
if trie == nil {
return proof, nil, nil, false, false, errors.New("storage trie for requested address does not exist")
}
Expand Down Expand Up @@ -457,7 +468,7 @@ func (s *StateDB) SetStateObjectIfExists(addr common.Address) {
}

/*
When an account that does not exist is tried to be fetched by PrefetchAccount and when the some other account
When an account that does not exist is being fetched by PrefetchAccount and when some other account
exist at the overlapping address (the beginning of it), this (wrong) account is obtained by PrefetchAccount
and needs to be ignored.
*/
Expand Down Expand Up @@ -533,8 +544,15 @@ func (s *StateDB) updateStateObject(obj *stateObject) {
if err != nil {
panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
}
if err = s.trie.TryUpdateAlwaysHash(addr[:], data); err != nil {
s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err))

if !oracle.AccountPreventHashingInSecureTrie {
if err = s.trie.TryUpdateAlwaysHash(addr[:], data); err != nil {
s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err))
}
} else {
if err = s.trie.TryUpdate(addr[:], data); err != nil {
s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err))
}
}

// If state snapshotting is active, cache the data til commit. Note, this
Expand Down
16 changes: 5 additions & 11 deletions geth-utils/gethutil/mpt/trie/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,33 +102,27 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) (
fromLevel--
continue
}
// var hn Node

// We need nibbles in witness for extension keys.
// copy n.Key before it gets changed in ProofHash
var nCopy []byte
if short, ok := n.(*ShortNode); ok {
if !hasTerm(short.Key) { // only for extension keys
if !hasTerm(short.Key) { // extension keys
nCopy = make([]byte, len(short.Key))
copy(nCopy, short.Key)
extNibbles = append(extNibbles, nCopy)
} else {
extNibbles = append(extNibbles, []byte{})
}
} else {
extNibbles = append(extNibbles, []byte{})
}

// n, hn = hasher.ProofHash(n)
n, _ = hasher.ProofHash(n)
// if hash, ok := hn.(HashNode); ok || i == 0 {
// If the node's database encoding is a hash (or is the
// root node), it becomes a proof element.
enc, _ := rlp.EncodeToBytes(n)
/*
if !ok {
hash = hasher.HashData(enc)
}
*/
// proofDb.Put(hash, enc)
proofDb.Put([]byte{1, 1, 1}, enc)
// }
}

isNeighbourNodeHashed := false
Expand Down
11 changes: 8 additions & 3 deletions geth-utils/gethutil/mpt/trie/secure_trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type SecureTrie struct {
hashKeyBuf [common.HashLength]byte
secKeyCache map[string][]byte
secKeyCacheOwner *SecureTrie // Pointer to self, replace the key cache on mismatch
isStorageTrie bool
}

// NewSecure creates a trie with an existing root node from a backing database
Expand All @@ -53,15 +54,15 @@ type SecureTrie struct {
// Loaded nodes are kept around until their 'cache generation' expires.
// A new cache generation is created by each call to Commit.
// cachelimit sets the number of past cache generations to keep.
func NewSecure(root common.Hash, db *Database) (*SecureTrie, error) {
func NewSecure(root common.Hash, db *Database, isStorageTrie bool) (*SecureTrie, error) {
if db == nil {
panic("trie.NewSecure called without a database")
}
trie, err := New(root, db)
if err != nil {
return nil, err
}
return &SecureTrie{trie: *trie}, nil
return &SecureTrie{trie: *trie, isStorageTrie: isStorageTrie}, nil
}

// Get returns the value for key stored in the trie.
Expand Down Expand Up @@ -202,7 +203,8 @@ func (t *SecureTrie) NodeIterator(start []byte) NodeIterator {
// The caller must not hold onto the return value because it will become
// invalid on the next call to hashKey or secKey.
func (t *SecureTrie) hashKey(key []byte) []byte {
if !oracle.PreventHashingInSecureTrie {
preventHashing := (oracle.PreventHashingInSecureTrie && t.isStorageTrie) || (oracle.AccountPreventHashingInSecureTrie && !t.isStorageTrie)
if !preventHashing {
h := NewHasher(false)
h.sha.Reset()
h.sha.Write(key)
Expand All @@ -211,6 +213,9 @@ func (t *SecureTrie) hashKey(key []byte) []byte {
return t.hashKeyBuf[:]
} else {
// For generating special tests for MPT circuit.
if len(key) < 32 { // accounts
key = append(key, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}...)
}
return key
}
}
Expand Down
Loading
Loading