github.com/ethereum-optimism/optimism@v1.7.2/op-node/withdrawals/proof.go (about) 1 package withdrawals 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 8 "github.com/ethereum/go-ethereum/common" 9 "github.com/ethereum/go-ethereum/core/types" 10 "github.com/ethereum/go-ethereum/crypto" 11 "github.com/ethereum/go-ethereum/ethclient/gethclient" 12 "github.com/ethereum/go-ethereum/rlp" 13 "github.com/ethereum/go-ethereum/trie" 14 ) 15 16 type proofDB struct { 17 m map[string][]byte 18 } 19 20 func (p *proofDB) Has(key []byte) (bool, error) { 21 _, ok := p.m[string(key)] 22 return ok, nil 23 } 24 25 func (p *proofDB) Get(key []byte) ([]byte, error) { 26 v, ok := p.m[string(key)] 27 if !ok { 28 return nil, errors.New("not found") 29 } 30 return v, nil 31 } 32 33 func GenerateProofDB(proof []string) *proofDB { 34 p := proofDB{m: make(map[string][]byte)} 35 for _, s := range proof { 36 value := common.FromHex(s) 37 key := crypto.Keccak256(value) 38 p.m[string(key)] = value 39 } 40 return &p 41 } 42 43 func VerifyAccountProof(root common.Hash, address common.Address, account types.StateAccount, proof []string) error { 44 expected, err := rlp.EncodeToBytes(&account) 45 if err != nil { 46 return fmt.Errorf("failed to encode rlp: %w", err) 47 } 48 secureKey := crypto.Keccak256(address[:]) 49 db := GenerateProofDB(proof) 50 value, err := trie.VerifyProof(root, secureKey, db) 51 if err != nil { 52 return fmt.Errorf("failed to verify proof: %w", err) 53 } 54 55 if bytes.Equal(value, expected) { 56 return nil 57 } else { 58 return errors.New("proved value is not the same as the expected value") 59 } 60 } 61 62 func VerifyStorageProof(root common.Hash, proof gethclient.StorageResult) error { 63 secureKey := crypto.Keccak256(common.FromHex(proof.Key)) 64 db := GenerateProofDB(proof.Proof) 65 value, err := trie.VerifyProof(root, secureKey, db) 66 if err != nil { 67 return fmt.Errorf("failed to verify proof: %w", err) 68 } 69 70 expected := proof.Value.Bytes() 71 if bytes.Equal(value, expected) { 72 return nil 73 } else { 74 return errors.New("proved value is not the same as the expected value") 75 } 76 } 77 78 func VerifyProof(stateRoot common.Hash, proof *gethclient.AccountResult) error { 79 err := VerifyAccountProof( 80 stateRoot, 81 proof.Address, 82 types.StateAccount{ 83 Nonce: proof.Nonce, 84 Balance: proof.Balance, 85 Root: proof.StorageHash, 86 CodeHash: proof.CodeHash[:], 87 }, 88 proof.AccountProof, 89 ) 90 if err != nil { 91 return fmt.Errorf("failed to validate account: %w", err) 92 } 93 for i, storageProof := range proof.StorageProof { 94 err = VerifyStorageProof(proof.StorageHash, storageProof) 95 if err != nil { 96 return fmt.Errorf("failed to validate storage proof %d: %w", i, err) 97 } 98 } 99 return nil 100 }