Commit 2034e9b2 authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-challenger: Include proof in challenge data (#9228)

* op-program: Support absorbing leaf with supplied commitment

* op-challenger: Include proofs with challenge data

* op-challenger: Use 0 bytes in hash when index not set
parent 7998bed9
...@@ -122,14 +122,8 @@ func (p *LargePreimageUploader) splitCalls(data *types.PreimageOracleData) (*mat ...@@ -122,14 +122,8 @@ func (p *LargePreimageUploader) splitCalls(data *types.PreimageOracleData) (*mat
} }
func (p *LargePreimageUploader) Squeeze(ctx context.Context, uuid *big.Int, stateMatrix *matrix.StateMatrix) error { func (p *LargePreimageUploader) Squeeze(ctx context.Context, uuid *big.Int, stateMatrix *matrix.StateMatrix) error {
prestate, prestateProof, err := stateMatrix.PrestateWithProof() prestate, prestateProof := stateMatrix.PrestateWithProof()
if err != nil { poststate, poststateProof := stateMatrix.PoststateWithProof()
return fmt.Errorf("failed to generate prestate proof: %w", err)
}
poststate, poststateProof, err := stateMatrix.PoststateWithProof()
if err != nil {
return fmt.Errorf("failed to generate poststate proof: %w", err)
}
challengePeriod, err := p.contract.ChallengePeriod(ctx) challengePeriod, err := p.contract.ChallengePeriod(ctx)
if err != nil { if err != nil {
return fmt.Errorf("failed to get challenge period: %w", err) return fmt.Errorf("failed to get challenge period: %w", err)
......
...@@ -37,38 +37,30 @@ var ( ...@@ -37,38 +37,30 @@ var (
// [ErrValid] is returned if the provided inputs are valid and no challenge can be created. // [ErrValid] is returned if the provided inputs are valid and no challenge can be created.
func Challenge(data io.Reader, commitments []common.Hash) (types.Challenge, error) { func Challenge(data io.Reader, commitments []common.Hash) (types.Challenge, error) {
s := NewStateMatrix() s := NewStateMatrix()
m := s.PackState() lastValidState := s.PackState()
var prestate types.Leaf var lastValidLeaf types.Leaf
var firstInvalidLeaf types.Leaf
for i := 0; ; i++ { for i := 0; ; i++ {
unpaddedLeaf, err := s.absorbNextLeafInput(data)
isEOF := errors.Is(err, io.EOF)
if err != nil && !isEOF {
return types.Challenge{}, fmt.Errorf("failed to verify inputs: %w", err)
}
validCommitment := s.StateCommitment()
if i >= len(commitments) { if i >= len(commitments) {
// There should have been more commitments. // There should have been more commitments.
// The contracts should prevent this so it can't be challenged, return an error // The contracts should prevent this so it can't be challenged, return an error
return types.Challenge{}, ErrIncorrectCommitmentCount return types.Challenge{}, ErrIncorrectCommitmentCount
} }
claimedCommitment := commitments[i] claimedCommitment := commitments[i]
_, err := s.absorbNextLeafInput(data, func() common.Hash { return claimedCommitment })
var paddedLeaf [types.BlockSize]byte isEOF := errors.Is(err, io.EOF)
copy(paddedLeaf[:], unpaddedLeaf) if err != nil && !isEOF {
// TODO(client-pod#480): Add actual keccak padding to ensure the merkle proofs are correct return types.Challenge{}, fmt.Errorf("failed to verify inputs: %w", err)
poststate := types.Leaf{
Input: paddedLeaf,
Index: big.NewInt(int64(i)),
StateCommitment: claimedCommitment,
} }
validCommitment := s.StateCommitment()
if firstInvalidLeaf == (types.Leaf{}) {
if validCommitment != claimedCommitment { if validCommitment != claimedCommitment {
// TODO(client-pod#480): Add merkle proofs for these (invalid) leaves lastValidLeaf = s.prestateLeaf
return types.Challenge{ firstInvalidLeaf = s.poststateLeaf
StateMatrix: m, } else {
Prestate: prestate, lastValidState = s.PackState()
Poststate: poststate, }
}, nil
} }
if isEOF { if isEOF {
if i < len(commitments)-1 { if i < len(commitments)-1 {
...@@ -78,8 +70,20 @@ func Challenge(data io.Reader, commitments []common.Hash) (types.Challenge, erro ...@@ -78,8 +70,20 @@ func Challenge(data io.Reader, commitments []common.Hash) (types.Challenge, erro
} }
break break
} }
prestate = poststate }
m = s.PackState() if firstInvalidLeaf != (types.Leaf{}) {
var prestateProof merkle.Proof
if lastValidLeaf != (types.Leaf{}) {
prestateProof = s.merkleTree.ProofAtIndex(lastValidLeaf.IndexUint64())
}
poststateProof := s.merkleTree.ProofAtIndex(firstInvalidLeaf.IndexUint64())
return types.Challenge{
StateMatrix: lastValidState,
Prestate: lastValidLeaf,
PrestateProof: prestateProof,
Poststate: firstInvalidLeaf,
PoststateProof: poststateProof,
}, nil
} }
return types.Challenge{}, ErrValid return types.Challenge{}, ErrValid
} }
...@@ -88,12 +92,6 @@ func Challenge(data io.Reader, commitments []common.Hash) (types.Challenge, erro ...@@ -88,12 +92,6 @@ func Challenge(data io.Reader, commitments []common.Hash) (types.Challenge, erro
func NewStateMatrix() *StateMatrix { func NewStateMatrix() *StateMatrix {
return &StateMatrix{ return &StateMatrix{
s: newLegacyKeccak256(), s: newLegacyKeccak256(),
prestateLeaf: types.Leaf{
Index: big.NewInt(0),
},
poststateLeaf: types.Leaf{
Index: big.NewInt(0),
},
merkleTree: merkle.NewBinaryMerkleTree(), merkleTree: merkle.NewBinaryMerkleTree(),
} }
} }
...@@ -117,10 +115,10 @@ func (d *StateMatrix) PackState() []byte { ...@@ -117,10 +115,10 @@ func (d *StateMatrix) PackState() []byte {
// newLeafWithPadding creates a new [Leaf] from inputs, padding the input to the [BlockSize]. // newLeafWithPadding creates a new [Leaf] from inputs, padding the input to the [BlockSize].
func newLeafWithPadding(input []byte, index *big.Int, commitment common.Hash) types.Leaf { func newLeafWithPadding(input []byte, index *big.Int, commitment common.Hash) types.Leaf {
// TODO(client-pod#480): Add actual keccak padding to ensure the merkle proofs are correct (for readData) // TODO(client-pod#480): Add actual keccak padding to ensure the merkle proofs are correct (for readData)
paddedInput := make([]byte, types.BlockSize) var paddedInput [types.BlockSize]byte
copy(paddedInput, input) copy(paddedInput[:], input)
return types.Leaf{ return types.Leaf{
Input: ([types.BlockSize]byte)(paddedInput), Input: paddedInput,
Index: index, Index: index,
StateCommitment: commitment, StateCommitment: commitment,
} }
...@@ -133,7 +131,7 @@ func (d *StateMatrix) AbsorbUpTo(in io.Reader, maxLen int) (types.InputData, err ...@@ -133,7 +131,7 @@ func (d *StateMatrix) AbsorbUpTo(in io.Reader, maxLen int) (types.InputData, err
input := make([]byte, 0, maxLen) input := make([]byte, 0, maxLen)
commitments := make([]common.Hash, 0, maxLen/types.BlockSize) commitments := make([]common.Hash, 0, maxLen/types.BlockSize)
for len(input)+types.BlockSize <= maxLen { for len(input)+types.BlockSize <= maxLen {
readData, err := d.absorbNextLeafInput(in) readData, err := d.absorbNextLeafInput(in, d.StateCommitment)
if errors.Is(err, io.EOF) { if errors.Is(err, io.EOF) {
input = append(input, readData...) input = append(input, readData...)
commitments = append(commitments, d.StateCommitment()) commitments = append(commitments, d.StateCommitment())
...@@ -157,26 +155,20 @@ func (d *StateMatrix) AbsorbUpTo(in io.Reader, maxLen int) (types.InputData, err ...@@ -157,26 +155,20 @@ func (d *StateMatrix) AbsorbUpTo(in io.Reader, maxLen int) (types.InputData, err
} }
// PrestateWithProof returns the prestate leaf with its merkle proof. // PrestateWithProof returns the prestate leaf with its merkle proof.
func (d *StateMatrix) PrestateWithProof() (types.Leaf, merkle.Proof, error) { func (d *StateMatrix) PrestateWithProof() (types.Leaf, merkle.Proof) {
proof, err := d.merkleTree.ProofAtIndex(d.prestateLeaf.Index.Uint64()) proof := d.merkleTree.ProofAtIndex(d.prestateLeaf.IndexUint64())
if err != nil { return d.prestateLeaf, proof
return types.Leaf{}, merkle.Proof{}, err
}
return d.prestateLeaf, proof, nil
} }
// PoststateWithProof returns the poststate leaf with its merkle proof. // PoststateWithProof returns the poststate leaf with its merkle proof.
func (d *StateMatrix) PoststateWithProof() (types.Leaf, merkle.Proof, error) { func (d *StateMatrix) PoststateWithProof() (types.Leaf, merkle.Proof) {
proof, err := d.merkleTree.ProofAtIndex(d.poststateLeaf.Index.Uint64()) proof := d.merkleTree.ProofAtIndex(d.poststateLeaf.IndexUint64())
if err != nil { return d.poststateLeaf, proof
return types.Leaf{}, merkle.Proof{}, err
}
return d.poststateLeaf, proof, nil
} }
// absorbNextLeafInput reads up to [BlockSize] bytes from in and absorbs them into the state matrix. // absorbNextLeafInput reads up to [BlockSize] bytes from in and absorbs them into the state matrix.
// If EOF is reached while reading, the state matrix is finalized and [io.EOF] is returned. // If EOF is reached while reading, the state matrix is finalized and [io.EOF] is returned.
func (d *StateMatrix) absorbNextLeafInput(in io.Reader) ([]byte, error) { func (d *StateMatrix) absorbNextLeafInput(in io.Reader, stateCommitment func() common.Hash) ([]byte, error) {
data := make([]byte, types.BlockSize) data := make([]byte, types.BlockSize)
read := 0 read := 0
final := false final := false
...@@ -198,12 +190,13 @@ func (d *StateMatrix) absorbNextLeafInput(in io.Reader) ([]byte, error) { ...@@ -198,12 +190,13 @@ func (d *StateMatrix) absorbNextLeafInput(in io.Reader) ([]byte, error) {
// additional block. We can then return EOF to indicate there are no further blocks. // additional block. We can then return EOF to indicate there are no further blocks.
final = final && len(input) < types.BlockSize final = final && len(input) < types.BlockSize
d.absorbLeafInput(input, final) d.absorbLeafInput(input, final)
if d.prestateLeaf.StateCommitment == (common.Hash{}) { commitment := stateCommitment()
d.prestateLeaf = newLeafWithPadding(input, d.prestateLeaf.Index, d.StateCommitment()) if d.poststateLeaf == (types.Leaf{}) {
d.poststateLeaf = newLeafWithPadding(input, d.prestateLeaf.Index, d.StateCommitment()) d.prestateLeaf = types.Leaf{}
d.poststateLeaf = newLeafWithPadding(input, big.NewInt(0), commitment)
} else { } else {
d.prestateLeaf = d.poststateLeaf d.prestateLeaf = d.poststateLeaf
d.poststateLeaf = newLeafWithPadding(input, new(big.Int).Add(d.prestateLeaf.Index, big.NewInt(1)), d.StateCommitment()) d.poststateLeaf = newLeafWithPadding(input, new(big.Int).Add(d.prestateLeaf.Index, big.NewInt(1)), commitment)
} }
d.merkleTree.AddLeaf(d.poststateLeaf.Hash()) d.merkleTree.AddLeaf(d.poststateLeaf.Hash())
if final { if final {
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"math/rand" "math/rand"
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/keccak/merkle"
"github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types"
"github.com/ethereum-optimism/optimism/op-service/testutils" "github.com/ethereum-optimism/optimism/op-service/testutils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -58,39 +59,47 @@ type testData struct { ...@@ -58,39 +59,47 @@ type testData struct {
PoststateLeaf []byte `json:"poststateLeaf"` PoststateLeaf []byte `json:"poststateLeaf"`
} }
func TestReferenceCommitmentsFromReader(t *testing.T) { func TestAbsorbNextLeaf_ReferenceCommitments(t *testing.T) {
var tests []testData var tests []testData
require.NoError(t, json.Unmarshal(refTests, &tests)) require.NoError(t, json.Unmarshal(refTests, &tests))
for i, test := range tests { for i, test := range tests {
test := test test := test
t.Run(fmt.Sprintf("Ref-%v", i), func(t *testing.T) { t.Run(fmt.Sprintf("Ref-%v-%v", i, len(test.Input)), func(t *testing.T) {
prevLeaf := types.Leaf{}
s := NewStateMatrix() s := NewStateMatrix()
commitments := []common.Hash{s.StateCommitment()} commitments := []common.Hash{s.StateCommitment()}
in := bytes.NewReader(test.Input) in := bytes.NewReader(test.Input)
var prestateLeaf []byte
var poststateLeaf []byte
for { for {
readData, err := s.absorbNextLeafInput(in) readData, err := s.absorbNextLeafInput(in, s.StateCommitment)
if errors.Is(err, io.EOF) { isEOF := errors.Is(err, io.EOF)
if prestateLeaf == nil { if !isEOF {
prestateLeaf = readData // Shouldn't get any error except EOF
require.NoError(t, err)
} }
poststateLeaf = readData prestate, _ := s.PrestateWithProof()
poststate, _ := s.PoststateWithProof()
require.Equal(t, prevLeaf, prestate, "Prestate should be the previous post state")
require.Equal(t, poststate.Input[:len(readData)], readData, "Post state should have returned input data")
prevLeaf = poststate
commitments = append(commitments, s.StateCommitment()) commitments = append(commitments, s.StateCommitment())
if isEOF {
break break
} }
// Shouldn't get any error except EOF
require.NoError(t, err)
commitments = append(commitments, s.StateCommitment())
prestateLeaf = readData
} }
actual := s.Hash() actual := s.Hash()
expected := crypto.Keccak256Hash(test.Input) expected := crypto.Keccak256Hash(test.Input)
require.Equal(t, expected, actual) require.Equal(t, expected, actual)
require.Equal(t, test.Commitments, commitments) require.Equal(t, test.Commitments, commitments)
require.Equal(t, test.PrestateLeaf, prestateLeaf)
require.Equal(t, test.PoststateLeaf, poststateLeaf) prestate, _ := s.PrestateWithProof()
var expectedPre [types.BlockSize]byte
copy(expectedPre[:], test.PrestateLeaf)
require.Equal(t, expectedPre, prestate.Input, "Final prestate")
poststate, _ := s.PoststateWithProof()
var expectedPost [types.BlockSize]byte
copy(expectedPost[:], test.PoststateLeaf)
require.Equal(t, expectedPost, poststate.Input, "Final poststate")
}) })
} }
} }
...@@ -179,7 +188,7 @@ func TestAbsorbUpTo_InvalidLengths(t *testing.T) { ...@@ -179,7 +188,7 @@ func TestAbsorbUpTo_InvalidLengths(t *testing.T) {
} }
} }
func TestMatrix_AbsorbNextLeaf(t *testing.T) { func TestMatrix_absorbNextLeaf(t *testing.T) {
fullLeaf := make([]byte, types.BlockSize) fullLeaf := make([]byte, types.BlockSize)
for i := 0; i < types.BlockSize; i++ { for i := 0; i < types.BlockSize; i++ {
fullLeaf[i] = byte(i) fullLeaf[i] = byte(i)
...@@ -222,7 +231,7 @@ func TestMatrix_AbsorbNextLeaf(t *testing.T) { ...@@ -222,7 +231,7 @@ func TestMatrix_AbsorbNextLeaf(t *testing.T) {
state := NewStateMatrix() state := NewStateMatrix()
in := bytes.NewReader(test.input) in := bytes.NewReader(test.input)
for i, leaf := range test.leafInputs { for i, leaf := range test.leafInputs {
buf, err := state.absorbNextLeafInput(in) buf, err := state.absorbNextLeafInput(in, state.StateCommitment)
if errors.Is(err, io.EOF) { if errors.Is(err, io.EOF) {
require.Equal(t, test.errs[i], err) require.Equal(t, test.errs[i], err)
break break
...@@ -272,15 +281,31 @@ func TestVerifyPreimage(t *testing.T) { ...@@ -272,15 +281,31 @@ func TestVerifyPreimage(t *testing.T) {
return valid.Commitments return valid.Commitments
} }
leafData := func(idx int) (out [types.BlockSize]byte) { leafData := func(idx int) (out [types.BlockSize]byte) {
copy(out[:], preimage[idx*types.BlockSize:(idx+1)*types.BlockSize]) end := min((idx+1)*types.BlockSize, len(preimage))
copy(out[:], preimage[idx*types.BlockSize:end])
return return
} }
// merkleTree creates the final merkle tree after including all leaves.
merkleTree := func(commitments []common.Hash) *merkle.BinaryMerkleTree {
m := merkle.NewBinaryMerkleTree()
for i, commitment := range commitments {
leaf := types.Leaf{
Input: leafData(i),
Index: big.NewInt(int64(i)),
StateCommitment: commitment,
}
m.AddLeaf(leaf.Hash())
}
return m
}
challengeLeaf := func(commitments []common.Hash, invalidIdx int) types.Challenge { challengeLeaf := func(commitments []common.Hash, invalidIdx int) types.Challenge {
invalidLeafStart := invalidIdx * types.BlockSize invalidLeafStart := invalidIdx * types.BlockSize
s := NewStateMatrix() s := NewStateMatrix()
_, err := s.AbsorbUpTo(bytes.NewReader(preimage), invalidLeafStart) _, err := s.AbsorbUpTo(bytes.NewReader(preimage), invalidLeafStart)
require.NoError(t, err) require.NoError(t, err)
fullMerkle := merkleTree(commitments)
prestateLeaf := leafData(invalidIdx - 1) prestateLeaf := leafData(invalidIdx - 1)
poststateLeaf := leafData(invalidIdx) poststateLeaf := leafData(invalidIdx)
return types.Challenge{ return types.Challenge{
...@@ -290,11 +315,14 @@ func TestVerifyPreimage(t *testing.T) { ...@@ -290,11 +315,14 @@ func TestVerifyPreimage(t *testing.T) {
Index: big.NewInt(int64(invalidIdx - 1)), Index: big.NewInt(int64(invalidIdx - 1)),
StateCommitment: commitments[invalidIdx-1], StateCommitment: commitments[invalidIdx-1],
}, },
PrestateProof: fullMerkle.ProofAtIndex(uint64(invalidIdx - 1)),
Poststate: types.Leaf{ Poststate: types.Leaf{
Input: poststateLeaf, Input: poststateLeaf,
Index: big.NewInt(int64(invalidIdx)), Index: big.NewInt(int64(invalidIdx)),
StateCommitment: commitments[invalidIdx], StateCommitment: commitments[invalidIdx],
}, },
PoststateProof: fullMerkle.ProofAtIndex(uint64(invalidIdx)),
} }
} }
...@@ -312,12 +340,13 @@ func TestVerifyPreimage(t *testing.T) { ...@@ -312,12 +340,13 @@ func TestVerifyPreimage(t *testing.T) {
commitments: validCommitments, commitments: validCommitments,
expectedErr: ErrValid, expectedErr: ErrValid,
}, },
{ func() testInputs {
incorrectFirstCommitment := validCommitments()
incorrectFirstCommitment[0] = common.Hash{0xaa}
return testInputs{
name: "IncorrectFirstLeaf", name: "IncorrectFirstLeaf",
commitments: func() []common.Hash { commitments: func() []common.Hash {
commitments := validCommitments() return incorrectFirstCommitment
commitments[0] = common.Hash{0xaa}
return commitments
}, },
expected: types.Challenge{ expected: types.Challenge{
StateMatrix: NewStateMatrix().PackState(), StateMatrix: NewStateMatrix().PackState(),
...@@ -327,8 +356,10 @@ func TestVerifyPreimage(t *testing.T) { ...@@ -327,8 +356,10 @@ func TestVerifyPreimage(t *testing.T) {
Index: big.NewInt(int64(0)), Index: big.NewInt(int64(0)),
StateCommitment: common.Hash{0xaa}, StateCommitment: common.Hash{0xaa},
}, },
PoststateProof: merkleTree(incorrectFirstCommitment).ProofAtIndex(0),
}, },
}, }
}(),
} }
for i := 1; i < len(preimage)/types.BlockSize; i++ { for i := 1; i < len(preimage)/types.BlockSize; i++ {
...@@ -348,7 +379,12 @@ func TestVerifyPreimage(t *testing.T) { ...@@ -348,7 +379,12 @@ func TestVerifyPreimage(t *testing.T) {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
challenge, err := Challenge(bytes.NewReader(preimage), test.commitments()) challenge, err := Challenge(bytes.NewReader(preimage), test.commitments())
require.ErrorIs(t, err, test.expectedErr) require.ErrorIs(t, err, test.expectedErr)
require.Equal(t, test.expected, challenge) require.Equal(t, test.expected.StateMatrix, challenge.StateMatrix, "Correct state matrix")
require.Equal(t, test.expected.Prestate, challenge.Prestate, "Correct prestate")
require.Equal(t, test.expected.PrestateProof, challenge.PrestateProof, "Correct prestate proof")
require.Equal(t, test.expected.Poststate, challenge.Poststate, "Correct poststate")
require.Equal(t, test.expected.PoststateProof, challenge.PoststateProof, "Correct poststate proof")
require.Equal(t, test.expected, challenge, "Challenge correct overall")
}) })
} }
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x87d8548924b20b95fe1ed923236c44d2f98b8dc7a3c8c378e4193cc2745b1e8d" "0x87d8548924b20b95fe1ed923236c44d2f98b8dc7a3c8c378e4193cc2745b1e8d"
], ],
"prestateLeaf": "kYbKyRm02RR58P+t8WPE/UNL4zmr4XIe3qfMfFwRZVWlpzgDSmAXGNhqCGJZivDoNDRM1zrLaPAk5Ol8dAyi3shQgLHaBur7TLczzwxS9b8rU7WKPhTMsK+zblk3ps19yKixxPMjzMA5L70JOy0ng7/ZoJJhMuHC7TD1SYL5LEA=", "prestateLeaf": "",
"poststateLeaf": "kYbKyRm02RR58P+t8WPE/UNL4zmr4XIe3qfMfFwRZVWlpzgDSmAXGNhqCGJZivDoNDRM1zrLaPAk5Ol8dAyi3shQgLHaBur7TLczzwxS9b8rU7WKPhTMsK+zblk3ps19yKixxPMjzMA5L70JOy0ng7/ZoJJhMuHC7TD1SYL5LEA=" "poststateLeaf": "kYbKyRm02RR58P+t8WPE/UNL4zmr4XIe3qfMfFwRZVWlpzgDSmAXGNhqCGJZivDoNDRM1zrLaPAk5Ol8dAyi3shQgLHaBur7TLczzwxS9b8rU7WKPhTMsK+zblk3ps19yKixxPMjzMA5L70JOy0ng7/ZoJJhMuHC7TD1SYL5LEA="
}, },
{ {
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0xafaa5d998cf20052dea34066e466691f3a59af8a6143b7ff5626f87cb76f820b" "0xafaa5d998cf20052dea34066e466691f3a59af8a6143b7ff5626f87cb76f820b"
], ],
"prestateLeaf": "QbjuDum/N3hGQLgqXL+MCiPEUrt4bF+xejAngdRK3D8IOKnZfk6TaiGMdsG8vg==", "prestateLeaf": "",
"poststateLeaf": "QbjuDum/N3hGQLgqXL+MCiPEUrt4bF+xejAngdRK3D8IOKnZfk6TaiGMdsG8vg==" "poststateLeaf": "QbjuDum/N3hGQLgqXL+MCiPEUrt4bF+xejAngdRK3D8IOKnZfk6TaiGMdsG8vg=="
}, },
{ {
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0xc59f075e03c34088cfe44693f1260a94c0ebb6075b07c00875d0c2c072a87708" "0xc59f075e03c34088cfe44693f1260a94c0ebb6075b07c00875d0c2c072a87708"
], ],
"prestateLeaf": "vKG+6yYjKSdPcwd7e0iBfiwk7dek86+aVEoSgpkf9IdxiukoQFjZsx4XiOHcwv4=", "prestateLeaf": "",
"poststateLeaf": "vKG+6yYjKSdPcwd7e0iBfiwk7dek86+aVEoSgpkf9IdxiukoQFjZsx4XiOHcwv4=" "poststateLeaf": "vKG+6yYjKSdPcwd7e0iBfiwk7dek86+aVEoSgpkf9IdxiukoQFjZsx4XiOHcwv4="
}, },
{ {
...@@ -266,7 +266,7 @@ ...@@ -266,7 +266,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0xd587c1123b4ff0fa464810067afb76c630d2f55e699e10c87c0a0ef9b8066fb7" "0xd587c1123b4ff0fa464810067afb76c630d2f55e699e10c87c0a0ef9b8066fb7"
], ],
"prestateLeaf": "aKNFw0pM0XmPQULBOYhXDEpG7xyGpTPpLKWdfAqcx/TsA8M5fxeCyWV01nQK", "prestateLeaf": "",
"poststateLeaf": "aKNFw0pM0XmPQULBOYhXDEpG7xyGpTPpLKWdfAqcx/TsA8M5fxeCyWV01nQK" "poststateLeaf": "aKNFw0pM0XmPQULBOYhXDEpG7xyGpTPpLKWdfAqcx/TsA8M5fxeCyWV01nQK"
}, },
{ {
...@@ -285,7 +285,7 @@ ...@@ -285,7 +285,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x1a1f489ba334d4068d05ea8347fd83a14a73082101f8d2daba09553485e73c60" "0x1a1f489ba334d4068d05ea8347fd83a14a73082101f8d2daba09553485e73c60"
], ],
"prestateLeaf": "7GzH5TVEhQ==", "prestateLeaf": "",
"poststateLeaf": "7GzH5TVEhQ==" "poststateLeaf": "7GzH5TVEhQ=="
}, },
{ {
...@@ -294,7 +294,7 @@ ...@@ -294,7 +294,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x1811020a0424b78b1697b9cfaf67ea339be0988c5bfa859725bfbb0aec7ed76a" "0x1811020a0424b78b1697b9cfaf67ea339be0988c5bfa859725bfbb0aec7ed76a"
], ],
"prestateLeaf": "x9xGIRFaMdQq0l4MEJbBDSzCSTZLsd/0UkOSiHtALhd75Gi/c7ObBdk=", "prestateLeaf": "",
"poststateLeaf": "x9xGIRFaMdQq0l4MEJbBDSzCSTZLsd/0UkOSiHtALhd75Gi/c7ObBdk=" "poststateLeaf": "x9xGIRFaMdQq0l4MEJbBDSzCSTZLsd/0UkOSiHtALhd75Gi/c7ObBdk="
}, },
{ {
...@@ -303,7 +303,7 @@ ...@@ -303,7 +303,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0xdf980f53d2c8527c8438791243c129bd2aadb23872502fa0e4447e1b0b2202c3" "0xdf980f53d2c8527c8438791243c129bd2aadb23872502fa0e4447e1b0b2202c3"
], ],
"prestateLeaf": "O3mF1GL0vHkl1aZEKundwta4m+07cngnlLAtOOlhZA2n9NVQHvffMRc7kgg1zs9nUWNPUcj+O994cRWgMC1k", "prestateLeaf": "",
"poststateLeaf": "O3mF1GL0vHkl1aZEKundwta4m+07cngnlLAtOOlhZA2n9NVQHvffMRc7kgg1zs9nUWNPUcj+O994cRWgMC1k" "poststateLeaf": "O3mF1GL0vHkl1aZEKundwta4m+07cngnlLAtOOlhZA2n9NVQHvffMRc7kgg1zs9nUWNPUcj+O994cRWgMC1k"
}, },
{ {
...@@ -322,7 +322,7 @@ ...@@ -322,7 +322,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x85baa18bcb8dac402216a7c99c6bb508bfc96caabdfc83c7bccc0898a0389910" "0x85baa18bcb8dac402216a7c99c6bb508bfc96caabdfc83c7bccc0898a0389910"
], ],
"prestateLeaf": "Gy9pBTkfOeD0fUr8zbC58w5zP6YqVJZGv52nGLRXSlBlWeJLI35GmP219qhBhPZipJID71G+Hmjea/IB/N4poRzxS+9Ky/7wQNWMOadc/d+VVADXPu71Cy9IV3w=", "prestateLeaf": "",
"poststateLeaf": "Gy9pBTkfOeD0fUr8zbC58w5zP6YqVJZGv52nGLRXSlBlWeJLI35GmP219qhBhPZipJID71G+Hmjea/IB/N4poRzxS+9Ky/7wQNWMOadc/d+VVADXPu71Cy9IV3w=" "poststateLeaf": "Gy9pBTkfOeD0fUr8zbC58w5zP6YqVJZGv52nGLRXSlBlWeJLI35GmP219qhBhPZipJID71G+Hmjea/IB/N4poRzxS+9Ky/7wQNWMOadc/d+VVADXPu71Cy9IV3w="
}, },
{ {
...@@ -341,7 +341,7 @@ ...@@ -341,7 +341,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0xf38cdf1a78988c925677b1078d433a759ca4500334818977f2a480532921d78d" "0xf38cdf1a78988c925677b1078d433a759ca4500334818977f2a480532921d78d"
], ],
"prestateLeaf": "/tWP3uV4e9CVYkPJL8Z4kw==", "prestateLeaf": "",
"poststateLeaf": "/tWP3uV4e9CVYkPJL8Z4kw==" "poststateLeaf": "/tWP3uV4e9CVYkPJL8Z4kw=="
}, },
{ {
...@@ -360,7 +360,7 @@ ...@@ -360,7 +360,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x38859b60e7bc24fc4fb617ce269ca5eb01359eaf45a40b0b50f9248cf0904a32" "0x38859b60e7bc24fc4fb617ce269ca5eb01359eaf45a40b0b50f9248cf0904a32"
], ],
"prestateLeaf": "evoB", "prestateLeaf": "",
"poststateLeaf": "evoB" "poststateLeaf": "evoB"
}, },
{ {
...@@ -459,7 +459,7 @@ ...@@ -459,7 +459,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x932653825685e7a4719f711e5de643e9325e3e584f4b1f4f173a1d8914f087ef" "0x932653825685e7a4719f711e5de643e9325e3e584f4b1f4f173a1d8914f087ef"
], ],
"prestateLeaf": "sKUc0bS3vxziYuLSVP+8vjktAy0msieRxuSg0iLcAUuY03cmnnGtdmwOKwfuF2sHLGMDos8IwPbULHApG/i49Y3JAF4iRBWmppjET9h2cKwXgF83mrzd7Zd1bh7f/nz70AGPgfwuRVCYPRruYO36Lbynwg==", "prestateLeaf": "",
"poststateLeaf": "sKUc0bS3vxziYuLSVP+8vjktAy0msieRxuSg0iLcAUuY03cmnnGtdmwOKwfuF2sHLGMDos8IwPbULHApG/i49Y3JAF4iRBWmppjET9h2cKwXgF83mrzd7Zd1bh7f/nz70AGPgfwuRVCYPRruYO36Lbynwg==" "poststateLeaf": "sKUc0bS3vxziYuLSVP+8vjktAy0msieRxuSg0iLcAUuY03cmnnGtdmwOKwfuF2sHLGMDos8IwPbULHApG/i49Y3JAF4iRBWmppjET9h2cKwXgF83mrzd7Zd1bh7f/nz70AGPgfwuRVCYPRruYO36Lbynwg=="
}, },
{ {
...@@ -468,7 +468,7 @@ ...@@ -468,7 +468,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x2a05292281cbe8bb141e10a2199e10229ea3b1c049f9c3837090109a6c2c2ecc" "0x2a05292281cbe8bb141e10a2199e10229ea3b1c049f9c3837090109a6c2c2ecc"
], ],
"prestateLeaf": "iCvCPAopIESMi+Hl25arOaBs3JhDP9dQJg==", "prestateLeaf": "",
"poststateLeaf": "iCvCPAopIESMi+Hl25arOaBs3JhDP9dQJg==" "poststateLeaf": "iCvCPAopIESMi+Hl25arOaBs3JhDP9dQJg=="
}, },
{ {
...@@ -489,7 +489,7 @@ ...@@ -489,7 +489,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0xf4fd54da2d9deebfb13c263519bc96a75981aec25cfb546c9de7705284ae6c07" "0xf4fd54da2d9deebfb13c263519bc96a75981aec25cfb546c9de7705284ae6c07"
], ],
"prestateLeaf": "NIvaQ23RKSRtOnN9vQ/eEvXlDlYOTTy9STSkj6bTYU9dIQEZy8rHsgD+UkPF8anrPL0ZUdMQ5S7mAa0VB4/vDfB8Kl9H5j3jISJWQEY8HaCuc9JsS1PyLxROveE=", "prestateLeaf": "",
"poststateLeaf": "NIvaQ23RKSRtOnN9vQ/eEvXlDlYOTTy9STSkj6bTYU9dIQEZy8rHsgD+UkPF8anrPL0ZUdMQ5S7mAa0VB4/vDfB8Kl9H5j3jISJWQEY8HaCuc9JsS1PyLxROveE=" "poststateLeaf": "NIvaQ23RKSRtOnN9vQ/eEvXlDlYOTTy9STSkj6bTYU9dIQEZy8rHsgD+UkPF8anrPL0ZUdMQ5S7mAa0VB4/vDfB8Kl9H5j3jISJWQEY8HaCuc9JsS1PyLxROveE="
}, },
{ {
...@@ -542,7 +542,7 @@ ...@@ -542,7 +542,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x759c2672c3bad10c418cbecf4d7562dba49569dfea68ffcb444d7660591e2d7d" "0x759c2672c3bad10c418cbecf4d7562dba49569dfea68ffcb444d7660591e2d7d"
], ],
"prestateLeaf": "YmDfFJIJu992WScmzsVyne6MajcLV+PAuHQjjeqJffVgEfJQF5F63v7SVo2qm3F70XGO6LGinr8bUrXd/PKZp75uTG3THIudOg==", "prestateLeaf": "",
"poststateLeaf": "YmDfFJIJu992WScmzsVyne6MajcLV+PAuHQjjeqJffVgEfJQF5F63v7SVo2qm3F70XGO6LGinr8bUrXd/PKZp75uTG3THIudOg==" "poststateLeaf": "YmDfFJIJu992WScmzsVyne6MajcLV+PAuHQjjeqJffVgEfJQF5F63v7SVo2qm3F70XGO6LGinr8bUrXd/PKZp75uTG3THIudOg=="
}, },
{ {
...@@ -653,7 +653,7 @@ ...@@ -653,7 +653,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0xe2a777a8bffe0bbba1ad4d89515f6eaa9440c7d843b5543ce53cf15cdd7dc4ef" "0xe2a777a8bffe0bbba1ad4d89515f6eaa9440c7d843b5543ce53cf15cdd7dc4ef"
], ],
"prestateLeaf": "iaA3KhRXBhnFjkR2szfpxFslTINxAiauR6ZS41N7Tyfnk5iczJHJmjmPvWLUVbsoFWwbBvGkVPPJSyYV8z6Ll+CzQJmR", "prestateLeaf": "",
"poststateLeaf": "iaA3KhRXBhnFjkR2szfpxFslTINxAiauR6ZS41N7Tyfnk5iczJHJmjmPvWLUVbsoFWwbBvGkVPPJSyYV8z6Ll+CzQJmR" "poststateLeaf": "iaA3KhRXBhnFjkR2szfpxFslTINxAiauR6ZS41N7Tyfnk5iczJHJmjmPvWLUVbsoFWwbBvGkVPPJSyYV8z6Ll+CzQJmR"
}, },
{ {
...@@ -901,7 +901,7 @@ ...@@ -901,7 +901,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x6b0b2b4094f608f73c61f68be51329aff2fb0a5179de2b9b9467bfe9c3cdbe83" "0x6b0b2b4094f608f73c61f68be51329aff2fb0a5179de2b9b9467bfe9c3cdbe83"
], ],
"prestateLeaf": "BC+MRlxbvGUWnKSyfDm/ivblXLU9B8lijzAPSyuyDdTkYBZ/FSK4+2SMFmtm8KTghrh5OEvpwDz+NYX+y9wcxWFGBxy4zmC5QAmAZO78bJ0wSMdodhKgjE7JcPsUPgMuMGpvAa3TOQ==", "prestateLeaf": "",
"poststateLeaf": "BC+MRlxbvGUWnKSyfDm/ivblXLU9B8lijzAPSyuyDdTkYBZ/FSK4+2SMFmtm8KTghrh5OEvpwDz+NYX+y9wcxWFGBxy4zmC5QAmAZO78bJ0wSMdodhKgjE7JcPsUPgMuMGpvAa3TOQ==" "poststateLeaf": "BC+MRlxbvGUWnKSyfDm/ivblXLU9B8lijzAPSyuyDdTkYBZ/FSK4+2SMFmtm8KTghrh5OEvpwDz+NYX+y9wcxWFGBxy4zmC5QAmAZO78bJ0wSMdodhKgjE7JcPsUPgMuMGpvAa3TOQ=="
}, },
{ {
...@@ -910,7 +910,7 @@ ...@@ -910,7 +910,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x202223f2c589349b4674f6a6e32bf2ade3d3134b59a5c7c663117ecc87fa1455" "0x202223f2c589349b4674f6a6e32bf2ade3d3134b59a5c7c663117ecc87fa1455"
], ],
"prestateLeaf": "3L2fS5vNMdKj6LqS47x4oHrNhIIxLe9WYJ8inef4jgT/WXKUwlXH3SH1x9WDtYYD2A==", "prestateLeaf": "",
"poststateLeaf": "3L2fS5vNMdKj6LqS47x4oHrNhIIxLe9WYJ8inef4jgT/WXKUwlXH3SH1x9WDtYYD2A==" "poststateLeaf": "3L2fS5vNMdKj6LqS47x4oHrNhIIxLe9WYJ8inef4jgT/WXKUwlXH3SH1x9WDtYYD2A=="
}, },
{ {
...@@ -919,7 +919,7 @@ ...@@ -919,7 +919,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x6c7492b6bf953a71885ecd61168a95fc2e6d73ee46df0bf5ef3a366a34c364d3" "0x6c7492b6bf953a71885ecd61168a95fc2e6d73ee46df0bf5ef3a366a34c364d3"
], ],
"prestateLeaf": "+1FoFm7ydb3xXIdbfSHG7FduytLO9fpgdX43FT+x7FtCbosJEV75Q81gxdLJ8JMMS3/Cxyk0dnEE7f/kI8tiaCdpoFMbXVSPETE+VhpYh3tqUsPx3XvxPp3UnsTT6QwXSWshkw==", "prestateLeaf": "",
"poststateLeaf": "+1FoFm7ydb3xXIdbfSHG7FduytLO9fpgdX43FT+x7FtCbosJEV75Q81gxdLJ8JMMS3/Cxyk0dnEE7f/kI8tiaCdpoFMbXVSPETE+VhpYh3tqUsPx3XvxPp3UnsTT6QwXSWshkw==" "poststateLeaf": "+1FoFm7ydb3xXIdbfSHG7FduytLO9fpgdX43FT+x7FtCbosJEV75Q81gxdLJ8JMMS3/Cxyk0dnEE7f/kI8tiaCdpoFMbXVSPETE+VhpYh3tqUsPx3XvxPp3UnsTT6QwXSWshkw=="
}, },
{ {
...@@ -984,7 +984,7 @@ ...@@ -984,7 +984,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0x5f19fac317da21422bb1f587b1dff8f3df060092fdbfdd227271e3bb3fc182fb" "0x5f19fac317da21422bb1f587b1dff8f3df060092fdbfdd227271e3bb3fc182fb"
], ],
"prestateLeaf": "5AOpWwV0q9zthtbxpvpnf/utrQl1riNtoHTJPRm2uWgO6XaJlJQNKMXa", "prestateLeaf": "",
"poststateLeaf": "5AOpWwV0q9zthtbxpvpnf/utrQl1riNtoHTJPRm2uWgO6XaJlJQNKMXa" "poststateLeaf": "5AOpWwV0q9zthtbxpvpnf/utrQl1riNtoHTJPRm2uWgO6XaJlJQNKMXa"
}, },
{ {
...@@ -1015,7 +1015,7 @@ ...@@ -1015,7 +1015,7 @@
"0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a",
"0xd517103b16c5e12cca833ae2cc160e3d11c59c20aa380cfa5284aa10bdf4709a" "0xd517103b16c5e12cca833ae2cc160e3d11c59c20aa380cfa5284aa10bdf4709a"
], ],
"prestateLeaf": "eCmovNYrO+YV73aWboXDY/ToIZIp6UfGwIarwJunhPk8EVjTQb3x5K8BPPMG5KRLbTh12+Pu31HC2xXyg7F+SmHbXmt+Uog9FXvnrI9emRAk", "prestateLeaf": "",
"poststateLeaf": "eCmovNYrO+YV73aWboXDY/ToIZIp6UfGwIarwJunhPk8EVjTQb3x5K8BPPMG5KRLbTh12+Pu31HC2xXyg7F+SmHbXmt+Uog9FXvnrI9emRAk" "poststateLeaf": "eCmovNYrO+YV73aWboXDY/ToIZIp6UfGwIarwJunhPk8EVjTQb3x5K8BPPMG5KRLbTh12+Pu31HC2xXyg7F+SmHbXmt+Uog9FXvnrI9emRAk"
}, },
{ {
......
package merkle package merkle
import ( import (
"errors"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
...@@ -17,8 +15,6 @@ type Proof [BinaryMerkleTreeDepth]common.Hash ...@@ -17,8 +15,6 @@ type Proof [BinaryMerkleTreeDepth]common.Hash
var ( var (
// MaxLeafCount is the maximum number of leaves in the merkle tree. // MaxLeafCount is the maximum number of leaves in the merkle tree.
MaxLeafCount = 1<<BinaryMerkleTreeDepth - 1 // 2^16 - 1 MaxLeafCount = 1<<BinaryMerkleTreeDepth - 1 // 2^16 - 1
// IndexOutOfBoundsError is returned when an index is out of bounds.
IndexOutOfBoundsError = errors.New("index out of bounds")
// zeroHashes is a list of empty hashes in the binary merkle tree, indexed by height. // zeroHashes is a list of empty hashes in the binary merkle tree, indexed by height.
zeroHashes [BinaryMerkleTreeDepth]common.Hash zeroHashes [BinaryMerkleTreeDepth]common.Hash
// rootHash is the known root hash of the empty binary merkle tree. // rootHash is the known root hash of the empty binary merkle tree.
...@@ -131,9 +127,9 @@ func (m *BinaryMerkleTree) AddLeaf(hash common.Hash) { ...@@ -131,9 +127,9 @@ func (m *BinaryMerkleTree) AddLeaf(hash common.Hash) {
} }
// ProofAtIndex returns a merkle proof at the given leaf node index. // ProofAtIndex returns a merkle proof at the given leaf node index.
func (m *BinaryMerkleTree) ProofAtIndex(index uint64) (proof Proof, err error) { func (m *BinaryMerkleTree) ProofAtIndex(index uint64) (proof Proof) {
if index >= uint64(MaxLeafCount) { if index >= uint64(MaxLeafCount) {
return proof, IndexOutOfBoundsError panic("proof index out of bounds")
} }
levelNode := m.walkDownToLeafCount(index + 1) levelNode := m.walkDownToLeafCount(index + 1)
...@@ -154,5 +150,5 @@ func (m *BinaryMerkleTree) ProofAtIndex(index uint64) (proof Proof, err error) { ...@@ -154,5 +150,5 @@ func (m *BinaryMerkleTree) ProofAtIndex(index uint64) (proof Proof, err error) {
levelNode = levelNode.Parent levelNode = levelNode.Parent
} }
return proof, nil return proof
} }
...@@ -67,8 +67,7 @@ func TestBinaryMerkleTree_ProofAtIndex(t *testing.T) { ...@@ -67,8 +67,7 @@ func TestBinaryMerkleTree_ProofAtIndex(t *testing.T) {
for i := 0; i < int(test.LeafCount); i++ { for i := 0; i < int(test.LeafCount); i++ {
tree.AddLeaf(leafHash(i)) tree.AddLeaf(leafHash(i))
} }
proof, err := tree.ProofAtIndex(test.Index) proof := tree.ProofAtIndex(test.Index)
require.NoError(t, err)
require.Equal(t, test.Proofs, proof) require.Equal(t, test.Proofs, proof)
}) })
} }
......
...@@ -23,12 +23,25 @@ type Leaf struct { ...@@ -23,12 +23,25 @@ type Leaf struct {
StateCommitment common.Hash StateCommitment common.Hash
} }
func (l Leaf) IndexUint64() uint64 {
if l.Index == nil {
return 0
}
return l.Index.Uint64()
}
// Hash returns the hash of the leaf data. That is the // Hash returns the hash of the leaf data. That is the
// bytewise concatenation of the input, index, and state commitment. // bytewise concatenation of the input, index, and state commitment.
func (l Leaf) Hash() common.Hash { func (l Leaf) Hash() common.Hash {
concatted := make([]byte, 0, 136+32+32) concatted := make([]byte, 0, 136+32+32)
concatted = append(concatted, l.Input[:]...) concatted = append(concatted, l.Input[:]...)
concatted = append(concatted, l.Index.Bytes()...) var indexBytes []byte
if l.Index != nil {
indexBytes = l.Index.Bytes()
} else {
indexBytes = big.NewInt(0).Bytes()
}
concatted = append(concatted, indexBytes...)
concatted = append(concatted, l.StateCommitment.Bytes()...) concatted = append(concatted, l.StateCommitment.Bytes()...)
return crypto.Keccak256Hash(concatted) return crypto.Keccak256Hash(concatted)
} }
......
...@@ -75,10 +75,7 @@ func DiffMerkle() { ...@@ -75,10 +75,7 @@ func DiffMerkle() {
} }
// Generate the proof for the given index. // Generate the proof for the given index.
proof, err := merkleTree.ProofAtIndex(uint64(index)) proof := merkleTree.ProofAtIndex(uint64(index))
if err != nil {
log.Fatal("Failed to generate proof: ", err)
}
// Generate the merkle root. // Generate the merkle root.
root := merkleTree.RootHash() root := merkleTree.RootHash()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment