Compare commits

...

9 Commits

Author SHA1 Message Date
james-prysm
90266bf2d9 Merge branch 'develop' into prysmctl-scripts 2023-01-30 10:03:53 -06:00
Nishant Das
e8c25effb0 Cache Fork Digest Computation (#11931) 2023-01-29 16:07:50 +00:00
Potuz
cc454bb42c Cycle the BLS changes pool when falling below a threshold (#11873)
* Cycle the BLS changes pool when falling below a threshold

* move cycle logic within pool

* set threshold at 2000

* fix conflict

* more fixes

---------

Co-authored-by: kasey <489222+kasey@users.noreply.github.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-28 14:42:03 +00:00
Sammy Rosso
9529c73ff1 EIP-4881: Spec implementation (#11720)
* Initial spec rewrite

* Finish adding merkle tree implementation

* Last bits

* Move reverse function

* Add comments

* Add deposit tree snapshot

* Add deposit tree

* Add comments + cleanup

* Fixes

* Add missing errors

* Small fixes

* Add unhandled error

* Cleanup

* Fix unsafe file.Close

* Add missing comments

* Small fixes

* Address some of deepSource' compaints

* Add depositCount check

* Add finalizedDeposit check

* Replace pointer magic with copy()

* Add test for slice reversal

* add back bytes method

* Add package level description

* Remove zerohash gen and add additional checks

* Add additional comments

* Small lint fixes

* Forgot an error

* Small fixes

* Move Uint64ToBytesLittleEndian32 + test

* Fix uint subtraction issue

* Move mixInLength below error handling

* Fix

* Fix deposit root

---------

Co-authored-by: rauljordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-27 17:35:25 +00:00
terencechain
eca129d8ff Better log for block that never became head (#11917)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-27 11:58:43 -05:00
james-prysm
ed9189db07 Merge branch 'develop' into prysmctl-scripts 2023-01-27 07:32:59 -06:00
terencechain
53a4939da4 Use correct attribute if there's a payload ID cache miss (#11918)
* Use correct attribute if there's a payload ID cache miss

* Test

* Default case unknown state version

Co-authored-by: Potuz <potuz@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-27 11:13:47 +00:00
Manu NALEPA
efc1e06c6b Validator client beacon api non functional fixes (#11915)
* Validator Client Beacon API: Use Go idiomatic error handling

* Validator Client Beacon API: Use `buildURL`

`buildURL` sort params by keys.

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2023-01-27 10:44:23 +00:00
James He
dc038f3ee2 updating prysm scripts for prysmctl download 2023-01-27 11:37:44 +01:00
26 changed files with 936 additions and 40 deletions

View File

@@ -28,6 +28,7 @@ import (
"github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1/attestation"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/time/slots"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
@@ -196,6 +197,22 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
if err != nil {
log.WithError(err).Warn("Could not update head")
}
if blockRoot != headRoot {
receivedWeight, err := s.ForkChoicer().Weight(blockRoot)
if err != nil {
log.WithField("root", fmt.Sprintf("%#x", blockRoot)).Warn("could not determine node weight")
}
headWeight, err := s.ForkChoicer().Weight(headRoot)
if err != nil {
log.WithField("root", fmt.Sprintf("%#x", headRoot)).Warn("could not determine node weight")
}
log.WithFields(logrus.Fields{
"receivedRoot": fmt.Sprintf("%#x", blockRoot),
"receivedWeight": receivedWeight,
"headRoot": fmt.Sprintf("%#x", headRoot),
"headWeight": headWeight,
}).Debug("Head block is not the received block")
}
newBlockHeadElapsedTime.Observe(float64(time.Since(start).Milliseconds()))
if err := s.notifyEngineIfChangedHead(ctx, headRoot); err != nil {

View File

@@ -2,7 +2,20 @@ load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["merkle_tree.go"],
srcs = [
"deposit_tree.go",
"deposit_tree_snapshot.go",
"merkle_tree.go",
"zerohashes.gen.go",
],
importpath = "github.com/prysmaticlabs/prysm/v3/beacon-chain/cache/depositsnapshot",
visibility = ["//visibility:public"],
deps = [
"//container/slice:go_default_library",
"//crypto/hash:go_default_library",
"//encoding/bytesutil:go_default_library",
"//math:go_default_library",
"//proto/eth/v1:go_default_library",
"@com_github_pkg_errors//:go_default_library",
],
)

View File

@@ -0,0 +1,157 @@
// Package depositsnapshot implements the EIP-4881 standard for 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.
// Full EIP-4881 specification can be found here: https://eips.ethereum.org/EIPS/eip-4881
package depositsnapshot
import (
"crypto/sha256"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v3/math"
eth "github.com/prysmaticlabs/prysm/v3/proto/eth/v1"
)
var (
// ErrEmptyExecutionBlock occurs when the execution block is nil.
ErrEmptyExecutionBlock = errors.New("empty execution block")
// ErrInvalidSnapshotRoot occurs when the snapshot root does not match the calculated root.
ErrInvalidSnapshotRoot = errors.New("snapshot root is invalid")
// ErrInvalidMixInLength occurs when the value for mix in length is 0.
ErrInvalidMixInLength = errors.New("mixInLength 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")
// ErrNoDeposits occurs when the number of deposits is 0.
ErrNoDeposits = errors.New("number of deposits should be greater than 0")
// ErrNoFinalizedDeposits occurs when the number of finalized deposits is 0.
ErrNoFinalizedDeposits = errors.New("number of finalized deposits should be greater than 0")
// 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")
)
// DepositTree is the Merkle tree representation of deposits.
type DepositTree struct {
tree MerkleTreeNode
mixInLength uint64 // number of deposits in the tree, reference implementation calls this mix_in_length.
finalizedExecutionBlock executionBlock
}
type executionBlock struct {
Hash [32]byte
Depth uint64
}
// New creates an empty deposit tree.
//
//nolint:unused
func New() *DepositTree {
var leaves [][32]byte
merkle := create(leaves, DepositContractDepth)
return &DepositTree{
tree: merkle,
mixInLength: 0,
finalizedExecutionBlock: executionBlock{},
}
}
// getSnapshot returns a deposit tree snapshot.
//
//nolint:unused
func (d *DepositTree) getSnapshot() (DepositTreeSnapshot, error) {
if d.finalizedExecutionBlock == (executionBlock{}) {
return DepositTreeSnapshot{}, ErrEmptyExecutionBlock
}
var finalized [][32]byte
depositCount, _ := d.tree.GetFinalized(finalized)
return fromTreeParts(finalized, depositCount, d.finalizedExecutionBlock)
}
// fromSnapshot returns a deposit tree from a deposit tree snapshot.
//
//nolint:unused
func fromSnapshot(snapshot DepositTreeSnapshot) (DepositTree, error) {
root, err := snapshot.CalculateRoot()
if err != nil {
return DepositTree{}, err
}
if snapshot.depositRoot != root {
return DepositTree{}, ErrInvalidSnapshotRoot
}
if snapshot.depositCount >= math.PowerOf2(uint64(DepositContractDepth)) {
return DepositTree{}, ErrTooManyDeposits
}
tree, err := fromSnapshotParts(snapshot.finalized, snapshot.depositCount, DepositContractDepth)
if err != nil {
return DepositTree{}, err
}
if snapshot.depositCount == 0 {
return DepositTree{}, ErrNoDeposits
}
return DepositTree{
tree: tree,
mixInLength: snapshot.depositCount,
finalizedExecutionBlock: snapshot.executionBlock,
}, nil
}
// finalize marks a deposit as finalized.
//
//nolint:unused
func (d *DepositTree) finalize(eth1data *eth.Eth1Data, executionBlockHeight uint64) error {
var blockHash [32]byte
copy(blockHash[:], eth1data.BlockHash)
d.finalizedExecutionBlock = executionBlock{
Hash: blockHash,
Depth: executionBlockHeight,
}
_, err := d.tree.Finalize(eth1data.DepositCount, DepositContractDepth)
if err != nil {
return err
}
return nil
}
// getProof returns the Deposit tree proof.
//
//nolint:unused
func (d *DepositTree) getProof(index uint64) ([32]byte, [][32]byte, error) {
if d.mixInLength <= 0 {
return [32]byte{}, nil, ErrInvalidMixInLength
}
finalizedDeposits, _ := d.tree.GetFinalized([][32]byte{})
if finalizedDeposits == 0 {
return [32]byte{}, nil, ErrNoFinalizedDeposits
}
if finalizedDeposits != 0 {
finalizedDeposits = finalizedDeposits - 1
}
if index <= finalizedDeposits {
return [32]byte{}, nil, ErrInvalidIndex
}
leaf, proof := generateProof(d.tree, index, DepositContractDepth)
var mixInLength [32]byte
copy(mixInLength[:], bytesutil.Uint64ToBytesLittleEndian32(d.mixInLength))
proof = append(proof, mixInLength)
return leaf, proof, nil
}
// getRoot returns the root of the deposit tree.
//
//nolint:unused
func (d *DepositTree) getRoot() [32]byte {
root := d.tree.GetRoot()
return sha256.Sum256(append(root[:], bytesutil.Uint64ToBytesLittleEndian32(d.mixInLength)...))
}
// pushLeaf adds a new leaf to the tree.
//
//nolint:unused
func (d *DepositTree) pushLeaf(leaf [32]byte) error {
var err error
d.tree, err = d.tree.PushLeaf(leaf, DepositContractDepth)
if err != nil {
return err
}
d.mixInLength++
return nil
}

View File

@@ -0,0 +1,62 @@
package depositsnapshot
import (
"crypto/sha256"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
)
var (
// ErrZeroIndex occurs when the value of index is 0.
ErrZeroIndex = errors.New("index should be greater than 0")
)
// DepositTreeSnapshot represents the data used to create a
// deposit tree given a snapshot.
//
//nolint:unused
type DepositTreeSnapshot struct {
finalized [][32]byte
depositRoot [32]byte
depositCount uint64
executionBlock executionBlock
}
// CalculateRoot returns the root of a deposit tree snapshot.
func (ds *DepositTreeSnapshot) CalculateRoot() ([32]byte, error) {
size := ds.depositCount
index := len(ds.finalized)
root := Zerohashes[0]
for i := 0; i < DepositContractDepth; i++ {
if (size & 1) == 1 {
if index == 0 {
return [32]byte{}, ErrZeroIndex
}
index--
root = sha256.Sum256(append(ds.finalized[index][:], root[:]...))
} else {
root = sha256.Sum256(append(root[:], Zerohashes[i][:]...))
}
size >>= 1
}
return sha256.Sum256(append(root[:], bytesutil.Uint64ToBytesLittleEndian(ds.depositCount)...)), nil
}
// fromTreeParts constructs the deposit tree from pre-existing data.
//
//nolint:unused
func fromTreeParts(finalised [][32]byte, depositCount uint64, executionBlock executionBlock) (DepositTreeSnapshot, error) {
snapshot := DepositTreeSnapshot{
finalized: finalised,
depositRoot: Zerohashes[0],
depositCount: depositCount,
executionBlock: executionBlock,
}
root, err := snapshot.CalculateRoot()
if err != nil {
return snapshot, ErrInvalidSnapshotRoot
}
snapshot.depositRoot = root
return snapshot, nil
}

View File

@@ -1,5 +1,28 @@
package depositsnapshot
import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/container/slice"
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
"github.com/prysmaticlabs/prysm/v3/math"
)
const (
// DepositContractDepth is the maximum tree depth as defined by EIP-4881.
DepositContractDepth = 32
)
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")
)
// MerkleTreeNode is the interface for a Merkle tree.
type MerkleTreeNode interface {
// GetRoot returns the root of the Merkle tree.
@@ -7,9 +30,295 @@ type MerkleTreeNode interface {
// IsFull returns whether there is space left for deposits.
IsFull() bool
// Finalize marks deposits of the Merkle tree as finalized.
Finalize(deposits uint, depth uint) MerkleTreeNode
// GetFinalized returns a list of hashes of all the finalized nodes and the number of deposits.
GetFinalized(result [][32]byte) ([][32]byte, uint)
Finalize(depositsToFinalize uint64, depth uint64) (MerkleTreeNode, error)
// GetFinalized returns the number of deposits and a list of hashes of all the finalized nodes.
GetFinalized(result [][32]byte) (uint64, [][32]byte)
// PushLeaf adds a new leaf node at the next available Zero node.
PushLeaf(leaf [32]byte, deposits uint, depth uint) MerkleTreeNode
PushLeaf(leaf [32]byte, depth uint64) (MerkleTreeNode, error)
// Right represents the right child of a node.
Right() MerkleTreeNode
// Left represents the left child of a node.
Left() MerkleTreeNode
}
// create builds a new merkle tree
func create(leaves [][32]byte, depth uint64) MerkleTreeNode {
length := uint64(len(leaves))
if length == 0 {
return &ZeroNode{depth: depth}
}
if depth == 0 {
return &LeafNode{hash: leaves[0]}
}
split := math.Min(math.PowerOf2(depth-1), length)
left := create(leaves[0:split], depth-1)
right := create(leaves[split:], depth-1)
return &InnerNode{left: left, right: right}
}
// fromSnapshotParts creates a new Merkle tree from a list of finalized leaves, number of deposits and specified depth.
//
//nolint:unused
func fromSnapshotParts(finalized [][32]byte, deposits uint64, level uint64) (_ MerkleTreeNode, err error) {
if len(finalized) < 1 || deposits == 0 {
return &ZeroNode{
depth: level,
}, nil
}
if deposits == math.PowerOf2(level) {
return &FinalizedNode{
depositCount: deposits,
hash: finalized[0],
}, nil
}
if level == 0 {
return &ZeroNode{}, ErrZeroLevel
}
node := InnerNode{}
if leftSubtree := math.PowerOf2(level - 1); deposits <= leftSubtree {
node.left, err = fromSnapshotParts(finalized, deposits, level-1)
if err != nil {
return &ZeroNode{}, err
}
node.right = &ZeroNode{depth: level - 1}
} else {
node.left = &FinalizedNode{
depositCount: leftSubtree,
hash: finalized[0],
}
node.right, err = fromSnapshotParts(finalized[1:], deposits-leftSubtree, level-1)
if err != nil {
return &ZeroNode{}, err
}
}
return &node, nil
}
// generateProof returns a merkle proof and root
//
//nolint:unused
func generateProof(tree MerkleTreeNode, index uint64, depth uint64) ([32]byte, [][32]byte) {
var proof [][32]byte
node := tree
for depth > 0 {
ithBit := (index >> (depth - 1)) & 0x1
if ithBit == 1 {
proof = append(proof, node.Left().GetRoot())
node = node.Right()
} else {
proof = append(proof, node.Right().GetRoot())
node = node.Left()
}
depth--
}
proof = slice.Reverse(proof)
return node.GetRoot(), proof
}
// FinalizedNode represents a finalized node and satisfies the MerkleTreeNode interface.
type FinalizedNode struct {
depositCount uint64
hash [32]byte
}
// GetRoot returns the root of the Merkle tree.
func (f *FinalizedNode) GetRoot() [32]byte {
return f.hash
}
// IsFull returns whether there is space left for deposits.
// A FinalizedNode will always return true as by definition it
// is full and deposits can't be added to it.
func (_ *FinalizedNode) IsFull() bool {
return true
}
// Finalize marks deposits of the Merkle tree as finalized.
func (f *FinalizedNode) Finalize(depositsToFinalize uint64, depth uint64) (MerkleTreeNode, error) {
return f, nil
}
// GetFinalized returns a list of hashes of all the finalized nodes and the number of deposits.
func (f *FinalizedNode) GetFinalized(result [][32]byte) (uint64, [][32]byte) {
return f.depositCount, append(result, f.hash)
}
// PushLeaf adds a new leaf node at the next available zero node.
func (_ *FinalizedNode) PushLeaf(_ [32]byte, _ uint64) (MerkleTreeNode, error) {
return nil, ErrFinalizedNodeCannotPushLeaf
}
// Right returns nil as a finalized node can't have any children.
func (_ *FinalizedNode) Right() MerkleTreeNode {
return nil
}
// Left returns nil as a finalized node can't have any children.
func (_ *FinalizedNode) Left() MerkleTreeNode {
return nil
}
// LeafNode represents a leaf node holding a deposit and satisfies the MerkleTreeNode interface.
type LeafNode struct {
hash [32]byte
}
// GetRoot returns the root of the Merkle tree.
func (l *LeafNode) GetRoot() [32]byte {
return l.hash
}
// IsFull returns whether there is space left for deposits.
// A LeafNode will always return true as it is the last node
// in the tree and therefore can't have any deposits added to it.
func (_ *LeafNode) IsFull() bool {
return true
}
// Finalize marks deposits of the Merkle tree as finalized.
func (l *LeafNode) Finalize(depositsToFinalize uint64, depth uint64) (MerkleTreeNode, error) {
return &FinalizedNode{1, l.hash}, nil
}
// GetFinalized returns a list of hashes of all the finalized nodes and the number of deposits.
func (_ *LeafNode) GetFinalized(result [][32]byte) (uint64, [][32]byte) {
return 0, result
}
// PushLeaf adds a new leaf node at the next available zero node.
func (_ *LeafNode) PushLeaf(_ [32]byte, _ uint64) (MerkleTreeNode, error) {
return nil, ErrLeafNodeCannotPushLeaf
}
// Right returns nil as a leaf node is the last node and can't have any children.
func (_ *LeafNode) Right() MerkleTreeNode {
return nil
}
// Left returns nil as a leaf node is the last node and can't have any children.
func (_ *LeafNode) Left() MerkleTreeNode {
return nil
}
// InnerNode represents an inner node with two children and satisfies the MerkleTreeNode interface.
type InnerNode struct {
left, right MerkleTreeNode
}
// GetRoot returns the root of the Merkle tree.
func (n *InnerNode) GetRoot() [32]byte {
left := n.left.GetRoot()
right := n.right.GetRoot()
return hash.Hash(append(left[:], right[:]...))
}
// IsFull returns whether there is space left for deposits.
func (n *InnerNode) IsFull() bool {
return n.right.IsFull()
}
// Finalize marks deposits of the Merkle tree as finalized.
func (n *InnerNode) Finalize(depositsToFinalize uint64, depth uint64) (_ MerkleTreeNode, err error) {
deposits := math.PowerOf2(depth)
if deposits <= depositsToFinalize {
return &FinalizedNode{deposits, n.GetRoot()}, nil
}
if depth == 0 {
return &ZeroNode{}, ErrZeroDepth
}
n.left, err = n.left.Finalize(depositsToFinalize, depth-1)
if err != nil {
return &ZeroNode{}, err
}
if depositsToFinalize > deposits/2 {
remaining := depositsToFinalize - deposits/2
n.right, err = n.right.Finalize(remaining, depth-1)
if err != nil {
return &ZeroNode{}, err
}
}
return n, nil
}
// GetFinalized returns a list of hashes of all the finalized nodes and the number of deposits.
func (n *InnerNode) GetFinalized(result [][32]byte) (uint64, [][32]byte) {
leftDeposits, result := n.left.GetFinalized(result)
rightDeposits, result := n.right.GetFinalized(result)
return leftDeposits + rightDeposits, result
}
// PushLeaf adds a new leaf node at the next available zero node.
func (n *InnerNode) PushLeaf(leaf [32]byte, depth uint64) (MerkleTreeNode, error) {
if !n.left.IsFull() {
left, err := n.left.PushLeaf(leaf, depth-1)
if err == nil {
n.left = left
} else {
return n, err
}
} else {
right, err := n.right.PushLeaf(leaf, depth-1)
if err == nil {
n.right = right
} else {
return n, err
}
}
return n, nil
}
// Right returns the child node on the right.
func (n *InnerNode) Right() MerkleTreeNode {
return n.right
}
// Left returns the child node on the left.
func (n *InnerNode) Left() MerkleTreeNode {
return n.left
}
// ZeroNode represents an empty node without a deposit and satisfies the MerkleTreeNode interface.
type ZeroNode struct {
depth uint64
}
// GetRoot returns the root of the Merkle tree.
func (z *ZeroNode) GetRoot() [32]byte {
if z.depth == DepositContractDepth {
return hash.Hash(append(Zerohashes[z.depth-1][:], Zerohashes[z.depth-1][:]...))
}
return Zerohashes[z.depth]
}
// IsFull returns wh ether there is space left for deposits.
// A ZeroNode will always return false as a ZeroNode is an empty node
// that gets replaced by a deposit.
func (_ *ZeroNode) IsFull() bool {
return false
}
// Finalize marks deposits of the Merkle tree as finalized.
func (_ *ZeroNode) Finalize(depositsToFinalize uint64, depth uint64) (MerkleTreeNode, error) {
return nil, nil
}
// GetFinalized returns a list of hashes of all the finalized nodes and the number of deposits.
func (_ *ZeroNode) GetFinalized(result [][32]byte) (uint64, [][32]byte) {
return 0, result
}
// PushLeaf adds a new leaf node at the next available zero node.
func (_ *ZeroNode) PushLeaf(leaf [32]byte, depth uint64) (MerkleTreeNode, error) {
return create([][32]byte{leaf}, depth), nil
}
// Right returns nil as a zero node can't have any children.
func (_ *ZeroNode) Right() MerkleTreeNode {
return nil
}
// Left returns nil as a zero node can't have any children.
func (_ *ZeroNode) Left() MerkleTreeNode {
return nil
}

View File

@@ -0,0 +1,69 @@
// Code generated by gen_zerohashes. DO NOT EDIT.
package depositsnapshot
var Zerohashes = [][32]byte{
// 0000000000000000000000000000000000000000000000000000000000000000
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b
{245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169, 39, 89, 251, 75},
// db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71
{219, 86, 17, 78, 0, 253, 212, 193, 248, 92, 137, 43, 243, 90, 201, 168, 146, 137, 170, 236, 177, 235, 208, 169, 108, 222, 96, 106, 116, 139, 93, 113},
// c78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c
{199, 128, 9, 253, 240, 127, 197, 106, 17, 241, 34, 55, 6, 88, 163, 83, 170, 165, 66, 237, 99, 228, 76, 75, 193, 95, 244, 205, 16, 90, 179, 60},
// 536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c
{83, 109, 152, 131, 127, 45, 209, 101, 165, 93, 94, 234, 233, 20, 133, 149, 68, 114, 213, 111, 36, 109, 242, 86, 191, 60, 174, 25, 53, 42, 18, 60},
// 9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30
{158, 253, 224, 82, 170, 21, 66, 159, 174, 5, 186, 212, 208, 177, 215, 198, 77, 166, 77, 3, 215, 161, 133, 74, 88, 140, 44, 184, 67, 12, 13, 48},
// d88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1
{216, 141, 223, 238, 212, 0, 168, 117, 85, 150, 178, 25, 66, 193, 73, 126, 17, 76, 48, 46, 97, 24, 41, 15, 145, 230, 119, 41, 118, 4, 31, 161},
// 87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c
{135, 235, 13, 219, 165, 126, 53, 246, 210, 134, 103, 56, 2, 164, 175, 89, 117, 226, 37, 6, 199, 207, 76, 100, 187, 107, 229, 238, 17, 82, 127, 44},
// 26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193
{38, 132, 100, 118, 253, 95, 197, 74, 93, 67, 56, 81, 103, 201, 81, 68, 242, 100, 63, 83, 60, 200, 91, 185, 209, 107, 120, 47, 141, 125, 177, 147},
// 506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1
{80, 109, 134, 88, 45, 37, 36, 5, 184, 64, 1, 135, 146, 202, 210, 191, 18, 89, 241, 239, 90, 165, 248, 135, 225, 60, 178, 240, 9, 79, 81, 225},
// ffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b
{255, 255, 10, 215, 230, 89, 119, 47, 149, 52, 193, 149, 200, 21, 239, 196, 1, 78, 241, 225, 218, 237, 68, 4, 192, 99, 133, 209, 17, 146, 233, 43},
// 6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220
{108, 240, 65, 39, 219, 5, 68, 28, 216, 51, 16, 122, 82, 190, 133, 40, 104, 137, 14, 67, 23, 230, 160, 42, 180, 118, 131, 170, 117, 150, 66, 32},
// b7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f
{183, 208, 95, 135, 95, 20, 0, 39, 239, 81, 24, 162, 36, 123, 187, 132, 206, 143, 47, 15, 17, 35, 98, 48, 133, 218, 247, 150, 12, 50, 159, 95},
// df6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e
{223, 106, 245, 245, 187, 219, 107, 233, 239, 138, 166, 24, 228, 191, 128, 115, 150, 8, 103, 23, 30, 41, 103, 111, 139, 40, 77, 234, 106, 8, 168, 94},
// b58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784
{181, 141, 144, 15, 94, 24, 46, 60, 80, 239, 116, 150, 158, 161, 108, 119, 38, 197, 73, 117, 124, 194, 53, 35, 195, 105, 88, 125, 167, 41, 55, 132},
// d49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb
{212, 154, 117, 2, 255, 207, 176, 52, 11, 29, 120, 133, 104, 133, 0, 202, 48, 129, 97, 167, 249, 107, 98, 223, 157, 8, 59, 113, 252, 200, 242, 187},
// 8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb
{143, 230, 177, 104, 146, 86, 192, 211, 133, 244, 47, 91, 190, 32, 39, 162, 44, 25, 150, 225, 16, 186, 151, 193, 113, 211, 229, 148, 141, 233, 43, 235},
// 8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab
{141, 13, 99, 195, 158, 186, 222, 133, 9, 224, 174, 60, 156, 56, 118, 251, 95, 161, 18, 190, 24, 249, 5, 236, 172, 254, 203, 146, 5, 118, 3, 171},
// 95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4
{149, 238, 200, 178, 229, 65, 202, 212, 233, 29, 227, 131, 133, 242, 224, 70, 97, 159, 84, 73, 108, 35, 130, 203, 108, 172, 213, 185, 140, 38, 245, 164},
// f893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f
{248, 147, 233, 8, 145, 119, 117, 182, 43, 255, 35, 41, 77, 187, 227, 161, 205, 142, 108, 193, 195, 91, 72, 1, 136, 123, 100, 106, 111, 129, 241, 127},
// cddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa
{205, 219, 167, 181, 146, 227, 19, 51, 147, 193, 97, 148, 250, 199, 67, 26, 191, 47, 84, 133, 237, 113, 29, 178, 130, 24, 60, 129, 158, 8, 235, 170},
// 8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c
{138, 141, 127, 227, 175, 140, 170, 8, 90, 118, 57, 168, 50, 0, 20, 87, 223, 185, 18, 138, 128, 97, 20, 42, 208, 51, 86, 41, 255, 35, 255, 156},
// feb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167
{254, 179, 195, 55, 215, 165, 26, 111, 191, 0, 185, 227, 76, 82, 225, 201, 25, 92, 150, 155, 212, 231, 160, 191, 213, 29, 92, 91, 237, 156, 17, 103},
// e71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7
{231, 31, 10, 168, 60, 195, 46, 223, 190, 250, 159, 77, 62, 1, 116, 202, 133, 24, 46, 236, 159, 58, 9, 246, 166, 192, 223, 99, 119, 165, 16, 215},
// 31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0
{49, 32, 111, 168, 10, 80, 187, 106, 190, 41, 8, 80, 88, 241, 98, 18, 33, 42, 96, 238, 200, 240, 73, 254, 203, 146, 216, 200, 224, 168, 75, 192},
// 21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544
{33, 53, 43, 254, 203, 237, 221, 233, 147, 131, 159, 97, 76, 61, 172, 10, 62, 227, 117, 67, 249, 180, 18, 177, 97, 153, 220, 21, 142, 35, 181, 68},
// 619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765
{97, 158, 49, 39, 36, 187, 109, 124, 49, 83, 237, 157, 231, 145, 215, 100, 163, 102, 179, 137, 175, 19, 197, 139, 248, 168, 217, 4, 129, 164, 103, 101},
// 7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4
{124, 221, 41, 134, 38, 130, 80, 98, 141, 12, 16, 227, 133, 197, 140, 97, 145, 230, 251, 224, 81, 145, 188, 192, 79, 19, 63, 44, 234, 114, 193, 196},
// 848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1
{132, 137, 48, 189, 123, 168, 202, 197, 70, 97, 7, 33, 19, 251, 39, 136, 105, 224, 123, 184, 88, 127, 145, 57, 41, 51, 55, 77, 1, 123, 203, 225},
// 8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636
{136, 105, 255, 44, 34, 178, 140, 193, 5, 16, 217, 133, 50, 146, 128, 51, 40, 190, 79, 176, 232, 4, 149, 232, 187, 141, 39, 31, 91, 136, 150, 54},
// b5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c
{181, 254, 40, 231, 159, 27, 133, 15, 134, 88, 36, 108, 233, 182, 161, 231, 180, 159, 192, 109, 183, 20, 62, 143, 224, 180, 242, 176, 197, 82, 58, 92},
// 985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7
{152, 94, 146, 159, 112, 175, 40, 208, 189, 209, 169, 10, 128, 143, 151, 127, 89, 124, 124, 119, 140, 72, 158, 152, 211, 189, 137, 16, 211, 26, 192, 247},
}

View File

@@ -17,6 +17,10 @@ const ForkVersionByteLength = 4
// DomainByteLength length of domain byte array.
const DomainByteLength = 4
// digestMap maps the fork version and genesis validator root to the
// resultant fork digest.
var digestMap = make(map[string][32]byte)
// ErrSigFailedToVerify returns when a signature of a block object(ie attestation, slashing, exit... etc)
// failed to verify.
var ErrSigFailedToVerify = errors.New("signature did not verify")
@@ -240,6 +244,9 @@ func domain(domainType [DomainByteLength]byte, forkDataRoot []byte) []byte {
// genesis_validators_root=genesis_validators_root,
// ))
func computeForkDataRoot(version, root []byte) ([32]byte, error) {
if val, ok := digestMap[string(version)+string(root)]; ok {
return val, nil
}
r, err := (&ethpb.ForkData{
CurrentVersion: version,
GenesisValidatorsRoot: root,
@@ -247,6 +254,10 @@ func computeForkDataRoot(version, root []byte) ([32]byte, error) {
if err != nil {
return [32]byte{}, err
}
// Cache result of digest computation
// as this is a hot path and doesn't need
// to be constantly computed.
digestMap[string(version)+string(root)] = r
return r, nil
}

View File

@@ -136,6 +136,25 @@ func TestFuzzverifySigningRoot_10000(_ *testing.T) {
}
}
func TestDigestMap(t *testing.T) {
testVersion := []byte{'A', 'B', 'C', 'D'}
testValRoot := [32]byte{'t', 'e', 's', 't', 'r', 'o', 'o', 't'}
digest, err := signing.ComputeForkDigest(testVersion, testValRoot[:])
assert.NoError(t, err)
cachedDigest, err := signing.ComputeForkDigest(testVersion, testValRoot[:])
assert.NoError(t, err)
assert.Equal(t, digest, cachedDigest)
testVersion[3] = 'E'
cachedDigest, err = signing.ComputeForkDigest(testVersion, testValRoot[:])
assert.NoError(t, err)
assert.NotEqual(t, digest, cachedDigest)
testValRoot[5] = 'z'
cachedDigest2, err := signing.ComputeForkDigest(testVersion, testValRoot[:])
assert.NoError(t, err)
assert.NotEqual(t, digest, cachedDigest2)
assert.NotEqual(t, cachedDigest, cachedDigest2)
}
func TestBlockSignatureBatch_NoSigVerification(t *testing.T) {
tests := []struct {
pubkey []byte

View File

@@ -14,6 +14,11 @@ import (
"github.com/sirupsen/logrus"
)
// We recycle the BLS changes pool to avoid the backing map growing without
// bound. The cycling operation is expensive because it copies all elements, so
// we only do it when the map is smaller than this upper bound.
const blsChangesPoolThreshold = 2000
// PoolManager maintains pending and seen BLS-to-execution-change objects.
// This pool is used by proposers to insert BLS-to-execution-change objects into new blocks.
type PoolManager interface {
@@ -39,6 +44,15 @@ func NewPool() *Pool {
}
}
// Copies the internal map and returns a new one.
func (p *Pool) cycleMap() {
newMap := make(map[primitives.ValidatorIndex]*doublylinkedlist.Node[*ethpb.SignedBLSToExecutionChange])
for k, v := range p.m {
newMap[k] = v
}
p.m = newMap
}
// PendingBLSToExecChanges returns all objects from the pool.
func (p *Pool) PendingBLSToExecChanges() ([]*ethpb.SignedBLSToExecutionChange, error) {
p.lock.RLock()
@@ -150,6 +164,9 @@ func (p *Pool) MarkIncluded(change *ethpb.SignedBLSToExecutionChange) {
delete(p.m, change.Message.ValidatorIndex)
p.pending.Remove(node)
if p.numPending() == blsChangesPoolThreshold {
p.cycleMap()
}
}
// ValidatorExists checks if the bls to execution change object exists
@@ -162,3 +179,8 @@ func (p *Pool) ValidatorExists(idx primitives.ValidatorIndex) bool {
return node != nil
}
// numPending returns the number of pending bls to execution changes in the pool
func (p *Pool) numPending() int {
return p.pending.Len()
}

View File

@@ -407,3 +407,29 @@ func TestValidatorExists(t *testing.T) {
assert.Equal(t, false, pool.ValidatorExists(30))
})
}
func TestPoolCycleMap(t *testing.T) {
pool := NewPool()
firstChange := &eth.SignedBLSToExecutionChange{
Message: &eth.BLSToExecutionChange{
ValidatorIndex: primitives.ValidatorIndex(0),
}}
pool.InsertBLSToExecChange(firstChange)
secondChange := &eth.SignedBLSToExecutionChange{
Message: &eth.BLSToExecutionChange{
ValidatorIndex: primitives.ValidatorIndex(10),
}}
pool.InsertBLSToExecChange(secondChange)
thirdChange := &eth.SignedBLSToExecutionChange{
Message: &eth.BLSToExecutionChange{
ValidatorIndex: primitives.ValidatorIndex(30),
}}
pool.InsertBLSToExecChange(thirdChange)
pool.cycleMap()
require.Equal(t, true, pool.ValidatorExists(0))
require.Equal(t, true, pool.ValidatorExists(10))
require.Equal(t, true, pool.ValidatorExists(30))
require.Equal(t, false, pool.ValidatorExists(20))
}

View File

@@ -141,19 +141,36 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot primitives.Slot,
SafeBlockHash: finalizedBlockHash,
FinalizedBlockHash: finalizedBlockHash,
}
p := &enginev1.PayloadAttributes{
Timestamp: uint64(t.Unix()),
PrevRandao: random,
SuggestedFeeRecipient: feeRecipient.Bytes(),
var attr payloadattribute.Attributer
switch st.Version() {
case version.Capella:
withdrawals, err := st.ExpectedWithdrawals()
if err != nil {
return nil, err
}
attr, err = payloadattribute.New(&enginev1.PayloadAttributesV2{
Timestamp: uint64(t.Unix()),
PrevRandao: random,
SuggestedFeeRecipient: feeRecipient.Bytes(),
Withdrawals: withdrawals,
})
if err != nil {
return nil, err
}
case version.Bellatrix:
attr, err = payloadattribute.New(&enginev1.PayloadAttributes{
Timestamp: uint64(t.Unix()),
PrevRandao: random,
SuggestedFeeRecipient: feeRecipient.Bytes(),
})
if err != nil {
return nil, err
}
default:
return nil, errors.New("unknown beacon state version")
}
// This will change in subsequent hardforks like Capella.
pa, err := payloadattribute.New(p)
if err != nil {
return nil, err
}
payloadID, _, err := vs.ExecutionEngineCaller.ForkchoiceUpdated(ctx, f, pa)
payloadID, _, err := vs.ExecutionEngineCaller.ForkchoiceUpdated(ctx, f, attr)
if err != nil {
return nil, errors.Wrap(err, "could not prepare payload")
}

View File

@@ -59,6 +59,18 @@ func TestServer_getExecutionPayload(t *testing.T) {
Root: b2r[:],
}))
capellaTransitionState, _ := util.DeterministicGenesisStateCapella(t, 1)
wrappedHeaderCapella, err := blocks.WrappedExecutionPayloadHeaderCapella(&pb.ExecutionPayloadHeaderCapella{BlockNumber: 1})
require.NoError(t, err)
require.NoError(t, capellaTransitionState.SetLatestExecutionPayloadHeader(wrappedHeaderCapella))
b2pbCapella := util.NewBeaconBlockCapella()
b2rCapella, err := b2pbCapella.Block.HashTreeRoot()
require.NoError(t, err)
util.SaveBlock(t, context.Background(), beaconDB, b2pbCapella)
require.NoError(t, capellaTransitionState.SetFinalizedCheckpoint(&ethpb.Checkpoint{
Root: b2rCapella[:],
}))
require.NoError(t, beaconDB.SaveFeeRecipientsByValidatorIDs(context.Background(), []primitives.ValidatorIndex{0}, []common.Address{{}}))
tests := []struct {
@@ -87,6 +99,12 @@ func TestServer_getExecutionPayload(t *testing.T) {
payloadID: &pb.PayloadIDBytes{0x1},
validatorIndx: 1,
},
{
name: "transition completed, capella, happy case (doesn't have fee recipient in Db)",
st: capellaTransitionState,
payloadID: &pb.PayloadIDBytes{0x1},
validatorIndx: 1,
},
{
name: "transition completed, happy case, (payload ID cached)",
st: transitionSt,

View File

@@ -24,6 +24,21 @@ type Node[T any] struct {
next *Node[T]
}
// Copy returns a copy of the origina list.
func (l *List[T]) Copy() *List[T] {
if l == nil {
return nil
}
list := &List[T]{}
if l.len == 0 {
return list
}
for n := l.First(); n != nil; n = n.next {
list.Append(n.Copy())
}
return list
}
// First gets the reference to the first node in the list.
func (l *List[T]) First() *Node[T] {
return l.first
@@ -111,3 +126,12 @@ func (n *Node[T]) Value() (T, error) {
}
return n.value, nil
}
// Copy copies the given node and returns a new one. It does not do a deep copy
// of T.
func (n *Node[T]) Copy() *Node[T] {
if n == nil {
return nil
}
return NewNode(n.value)
}

View File

@@ -123,3 +123,36 @@ func TestRemove(t *testing.T) {
require.Equal(t, 2, list.len)
})
}
func TestNodeCopy(t *testing.T) {
first := NewNode(1)
second := first.Copy()
v, err := second.Value()
require.NoError(t, err)
require.Equal(t, first.value, v)
}
func TestListCopy(t *testing.T) {
list := &List[int]{}
first := NewNode(1)
second := NewNode(2)
third := NewNode(3)
list.Append(first)
list.Append(second)
list.Append(third)
copied := list.Copy()
require.Equal(t, 3, copied.Len())
m := copied.First()
for n := list.First(); n != nil; n = n.next {
nv, err := n.Value()
require.NoError(t, err)
mv, err := m.Value()
require.NoError(t, err)
require.Equal(t, nv, mv)
require.NotEqual(t, n, m)
m, err = m.Next()
require.NoError(t, err)
}
}

View File

@@ -382,3 +382,12 @@ func Unique[T comparable](a []T) []T {
}
return result[:end]
}
// Reverse reverses any slice in place
// Taken from https://github.com/faiface/generics/blob/8cf65f0b43803410724d8c671cb4d328543ba07d/examples/sliceutils/sliceutils.go
func Reverse[E any](s []E) []E {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
return s
}

View File

@@ -599,3 +599,20 @@ func TestUnique(t *testing.T) {
require.DeepEqual(t, []uint64{1, 2}, result)
})
}
func TestReverse(t *testing.T) {
tests := []struct {
value [][32]byte
want [][32]byte
}{
{[][32]byte{}, [][32]byte{}},
{[][32]byte{{'A'}, {'B'}, {'C'}, {'D'}},
[][32]byte{{'D'}, {'C'}, {'B'}, {'A'}}},
{[][32]byte{{1}, {2}, {3}, {4}},
[][32]byte{{4}, {3}, {2}, {1}}},
}
for _, tt := range tests {
b := slice.Reverse(tt.value)
require.DeepEqual(t, tt.want, b)
}
}

View File

@@ -115,6 +115,14 @@ func Uint64ToBytesLittleEndian(i uint64) []byte {
return buf
}
// Uint64ToBytesLittleEndian32 conversion of a uint64 to a fix
// sized 32 byte array in little endian order. Returns 32 byte array.
func Uint64ToBytesLittleEndian32(i uint64) []byte {
buf := make([]byte, 32)
binary.LittleEndian.PutUint64(buf, i)
return buf
}
// Uint64ToBytesBigEndian conversion.
func Uint64ToBytesBigEndian(i uint64) []byte {
buf := make([]byte, 8)

View File

@@ -300,3 +300,26 @@ func TestUint64ToBytesLittleEndian(t *testing.T) {
})
}
}
func TestUint64ToBytesLittleEndian32(t *testing.T) {
tests := []struct {
value uint64
want [32]byte
}{
{
value: 0x01000000,
want: [32]byte{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
},
{
value: 0x00000001,
want: [32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
},
}
for _, tt := range tests {
t.Run(fmt.Sprintf("0x%08x", tt.value), func(t *testing.T) {
if got := bytesutil.Uint64ToBytesLittleEndian32(tt.value); !bytes.Equal(got, tt.want[:]) {
t.Errorf("Uint64ToBytesLittleEndian32() = got %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -5,7 +5,7 @@ SetLocal EnableDelayedExpansion & REM All variables are set local to this run &
set PRYLABS_SIGNING_KEY=0AE0051D647BA3C1A917AF4072E33E4DF1A5036E
REM Complain if invalid arguments were provided.
for %%a in (beacon-chain validator client-stats) do (
for %%a in (beacon-chain validator prysmctl client-stats) do (
if %1 equ %%a (
goto validprocess
)
@@ -13,7 +13,7 @@ for %%a in (beacon-chain validator client-stats) do (
echo ERROR: PROCESS missing or invalid
echo Usage: ./prysm.bat PROCESS FLAGS.
echo.
echo PROCESS can be beacon-chain, validator, or client-stats.
echo PROCESS can be beacon-chain, validator, prysmctl or client-stats.
echo FLAGS are the flags or arguments passed to the PROCESS.
echo.
echo Use this script to download the latest Prysm release binaries.
@@ -70,6 +70,7 @@ IF defined USE_PRYSM_MODERN (
)
set VALIDATOR_REAL=%wrapper_dir%\validator-%prysm_version%-%system%-%arch%
set CLIENT_STATS_REAL=%wrapper_dir%\client-stats-%prysm_version%-%system%-%arch%
set PRYSMCTL_REAL=%wrapper_dir%\prysmctl-%prysm_version%-%system%-%arch%
if "%~1"=="beacon-chain" (
if exist "%BEACON_CHAIN_REAL%" (
@@ -130,6 +131,22 @@ if "%~1"=="client-stats" (
)
)
if "%~1"=="prysmctl" (
if exist %PRYSMCTL_REAL% (
echo prysmctl is up to date.
) else (
echo Downloading prysmctl %prysm_version% to %PRYSMCTL_REAL% %reason%
for /f "delims=" %%i in ('curl --silent -o nul -w "%%{http_code}" https://prysmaticlabs.com/releases/prysmctl-%prysm_version%-%system%-%arch% ') do set "http=%%i" && echo %%i
if "!http!"=="404" (
echo No prysmctl found for %prysm_version%
exit /b 1
)
curl -L https://prysmaticlabs.com/releases/prysmctl-%prysm_version%-%system%-%arch% -o %PRYSMCTL_REAL%
curl --silent -L https://prysmaticlabs.com/releases/prysmctl-%prysm_version%-%system%-%arch%.sha256 -o %wrapper_dir%\prysmctl-%prysm_version%-%system%-%arch%.sha256
curl --silent -L https://prysmaticlabs.com/releases/prysmctl-%prysm_version%-%system%-%arch%.sig -o %wrapper_dir%\prysmctl-%prysm_version%-%system%-%arch%.sig
)
)
if "%~1"=="slasher" (
echo The slasher binary is no longer available. Please use the --slasher flag with your beacon node. See: https://docs.prylabs.network/docs/prysm-usage/slasher/
exit /b 1
@@ -138,6 +155,7 @@ if "%~1"=="slasher" (
if "%~1"=="beacon-chain" ( set process=%BEACON_CHAIN_REAL%)
if "%~1"=="validator" ( set process=%VALIDATOR_REAL%)
if "%~1"=="client-stats" ( set process=%CLIENT_STATS_REAL%)
if "%~1"=="prysmctl" ( set process=%PRYSMCTL_REAL%)
REM GPG not natively available on Windows, external module required
echo WARN GPG verification is not natively available on Windows.

View File

@@ -2,11 +2,11 @@ $folderDist = "dist";
$ProgressPreference = 'SilentlyContinue' # Disable Invoke-WebRequest progress bar, makes it silent and faster.
# Complain if invalid arguments were provided.
if ("beacon-chain", "validator", "client-stats" -notcontains $args[0]) {
if ("beacon-chain", "validator","prysmctl", "client-stats" -notcontains $args[0]) {
Write-Host @"
Usage: ./prysm.sh1 PROCESS FLAGS.
PROCESS can be beacon-chain, validator, or client-stats.
PROCESS can be beacon-chain, validator, prysmctl, or client-stats.
FLAGS are the flags or arguments passed to the PROCESS.
Use this script to download the latest Prysm release binaries.

View File

@@ -69,7 +69,7 @@ function get_realpath() {
if [ "$#" -lt 1 ]; then
color "31" "Usage: ./prysm.sh PROCESS FLAGS."
color "31" " ./prysm.sh PROCESS --download-only."
color "31" "PROCESS can be beacon-chain, validator, or client-stats."
color "31" "PROCESS can be beacon-chain, validator, prysmctl, or client-stats."
exit 1
fi
@@ -178,6 +178,7 @@ else
fi
VALIDATOR_REAL="${wrapper_dir}/validator-${prysm_version}-${system}-${arch}"
CLIENT_STATS_REAL="${wrapper_dir}/client-stats-${prysm_version}-${system}-${arch}"
PRYSMCTL_REAL="${wrapper_dir}/prysmctl-${prysm_version}-${system}-${arch}"
if [[ $1 == beacon-chain ]]; then
if [[ ! -x $BEACON_CHAIN_REAL ]]; then
@@ -236,6 +237,24 @@ if [[ $1 == client-stats ]]; then
fi
fi
if [[ $1 == prysmctl ]]; then
if [[ ! -x $PRYSMCTL_REAL ]]; then
color "34" "Downloading prysmctl@${prysm_version} to ${CLIENT_STATS_REAL} (${reason})"
file=prysmctl-${prysm_version}-${system}-${arch}
res=$(curl -w '%{http_code}\n' -f -L "https://prysmaticlabs.com/releases/${file}" -o "$PRYSMCTL_REAL" | ( grep 404 || true ) )
if [[ $res == 404 ]];then
echo "No prysmctl found for ${prysm_version},(${file}) exit"
exit 1
fi
curl --silent -L "https://prysmaticlabs.com/releases/${file}.sha256" -o "${wrapper_dir}/${file}.sha256"
curl --silent -L "https://prysmaticlabs.com/releases/${file}.sig" -o "${wrapper_dir}/${file}.sig"
chmod +x "$PRYSMCTL_REAL"
else
color "37" "prysmctl is up to date."
fi
fi
if [[ $1 == slasher ]]; then
color "41" "The slasher binary is no longer available. Please use the --slasher flag with your beacon node. See: https://docs.prylabs.network/docs/prysm-usage/slasher/"
exit 1
@@ -254,11 +273,15 @@ client-stats)
readonly process=$CLIENT_STATS_REAL
;;
prysmctl)
readonly process=$PRYSMCTL_REAL
;;
*)
color "31" "Process '$1' is not found!"
color "31" "Usage: ./prysm.sh PROCESS FLAGS."
color "31" " ./prysm.sh PROCESS --download-only."
color "31" "PROCESS can be beacon-chain, validator, or client-stats."
color "31" "PROCESS can be beacon-chain, validator, prysmctl, or client-stats."
exit 1
;;
esac

View File

@@ -23,8 +23,8 @@ func (c beaconApiValidatorClient) getAttestationData(
query := buildURL("/eth/v1/validator/attestation_data", params)
produceAttestationDataResponseJson := rpcmiddleware.ProduceAttestationDataResponseJson{}
_, err := c.jsonRestHandler.GetRestJsonResponse(ctx, query, &produceAttestationDataResponseJson)
if err != nil {
if _, err := c.jsonRestHandler.GetRestJsonResponse(ctx, query, &produceAttestationDataResponseJson); err != nil {
return nil, errors.Wrap(err, "failed to get json response")
}

View File

@@ -53,12 +53,11 @@ func (c *beaconApiValidatorClient) getFork(ctx context.Context) (*apimiddleware.
stateForkResponseJson := &apimiddleware.StateForkResponseJson{}
_, err := c.jsonRestHandler.GetRestJsonResponse(
if _, err := c.jsonRestHandler.GetRestJsonResponse(
ctx,
endpoint,
stateForkResponseJson,
)
if err != nil {
); err != nil {
return nil, errors.Wrapf(err, "failed to get json response from `%s` REST endpoint", endpoint)
}
@@ -70,12 +69,11 @@ func (c *beaconApiValidatorClient) getHeaders(ctx context.Context) (*apimiddlewa
blockHeadersResponseJson := &apimiddleware.BlockHeadersResponseJson{}
_, err := c.jsonRestHandler.GetRestJsonResponse(
if _, err := c.jsonRestHandler.GetRestJsonResponse(
ctx,
endpoint,
blockHeadersResponseJson,
)
if err != nil {
); err != nil {
return nil, errors.Wrapf(err, "failed to get json response from `%s` REST endpoint", endpoint)
}
@@ -105,12 +103,11 @@ func (c *beaconApiValidatorClient) getSyncing(ctx context.Context) (*apimiddlewa
syncingResponseJson := &apimiddleware.SyncingResponseJson{}
_, err := c.jsonRestHandler.GetRestJsonResponse(
if _, err := c.jsonRestHandler.GetRestJsonResponse(
ctx,
endpoint,
syncingResponseJson,
)
if err != nil {
); err != nil {
return nil, errors.Wrapf(err, "failed to get json response from `%s` REST endpoint", endpoint)
}

View File

@@ -53,8 +53,7 @@ func (c beaconApiStateValidatorsProvider) GetStateValidators(
stateValidatorsJson := &rpcmiddleware.StateValidatorsResponseJson{}
_, err := c.jsonRestHandler.GetRestJsonResponse(ctx, url, stateValidatorsJson)
if err != nil {
if _, err := c.jsonRestHandler.GetRestJsonResponse(ctx, url, stateValidatorsJson); err != nil {
return &rpcmiddleware.StateValidatorsResponseJson{}, errors.Wrap(err, "failed to get json response")
}

View File

@@ -4,7 +4,7 @@ import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"github.com/ethereum/go-ethereum/common/hexutil"
@@ -77,8 +77,13 @@ func (c *beaconApiValidatorClient) getSyncCommitteeContribution(
}
blockRoot := hexutil.Encode(blockRootResponse.Root)
url := fmt.Sprintf("/eth/v1/validator/sync_committee_contribution?slot=%d&subcommittee_index=%d&beacon_block_root=%s",
uint64(req.Slot), req.SubnetId, blockRoot)
params := url.Values{}
params.Add("slot", strconv.FormatUint(uint64(req.Slot), 10))
params.Add("subcommittee_index", strconv.FormatUint(req.SubnetId, 10))
params.Add("beacon_block_root", blockRoot)
url := buildURL("/eth/v1/validator/sync_committee_contribution", params)
var resp apimiddleware.ProduceSyncCommitteeContributionResponseJson
if _, err := c.jsonRestHandler.GetRestJsonResponse(ctx, url, &resp); err != nil {

View File

@@ -228,8 +228,8 @@ func TestGetSyncCommitteeContribution(t *testing.T) {
jsonRestHandler.EXPECT().GetRestJsonResponse(
ctx,
fmt.Sprintf("/eth/v1/validator/sync_committee_contribution?slot=%d&subcommittee_index=%d&beacon_block_root=%s",
uint64(request.Slot), request.SubnetId, blockRoot),
fmt.Sprintf("/eth/v1/validator/sync_committee_contribution?beacon_block_root=%s&slot=%d&subcommittee_index=%d",
blockRoot, uint64(request.Slot), request.SubnetId),
&apimiddleware.ProduceSyncCommitteeContributionResponseJson{},
).SetArg(
2,