-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[1/n] feat(deposits): merkle tree machinery to support deposit inclusion verification #2265
base: main
Are you sure you want to change the base?
Changes from 17 commits
dd54258
ea02520
3f84c30
4401503
c4ff5b6
fcbedc9
f9b225d
e400806
1af579b
7919783
dfe96cd
b3534bb
8dd4fab
6bf0482
672c6e6
fef7fd2
aa85e49
a312bc2
7336132
c7b6fd8
8c699f9
5bb9a9b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
calbera marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,7 +44,7 @@ fi | |
# Find all .go files in the project directory and its subdirectories, ignoring .pb.go and .pb_encoding.go files | ||
find "${ROOT_DIR}" -type f -name "*.go" ! -name "*.pb.go" ! -name "*.pb_encoding.go" | while read -r file; do | ||
echo "Processing $file..." | ||
golines --reformat-tags --shorten-comments --write-output --max-len=80 "$file" | ||
golines --reformat-tags --shorten-comments --write-output --max-len=140 "$file" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @fridrik01 I found the culprit. This was shortening lines whenever I ran |
||
done | ||
|
||
echo "✅ All files processed." |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,7 +53,7 @@ license-fix: | |
|
||
nilaway: | ||
@echo "--> Running nilaway" | ||
(go run go.uber.org/nilaway/cmd/nilaway -exclude-errors-in-files "geth-primitives/deposit/" -v ./...) || exit 1; | ||
(go run go.uber.org/nilaway/cmd/nilaway -exclude-pkgs "github.com/berachain/beacon-kit/storage/deposit/merkle" -exclude-errors-in-files "geth-primitives/deposit/" -v ./...) || exit 1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not useful for now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will revive in subsequent PR when deposit/merkle package is being used |
||
@printf "Nilaway check complete\n" | ||
|
||
################# | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Deposit Merkle Tree | ||
|
||
This package implements the [EIP-4881 spec](https://eips.ethereum.org/EIPS/eip-4881) for a minimal sparse Merkle tree. | ||
|
||
The format proposed by the EIP allows for the pruning of deposits that are no longer needed to participate fully in consensus. | ||
|
||
Thanks to [Prysm](https://github.com/prysmaticlabs/prysm/blob/develop/beacon-chain/cache/depositsnapshot/deposit_tree.go) and Mark Mackey ([@ethDreamer](https://github.com/ethDreamer)) for the reference implementation. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
// | ||
// Copyright (C) 2024, Berachain Foundation. All rights reserved. | ||
// Use of this software is governed by the Business Source License included | ||
// in the LICENSE file of this repository and at www.mariadb.com/bsl11. | ||
// | ||
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY | ||
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER | ||
// VERSIONS OF THE LICENSED WORK. | ||
// | ||
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF | ||
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF | ||
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). | ||
// | ||
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON | ||
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, | ||
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF | ||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND | ||
// TITLE. | ||
|
||
package merkle | ||
|
||
import "github.com/berachain/beacon-kit/errors" | ||
|
||
var ( | ||
// ErrFinalizedNodeCannotPushLeaf may occur when attempting to push a leaf | ||
// to a finalized node. | ||
// When a node is finalized, it cannot be modified or changed. | ||
ErrFinalizedNodeCannotPushLeaf = errors.New( | ||
"can't push a leaf to a finalized node", | ||
) | ||
|
||
// ErrLeafNodeCannotPushLeaf may occur when attempting to push a leaf to a | ||
// leaf node. | ||
ErrLeafNodeCannotPushLeaf = errors.New("can't push a leaf to a leaf node") | ||
|
||
// ErrZeroLevel occurs when the value of level is 0. | ||
ErrZeroLevel = errors.New("level should be greater than 0") | ||
|
||
// ErrZeroDepth occurs when the value of depth is 0. | ||
ErrZeroDepth = errors.New("depth should be greater than 0") | ||
) | ||
|
||
var ( | ||
// ErrInvalidSnapshotRoot occurs when the snapshot root does not match the | ||
// calculated root. | ||
ErrInvalidSnapshotRoot = errors.New("snapshot root is invalid") | ||
|
||
// ErrInvalidDepositCount occurs when the value for mix in length is 0. | ||
ErrInvalidDepositCount = errors.New( | ||
"deposit count should be greater than 0", | ||
) | ||
|
||
// ErrInvalidIndex occurs when the index is less than the number of | ||
// finalized deposits. | ||
ErrInvalidIndex = errors.New( | ||
"index should be greater than finalizedDeposits - 1", | ||
) | ||
|
||
// ErrTooManyDeposits occurs when the number of deposits exceeds the | ||
// capacity of the tree. | ||
ErrTooManyDeposits = errors.New( | ||
"number of deposits should not be greater than the capacity of the tree", | ||
) | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
// | ||
// Copyright (C) 2024, Berachain Foundation. All rights reserved. | ||
// Use of this software is governed by the Business Source License included | ||
// in the LICENSE file of this repository and at www.mariadb.com/bsl11. | ||
// | ||
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY | ||
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER | ||
// VERSIONS OF THE LICENSED WORK. | ||
// | ||
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF | ||
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF | ||
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). | ||
// | ||
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON | ||
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, | ||
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF | ||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND | ||
// TITLE. | ||
|
||
package merkle | ||
|
||
import ( | ||
"slices" | ||
|
||
"github.com/berachain/beacon-kit/primitives/math/pow" | ||
"github.com/berachain/beacon-kit/primitives/merkle" | ||
) | ||
|
||
// create builds a new merkle tree. | ||
func create( | ||
hasher merkle.Hasher[[32]byte], | ||
leaves [][32]byte, | ||
depth uint64, | ||
) TreeNode { | ||
length := uint64(len(leaves)) | ||
if length == 0 { | ||
return &ZeroNode{ | ||
depth: depth, | ||
hasher: hasher, | ||
} | ||
} | ||
|
||
if depth == 0 { | ||
return &LeafNode{hash: leaves[0]} | ||
} | ||
|
||
split := min(pow.TwoToThePowerOf(depth-1), length) | ||
left := create(hasher, leaves[0:split], depth-1) | ||
right := create(hasher, leaves[split:], depth-1) | ||
return &InnerNode{ | ||
left: left, | ||
right: right, | ||
hasher: hasher, | ||
} | ||
} | ||
|
||
// fromSnapshotParts creates a new Merkle tree from a list of finalized leaves, | ||
// number of deposits and specified depth. | ||
func fromSnapshotParts( | ||
hasher merkle.Hasher[[32]byte], | ||
finalized [][32]byte, | ||
deposits uint64, | ||
level uint64, | ||
) (TreeNode, error) { | ||
var err error | ||
|
||
if len(finalized) < 1 || deposits == 0 { | ||
return &ZeroNode{ | ||
depth: level, | ||
hasher: hasher, | ||
}, nil | ||
} | ||
if deposits == pow.TwoToThePowerOf(level) { | ||
return &FinalizedNode{ | ||
depositCount: deposits, | ||
hash: finalized[0], | ||
}, nil | ||
} | ||
if level == 0 { | ||
return nil, ErrZeroLevel | ||
} | ||
node := InnerNode{ | ||
hasher: hasher, | ||
} | ||
if leftSubtree := pow.TwoToThePowerOf(level - 1); deposits <= leftSubtree { | ||
node.left, err = fromSnapshotParts(hasher, finalized, deposits, level-1) | ||
if err != nil { | ||
return nil, err | ||
} | ||
node.right = &ZeroNode{ | ||
depth: level - 1, | ||
hasher: hasher, | ||
} | ||
} else { | ||
node.left = &FinalizedNode{ | ||
depositCount: leftSubtree, | ||
hash: finalized[0], | ||
} | ||
node.right, err = fromSnapshotParts(hasher, finalized[1:], deposits-leftSubtree, level-1) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
return &node, nil | ||
} | ||
|
||
// generateProof returns a merkle proof and root. | ||
func generateProof( | ||
tree TreeNode, | ||
index uint64, | ||
depth uint64, | ||
) ([32]byte, [][32]byte) { | ||
var proof [][32]byte | ||
node := tree | ||
for depth > 0 { | ||
ithBit := (index >> (depth - 1)) & 0x1 //nolint:mnd // spec. | ||
if ithBit == 1 { | ||
proof = append(proof, node.Left().GetRoot()) | ||
node = node.Right() | ||
} else { | ||
proof = append(proof, node.Right().GetRoot()) | ||
node = node.Left() | ||
} | ||
depth-- | ||
} | ||
|
||
slices.Reverse(proof) | ||
return node.GetRoot(), proof | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: never necessary to fetch logs for block height 0