github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/scripts/go-ffi/merkle.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "strconv" 8 9 "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/merkle" 10 11 "github.com/ethereum/go-ethereum/accounts/abi" 12 "github.com/ethereum/go-ethereum/common" 13 "github.com/ethereum/go-ethereum/common/hexutil" 14 "github.com/ethereum/go-ethereum/crypto" 15 ) 16 17 // VerifyMerkleProof verifies a merkle proof against the root hash and the leaf hash. 18 // Reference: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#is_valid_merkle_branch 19 func VerifyMerkleProof(root, leaf common.Hash, index uint64, proof [merkle.BinaryMerkleTreeDepth]common.Hash) bool { 20 value := leaf 21 for i := 0; i < merkle.BinaryMerkleTreeDepth; i++ { 22 if ((index >> i) & 1) == 1 { 23 value = crypto.Keccak256Hash(proof[i][:], value[:]) 24 } else { 25 value = crypto.Keccak256Hash(value[:], proof[i][:]) 26 } 27 } 28 return value == root 29 } 30 31 const ( 32 // GenProof generates a merkle proof for a given leaf index by reconstructing the merkle tree from the passed 33 // leaves. 34 genProof = "gen_proof" 35 ) 36 37 var ( 38 rootAndProof, _ = abi.NewType("tuple", "", []abi.ArgumentMarshaling{ 39 {Name: "root", Type: "bytes32"}, 40 {Name: "proof", Type: "bytes32[]"}, 41 }) 42 43 merkleEncoder = abi.Arguments{ 44 {Type: rootAndProof}, 45 } 46 ) 47 48 // DiffMerkle generates an abi-encoded `merkleTestCase` of a specified variant. 49 func DiffMerkle() { 50 variant := os.Args[2] 51 if len(variant) == 0 { 52 log.Fatal("Must pass a variant to the merkle diff tester!") 53 } 54 55 switch variant { 56 case genProof: 57 if len(os.Args) < 5 { 58 log.Fatal("Invalid arguments to `gen_proof` variant.") 59 } 60 61 rawLeaves, err := hexutil.Decode(os.Args[3]) 62 if err != nil { 63 log.Fatal("Failed to decode leaves: ", err) 64 } 65 index, err := strconv.ParseInt(os.Args[4], 10, 64) 66 if err != nil { 67 log.Fatal("Failed to parse leaf index: ", err) 68 } 69 merkleTree := merkle.NewBinaryMerkleTree() 70 71 // Append all leaves to the merkle tree. 72 for i := 0; i < len(rawLeaves)/32; i++ { 73 leaf := common.BytesToHash(rawLeaves[i<<5 : (i+1)<<5]) 74 merkleTree.AddLeaf(leaf) 75 } 76 77 // Generate the proof for the given index. 78 proof := merkleTree.ProofAtIndex(uint64(index)) 79 80 // Generate the merkle root. 81 root := merkleTree.RootHash() 82 83 // Return "abi.encode(root, proof)" 84 packed, err := merkleEncoder.Pack(struct { 85 Root common.Hash 86 Proof [merkle.BinaryMerkleTreeDepth]common.Hash 87 }{ 88 Root: root, 89 Proof: proof, 90 }) 91 if err != nil { 92 log.Fatal("Failed to ABI encode root and proof: ", err) 93 } 94 fmt.Print(hexutil.Encode(packed[32:])) 95 default: 96 log.Fatal("Invalid variant passed to merkle diff tester!") 97 } 98 }