mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 21:08:10 -05:00
Validator client builder support (#10749)
* Startinb builder service and interface * Get header from builder * Add get builder block * Single validator registration * Add mev-builder http cli flag * Add method to verify registration signature * Add builder registration * Add submit validator registration * suporting yaml * fix yaml unmarshaling * rolling back some changes from unmarshal from file * adding yaml support * adding register validator support * added new validator requests into client/validator * fixing gofmt * updating flags and including gas limit, unit tests are still broken * fixing bazel * more name changes and fixing unit tests * fixing unit tests and renaming functions * fixing unit tests and renaming to match changes * adding new test for yaml * fixing bazel linter * reverting change on validator service proto * adding clarifying logs * renaming function name to be more descriptive * renaming variable * rolling back some files that will be added from the builder-1 branch * reverting more * more reverting * need placeholder * need placeholder * fixing unit test * fixing unit test * fixing unit test * fixing unit test * fixing more unit tests * fixing more unit tests * rolling back mockgen * fixing bazel * rolling back changes * removing duplicate function * fixing client mock * removing unused type * fixing missing brace * fixing bad field name * fixing bazel * updating naming * fixing bazel * fixing unit test * fixing bazel linting * unhandled err * fixing gofmt * simplifying name based on feedback * using corrected function * moving default fee recipient and gaslimit to beaconconfig * missing a few constant changes * fixing bazel * fixing more missed default renames * fixing more constants in tests * fixing bazel * adding update proposer setting per epoch * refactoring to reduce complexity * adding unit test for proposer settings * Update validator/client/validator.go Co-authored-by: terencechain <terence@prysmaticlabs.com> * trying out renaming based on feedback * adjusting based on review comments * making tests more appropriate * fixing bazel * updating flag description based on review feedback * addressing review feedback * switching to pushing at start of epoch for more time * adding new unit test and properly throwing error * switching keys in error to count * fixing log variable * resolving conflict * resolving more conflicts * adjusting error message Co-authored-by: terence tsao <terence@prysmaticlabs.com> Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
This commit is contained in:
@@ -29,7 +29,7 @@ go_test(
|
||||
data = glob(["testdata/**"]),
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
@@ -98,7 +98,7 @@ func TestClient_RegisterValidator(t *testing.T) {
|
||||
}
|
||||
reg := ð.SignedValidatorRegistrationV1{
|
||||
Message: ð.ValidatorRegistrationV1{
|
||||
FeeRecipient: ezDecode(t, fieldparams.EthBurnAddressHex),
|
||||
FeeRecipient: ezDecode(t, params.BeaconConfig().EthBurnAddressHex),
|
||||
GasLimit: 23,
|
||||
Timestamp: 42,
|
||||
Pubkey: ezDecode(t, "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a"),
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
@@ -270,10 +269,10 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
||||
recipient, err := s.cfg.BeaconDB.FeeRecipientByValidatorID(ctx, proposerID)
|
||||
switch {
|
||||
case errors.Is(err, kv.ErrNotFoundFeeRecipient):
|
||||
if feeRecipient.String() == fieldparams.EthBurnAddressHex {
|
||||
if feeRecipient.String() == params.BeaconConfig().EthBurnAddressHex {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"validatorIndex": proposerID,
|
||||
"burnAddress": fieldparams.EthBurnAddressHex,
|
||||
"burnAddress": params.BeaconConfig().EthBurnAddressHex,
|
||||
}).Warn("Fee recipient is currently using the burn address, " +
|
||||
"you will not be rewarded transaction fees on this setting. " +
|
||||
"Please set a different eth address as the fee recipient. " +
|
||||
|
||||
@@ -806,7 +806,7 @@ func Test_GetPayloadAttribute(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, hasPayload)
|
||||
require.Equal(t, suggestedVid, vId)
|
||||
require.Equal(t, fieldparams.EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient).String())
|
||||
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient).String())
|
||||
require.LogsContain(t, hook, "Fee recipient is currently using the burn address")
|
||||
|
||||
// Cache hit, advance state, has fee recipient
|
||||
|
||||
@@ -127,10 +127,10 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
case errors.As(err, kv.ErrNotFoundFeeRecipient):
|
||||
// If fee recipient is not found in DB and not set from beacon node CLI,
|
||||
// use the burn address.
|
||||
if feeRecipient.String() == fieldparams.EthBurnAddressHex {
|
||||
if feeRecipient.String() == params.BeaconConfig().EthBurnAddressHex {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"validatorIndex": vIdx,
|
||||
"burnAddress": fieldparams.EthBurnAddressHex,
|
||||
"burnAddress": params.BeaconConfig().EthBurnAddressHex,
|
||||
}).Warn("Fee recipient is currently using the burn address, " +
|
||||
"you will not be rewarded transaction fees on this setting. " +
|
||||
"Please set a different eth address as the fee recipient. " +
|
||||
|
||||
@@ -18,7 +18,6 @@ go_library(
|
||||
],
|
||||
deps = [
|
||||
"//cmd:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
|
||||
@@ -5,7 +5,6 @@ package flags
|
||||
import (
|
||||
"strings"
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -215,7 +214,7 @@ var (
|
||||
SuggestedFeeRecipient = &cli.StringFlag{
|
||||
Name: "suggested-fee-recipient",
|
||||
Usage: "Post bellatrix, this address will receive the transaction fees produced by any blocks from this node. Default to junk whilst bellatrix is in development state. Validator client can override this value through the preparebeaconproposer api.",
|
||||
Value: fieldparams.EthBurnAddressHex,
|
||||
Value: params.BeaconConfig().EthBurnAddressHex,
|
||||
}
|
||||
// TerminalTotalDifficultyOverride specifies the total difficulty to manual overrides the `TERMINAL_TOTAL_DIFFICULTY` parameter.
|
||||
TerminalTotalDifficultyOverride = &cli.StringFlag{
|
||||
|
||||
@@ -13,7 +13,7 @@ go_library(
|
||||
"//validator:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//io/file:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
field_params "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/io/file"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -327,21 +327,36 @@ var (
|
||||
// FeeRecipientConfigFileFlag defines the path or URL to a file with proposer config.
|
||||
FeeRecipientConfigFileFlag = &cli.StringFlag{
|
||||
Name: "fee-recipient-config-file",
|
||||
Usage: "Set path to a JSON file containing validator mappings to ETH addresses for receiving transaction fees when proposing blocks (i.e. --fee-recipient-config-file=/path/to/proposer.json). File format found in docs",
|
||||
Usage: "DEPRECATED, please use proposer-settings-file",
|
||||
Value: "",
|
||||
}
|
||||
// FeeRecipientConfigURLFlag defines the path or URL to a file with proposer config.
|
||||
FeeRecipientConfigURLFlag = &cli.StringFlag{
|
||||
Name: "fee-recipient-config-url",
|
||||
Usage: "Set URL to a REST endpoint containing validator mappings to ETH addresses for receiving transaction fees when proposing blocks (i.e. --fee-recipient-config-url=https://example.com/api/getConfig). File format found in docs",
|
||||
Usage: "DEPRECATED, please use proposer-settings-url",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
// ProposerSettingsFlag defines the path or URL to a file with proposer config.
|
||||
ProposerSettingsFlag = &cli.StringFlag{
|
||||
Name: "proposer-settings-file",
|
||||
Usage: "Set path to a YAML or JSON file containing validator settings used when proposing blocks such as (fee recipient and gas limit) (i.e. --proposer-settings-file=/path/to/proposer.json). File format found in docs",
|
||||
Value: "",
|
||||
}
|
||||
// ProposerSettingsURLFlag defines the path or URL to a file with proposer config.
|
||||
ProposerSettingsURLFlag = &cli.StringFlag{
|
||||
Name: "proposer-settings-url",
|
||||
Usage: "Set URL to a REST endpoint containing validator settings used when proposing blocks such as (fee recipient) (i.e. --proposer-settings-url=https://example.com/api/getConfig). File format found in docs",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
// SuggestedFeeRecipientFlag defines the address of the fee recipient.
|
||||
SuggestedFeeRecipientFlag = &cli.StringFlag{
|
||||
Name: "suggested-fee-recipient",
|
||||
Usage: "Sets ALL validators' mapping to a suggested an eth address to receive gas fees when proposing a block. This is a fall back setting and will be overridden by other flags that update the proposer settings. ",
|
||||
Value: field_params.EthBurnAddressHex,
|
||||
Name: "suggested-fee-recipient",
|
||||
Usage: "Sets ALL validators' mapping to a suggested an eth address to receive gas fees when proposing a block." +
|
||||
" note that this is only a suggestion when integrating with a Builder API, which may choose to specify a different fee recipient as payment for the blocks it builds." +
|
||||
" For additional setting overrides use the --" + ProposerSettingsFlag.Name + " or --" + ProposerSettingsURLFlag.Name + " Flags. ",
|
||||
Value: params.BeaconConfig().EthBurnAddressHex,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -78,6 +78,8 @@ var appFlags = []cli.Flag{
|
||||
flags.FeeRecipientConfigFileFlag,
|
||||
flags.FeeRecipientConfigURLFlag,
|
||||
flags.SuggestedFeeRecipientFlag,
|
||||
flags.ProposerSettingsURLFlag,
|
||||
flags.ProposerSettingsFlag,
|
||||
////////////////////
|
||||
cmd.DisableMonitoringFlag,
|
||||
cmd.MonitoringHostFlag,
|
||||
|
||||
@@ -111,6 +111,8 @@ var appHelpFlagGroups = []flagGroup{
|
||||
flags.Web3SignerPublicValidatorKeysFlag,
|
||||
flags.FeeRecipientConfigFileFlag,
|
||||
flags.FeeRecipientConfigURLFlag,
|
||||
flags.ProposerSettingsFlag,
|
||||
flags.ProposerSettingsURLFlag,
|
||||
flags.SuggestedFeeRecipientFlag,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -5,23 +5,22 @@ package field_params
|
||||
|
||||
const (
|
||||
Preset = "mainnet"
|
||||
BlockRootsLength = 8192 // SLOTS_PER_HISTORICAL_ROOT
|
||||
StateRootsLength = 8192 // SLOTS_PER_HISTORICAL_ROOT
|
||||
RandaoMixesLength = 65536 // EPOCHS_PER_HISTORICAL_VECTOR
|
||||
HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT
|
||||
ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT
|
||||
Eth1DataVotesLength = 2048 // SLOTS_PER_ETH1_VOTING_PERIOD
|
||||
PreviousEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
CurrentEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
SlashingsLength = 8192 // EPOCHS_PER_SLASHINGS_VECTOR
|
||||
SyncCommitteeLength = 512 // SYNC_COMMITTEE_SIZE
|
||||
RootLength = 32 // RootLength defines the byte length of a Merkle root.
|
||||
BLSSignatureLength = 96 // BLSSignatureLength defines the byte length of a BLSSignature.
|
||||
BLSPubkeyLength = 48 // BLSPubkeyLength defines the byte length of a BLSSignature.
|
||||
MaxTxsPerPayloadLength = 1048576 // MaxTxsPerPayloadLength defines the maximum number of transactions that can be included in a payload.
|
||||
MaxBytesPerTxLength = 1073741824 // MaxBytesPerTxLength defines the maximum number of bytes that can be included in a transaction.
|
||||
FeeRecipientLength = 20 // FeeRecipientLength defines the byte length of a fee recipient.
|
||||
LogsBloomLength = 256 // LogsBloomLength defines the byte length of a logs bloom.
|
||||
VersionLength = 4 // VersionLength defines the byte length of a fork version number.
|
||||
EthBurnAddressHex = "0x0000000000000000000000000000000000000000" // EthBurnAddressHex defines the hex encoded address of the eth1.0 burn contract.
|
||||
BlockRootsLength = 8192 // SLOTS_PER_HISTORICAL_ROOT
|
||||
StateRootsLength = 8192 // SLOTS_PER_HISTORICAL_ROOT
|
||||
RandaoMixesLength = 65536 // EPOCHS_PER_HISTORICAL_VECTOR
|
||||
HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT
|
||||
ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT
|
||||
Eth1DataVotesLength = 2048 // SLOTS_PER_ETH1_VOTING_PERIOD
|
||||
PreviousEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
CurrentEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
SlashingsLength = 8192 // EPOCHS_PER_SLASHINGS_VECTOR
|
||||
SyncCommitteeLength = 512 // SYNC_COMMITTEE_SIZE
|
||||
RootLength = 32 // RootLength defines the byte length of a Merkle root.
|
||||
BLSSignatureLength = 96 // BLSSignatureLength defines the byte length of a BLSSignature.
|
||||
BLSPubkeyLength = 48 // BLSPubkeyLength defines the byte length of a BLSSignature.
|
||||
MaxTxsPerPayloadLength = 1048576 // MaxTxsPerPayloadLength defines the maximum number of transactions that can be included in a payload.
|
||||
MaxBytesPerTxLength = 1073741824 // MaxBytesPerTxLength defines the maximum number of bytes that can be included in a transaction.
|
||||
FeeRecipientLength = 20 // FeeRecipientLength defines the byte length of a fee recipient.
|
||||
LogsBloomLength = 256 // LogsBloomLength defines the byte length of a logs bloom.
|
||||
VersionLength = 4 // VersionLength defines the byte length of a fork version number.
|
||||
)
|
||||
|
||||
@@ -5,23 +5,22 @@ package field_params
|
||||
|
||||
const (
|
||||
Preset = "minimal"
|
||||
BlockRootsLength = 64 // SLOTS_PER_HISTORICAL_ROOT
|
||||
StateRootsLength = 64 // SLOTS_PER_HISTORICAL_ROOT
|
||||
RandaoMixesLength = 64 // EPOCHS_PER_HISTORICAL_VECTOR
|
||||
HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT
|
||||
ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT
|
||||
Eth1DataVotesLength = 32 // SLOTS_PER_ETH1_VOTING_PERIOD
|
||||
PreviousEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
CurrentEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
SlashingsLength = 64 // EPOCHS_PER_SLASHINGS_VECTOR
|
||||
SyncCommitteeLength = 32 // SYNC_COMMITTEE_SIZE
|
||||
RootLength = 32 // RootLength defines the byte length of a Merkle root.
|
||||
BLSSignatureLength = 96 // BLSSignatureLength defines the byte length of a BLSSignature.
|
||||
BLSPubkeyLength = 48 // BLSPubkeyLength defines the byte length of a BLSSignature.
|
||||
MaxTxsPerPayloadLength = 1048576 // MaxTxsPerPayloadLength defines the maximum number of transactions that can be included in a payload.
|
||||
MaxBytesPerTxLength = 1073741824 // MaxBytesPerTxLength defines the maximum number of bytes that can be included in a transaction.
|
||||
FeeRecipientLength = 20 // FeeRecipientLength defines the byte length of a fee recipient.
|
||||
LogsBloomLength = 256 // LogsBloomLength defines the byte length of a logs bloom.
|
||||
VersionLength = 4 // VersionLength defines the byte length of a fork version number.
|
||||
EthBurnAddressHex = "0x0000000000000000000000000000000000000000" // EthBurnAddressHex defines the hex encoded address of the eth1.0 burn contract.
|
||||
BlockRootsLength = 64 // SLOTS_PER_HISTORICAL_ROOT
|
||||
StateRootsLength = 64 // SLOTS_PER_HISTORICAL_ROOT
|
||||
RandaoMixesLength = 64 // EPOCHS_PER_HISTORICAL_VECTOR
|
||||
HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT
|
||||
ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT
|
||||
Eth1DataVotesLength = 32 // SLOTS_PER_ETH1_VOTING_PERIOD
|
||||
PreviousEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
CurrentEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
SlashingsLength = 64 // EPOCHS_PER_SLASHINGS_VECTOR
|
||||
SyncCommitteeLength = 32 // SYNC_COMMITTEE_SIZE
|
||||
RootLength = 32 // RootLength defines the byte length of a Merkle root.
|
||||
BLSSignatureLength = 96 // BLSSignatureLength defines the byte length of a BLSSignature.
|
||||
BLSPubkeyLength = 48 // BLSPubkeyLength defines the byte length of a BLSSignature.
|
||||
MaxTxsPerPayloadLength = 1048576 // MaxTxsPerPayloadLength defines the maximum number of transactions that can be included in a payload.
|
||||
MaxBytesPerTxLength = 1073741824 // MaxBytesPerTxLength defines the maximum number of bytes that can be included in a transaction.
|
||||
FeeRecipientLength = 20 // FeeRecipientLength defines the byte length of a fee recipient.
|
||||
LogsBloomLength = 256 // LogsBloomLength defines the byte length of a logs bloom.
|
||||
VersionLength = 4 // VersionLength defines the byte length of a fork version number.
|
||||
)
|
||||
|
||||
@@ -192,6 +192,8 @@ type BeaconChainConfig struct {
|
||||
TerminalBlockHashActivationEpoch types.Epoch `yaml:"TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH" spec:"true"` // TerminalBlockHashActivationEpoch of beacon chain.
|
||||
TerminalTotalDifficulty string `yaml:"TERMINAL_TOTAL_DIFFICULTY" spec:"true"` // TerminalTotalDifficulty is part of the experimental Bellatrix spec. This value is type is currently TBD.
|
||||
DefaultFeeRecipient common.Address // DefaultFeeRecipient where the transaction fee goes to.
|
||||
EthBurnAddressHex string // EthBurnAddressHex is the constant eth address written in hex format to burn fees in that network. the default is 0x0
|
||||
DefaultBuilderGasLimit uint64 // DefaultBuilderGasLimit is the default used to set the gaslimit for the Builder APIs, typically at around 30M wei.
|
||||
}
|
||||
|
||||
// InitializeForkSchedule initializes the schedules forks baked into the config.
|
||||
|
||||
@@ -244,6 +244,8 @@ var mainnetBeaconConfig = &BeaconChainConfig{
|
||||
TerminalBlockHashActivationEpoch: 18446744073709551615,
|
||||
TerminalBlockHash: [32]byte{},
|
||||
TerminalTotalDifficulty: "115792089237316195423570985008687907853269984665640564039457584007913129638912",
|
||||
EthBurnAddressHex: "0x0000000000000000000000000000000000000000",
|
||||
DefaultBuilderGasLimit: uint64(30000000),
|
||||
}
|
||||
|
||||
// MainnetTestConfig provides a version of the mainnet config that has a different name
|
||||
|
||||
@@ -2,7 +2,7 @@ load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["fee-recipient-config.go"],
|
||||
srcs = ["proposer-settings.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/config/validator/service",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package validator_service_config
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
field_params "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
)
|
||||
|
||||
// FeeRecipientFileConfig is the struct representation of the JSON config file set in the validator through the CLI.
|
||||
// ProposeConfig is the map of validator address to fee recipient options all in hex format.
|
||||
// DefaultConfig is the default fee recipient address for all validators unless otherwise specified in the propose config.required.
|
||||
type FeeRecipientFileConfig struct {
|
||||
ProposeConfig map[string]*FeeRecipientFileOptions `json:"proposer_config"`
|
||||
DefaultConfig *FeeRecipientFileOptions `json:"default_config"`
|
||||
}
|
||||
|
||||
// FeeRecipientFileOptions is the struct representation of the JSON config file set in the validator through the CLI.
|
||||
// FeeRecipient is set to an eth address in hex string format with 0x prefix.
|
||||
type FeeRecipientFileOptions struct {
|
||||
FeeRecipient string `json:"fee_recipient"`
|
||||
}
|
||||
|
||||
// FeeRecipientConfig is a Prysm internal representation of the fee recipient config on the validator client.
|
||||
// FeeRecipientFileConfig maps to FeeRecipientConfig on import through the CLI.
|
||||
type FeeRecipientConfig struct {
|
||||
ProposeConfig map[[field_params.BLSPubkeyLength]byte]*FeeRecipientOptions
|
||||
DefaultConfig *FeeRecipientOptions
|
||||
}
|
||||
|
||||
// FeeRecipientOptions is a Prysm internal representation of the FeeRecipientFileOptions on the validator client in bytes format instead of hex.
|
||||
type FeeRecipientOptions struct {
|
||||
FeeRecipient common.Address
|
||||
}
|
||||
35
config/validator/service/proposer-settings.go
Normal file
35
config/validator/service/proposer-settings.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package validator_service_config
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
field_params "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
)
|
||||
|
||||
// ProposerSettingsPayload is the struct representation of the JSON or YAML payload set in the validator through the CLI.
|
||||
// ProposeConfig is the map of validator address to fee recipient options all in hex format.
|
||||
// DefaultConfig is the default fee recipient address for all validators unless otherwise specified in the propose config.required.
|
||||
type ProposerSettingsPayload struct {
|
||||
ProposeConfig map[string]*ProposerOptionPayload `json:"proposer_config" yaml:"proposer_config"`
|
||||
DefaultConfig *ProposerOptionPayload `json:"default_config" yaml:"default_config"`
|
||||
}
|
||||
|
||||
// ProposerOptionPayload is the struct representation of the JSON config file set in the validator through the CLI.
|
||||
// FeeRecipient is set to an eth address in hex string format with 0x prefix.
|
||||
// GasLimit is a number set to help the network decide on the maximum gas in each block.
|
||||
type ProposerOptionPayload struct {
|
||||
FeeRecipient string `json:"fee_recipient" yaml:"fee_recipient"`
|
||||
GasLimit uint64 `json:"gas_limit,omitempty" yaml:"gas_limit,omitempty"`
|
||||
}
|
||||
|
||||
// ProposerSettings is a Prysm internal representation of the fee recipient config on the validator client.
|
||||
// ProposerSettingsPayload maps to ProposerSettings on import through the CLI.
|
||||
type ProposerSettings struct {
|
||||
ProposeConfig map[[field_params.BLSPubkeyLength]byte]*ProposerOption
|
||||
DefaultConfig *ProposerOption
|
||||
}
|
||||
|
||||
// ProposerOption is a Prysm internal representation of the ProposerOptionPayload on the validator client in bytes format instead of hex.
|
||||
type ProposerOption struct {
|
||||
FeeRecipient common.Address
|
||||
GasLimit uint64
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
|
||||
// Hash: 926169eadd07a1db289a5e8416388f330cfb302b03fb1a1590af7fc8f52db228
|
||||
|
||||
package eth
|
||||
|
||||
import (
|
||||
|
||||
2
testing/mock/beacon_validator_client_mock.go
generated
2
testing/mock/beacon_validator_client_mock.go
generated
@@ -111,7 +111,7 @@ func (m *MockBeaconNodeValidatorClient) GetBeaconBlock(arg0 context.Context, arg
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetBeaconBlock indicates an expected call of GetBeaconBlock.
|
||||
// GetBeaconBlock indicates an expected call of GetBeaconBlock
|
||||
func (mr *MockBeaconNodeValidatorClientMockRecorder) GetBeaconBlock(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
|
||||
@@ -179,8 +179,8 @@ func (_ MockValidator) CheckDoppelGanger(_ context.Context) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
// UpdateFeeRecipient for mocking
|
||||
func (_ MockValidator) UpdateFeeRecipient(_ context.Context, _ keymanager.IKeymanager) error {
|
||||
// PushProposerSettings for mocking
|
||||
func (_ MockValidator) PushProposerSettings(_ context.Context, _ keymanager.IKeymanager) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@ go_test(
|
||||
"@com_github_wealdtech_go_eth2_util//:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
"@io_bazel_rules_go//proto/wkt:empty_go_proto",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
"@org_golang_google_grpc//metadata:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
|
||||
@@ -57,5 +57,5 @@ type Validator interface {
|
||||
ReceiveBlocks(ctx context.Context, connectionErrorChannel chan<- error)
|
||||
HandleKeyReload(ctx context.Context, newKeys [][fieldparams.BLSPubkeyLength]byte) (bool, error)
|
||||
CheckDoppelGanger(ctx context.Context) error
|
||||
UpdateFeeRecipient(ctx context.Context, km keymanager.IKeymanager) error
|
||||
PushProposerSettings(ctx context.Context, km keymanager.IKeymanager) error
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"github.com/prysmaticlabs/prysm/validator/client/iface"
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager"
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager/remote"
|
||||
"go.opencensus.io/trace"
|
||||
"google.golang.org/grpc/codes"
|
||||
@@ -115,10 +116,9 @@ func run(ctx context.Context, v iface.Validator) {
|
||||
log.Fatalf("Could not get keymanager: %v", err)
|
||||
}
|
||||
sub := km.SubscribeAccountChanges(accountsChangedChan)
|
||||
|
||||
// Set properties on the beacon node like the fee recipient for validators that are being used & active.
|
||||
if err := v.UpdateFeeRecipient(ctx, km); err != nil {
|
||||
log.Fatalf("PreparedBeaconProposer Failed: %v", err) // allow fatal. skipcq
|
||||
if err := v.PushProposerSettings(ctx, km); err != nil {
|
||||
log.Fatalf("Failed to update proposer settings: %v", err) // allow fatal. skipcq
|
||||
}
|
||||
for {
|
||||
slotCtx, cancel := context.WithCancel(ctx)
|
||||
@@ -152,15 +152,7 @@ func run(ctx context.Context, v iface.Validator) {
|
||||
}
|
||||
case slot := <-v.NextSlot():
|
||||
span.AddAttributes(trace.Int64Attribute("slot", int64(slot))) // lint:ignore uintcast -- This conversion is OK for tracing.
|
||||
|
||||
remoteKm, ok := km.(remote.RemoteKeymanager)
|
||||
if ok {
|
||||
_, err := remoteKm.ReloadPublicKeys(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error(msgCouldNotFetchKeys)
|
||||
}
|
||||
}
|
||||
|
||||
reloadRemoteKeys(ctx, km)
|
||||
allExited, err := v.AllValidatorsAreExited(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not check if validators are exited")
|
||||
@@ -184,6 +176,15 @@ func run(ctx context.Context, v iface.Validator) {
|
||||
continue
|
||||
}
|
||||
|
||||
if slots.IsEpochStart(slot) {
|
||||
go func() {
|
||||
//deadline set for next epoch rounded up
|
||||
if err := v.PushProposerSettings(ctx, km); err != nil {
|
||||
log.Warnf("Failed to update proposer settings: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Start fetching domain data for the next epoch.
|
||||
if slots.IsEpochEnd(slot) {
|
||||
go v.UpdateDomainDataCaches(ctx, slot+1)
|
||||
@@ -246,6 +247,16 @@ func run(ctx context.Context, v iface.Validator) {
|
||||
}
|
||||
}
|
||||
|
||||
func reloadRemoteKeys(ctx context.Context, km keymanager.IKeymanager) {
|
||||
remoteKm, ok := km.(remote.RemoteKeymanager)
|
||||
if ok {
|
||||
_, err := remoteKm.ReloadPublicKeys(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error(msgCouldNotFetchKeys)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isConnectionError(err error) bool {
|
||||
return err != nil && errors.Is(err, iface.ErrConnectionIssue)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/prysmaticlabs/prysm/async/event"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
@@ -245,3 +246,20 @@ func TestKeyReload_RemoteKeymanager(t *testing.T) {
|
||||
run(ctx, v)
|
||||
assert.Equal(t, true, km.ReloadPublicKeysCalled)
|
||||
}
|
||||
|
||||
func TestUpdateProposerSettingsAt_EpochStart(t *testing.T) {
|
||||
v := &testutil.FakeValidator{Km: &mockKeymanager{accountsChangedFeed: &event.Feed{}}}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
hook := logTest.NewGlobal()
|
||||
slot := params.BeaconConfig().SlotsPerEpoch
|
||||
ticker := make(chan types.Slot)
|
||||
v.NextSlotRet = ticker
|
||||
go func() {
|
||||
ticker <- slot
|
||||
|
||||
cancel()
|
||||
}()
|
||||
|
||||
run(ctx, v)
|
||||
assert.LogsContain(t, hook, "updated proposer settings")
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ type ValidatorService struct {
|
||||
grpcHeaders []string
|
||||
graffiti []byte
|
||||
Web3SignerConfig *remote_web3signer.SetupConfig
|
||||
feeRecipientConfig *validator_service_config.FeeRecipientConfig
|
||||
proposerSettings *validator_service_config.ProposerSettings
|
||||
}
|
||||
|
||||
// Config for the validator service.
|
||||
@@ -94,7 +94,7 @@ type Config struct {
|
||||
GraffitiFlag string
|
||||
Endpoint string
|
||||
Web3SignerConfig *remote_web3signer.SetupConfig
|
||||
FeeRecipientConfig *validator_service_config.FeeRecipientConfig
|
||||
ProposerSettings *validator_service_config.ProposerSettings
|
||||
}
|
||||
|
||||
// NewValidatorService creates a new validator service for the service
|
||||
@@ -123,7 +123,7 @@ func NewValidatorService(ctx context.Context, cfg *Config) (*ValidatorService, e
|
||||
graffitiStruct: cfg.GraffitiStruct,
|
||||
logDutyCountDown: cfg.LogDutyCountDown,
|
||||
Web3SignerConfig: cfg.Web3SignerConfig,
|
||||
feeRecipientConfig: cfg.FeeRecipientConfig,
|
||||
proposerSettings: cfg.ProposerSettings,
|
||||
}
|
||||
|
||||
dialOpts := ConstructDialOptions(
|
||||
@@ -206,7 +206,7 @@ func (v *ValidatorService) Start() {
|
||||
eipImportBlacklistedPublicKeys: slashablePublicKeys,
|
||||
logDutyCountDown: v.logDutyCountDown,
|
||||
Web3SignerConfig: v.Web3SignerConfig,
|
||||
feeRecipientConfig: v.feeRecipientConfig,
|
||||
ProposerSettings: v.proposerSettings,
|
||||
walletIntializedChannel: make(chan *wallet.Wallet, 1),
|
||||
}
|
||||
// To resolve a race condition at startup due to the interface
|
||||
|
||||
@@ -17,5 +17,6 @@ go_library(
|
||||
"//time:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"//validator/keymanager:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
prysmTime "github.com/prysmaticlabs/prysm/time"
|
||||
"github.com/prysmaticlabs/prysm/validator/client/iface"
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var _ iface.Validator = (*FakeValidator)(nil)
|
||||
@@ -247,8 +248,9 @@ func (fv *FakeValidator) HandleKeyReload(_ context.Context, newKeys [][fieldpara
|
||||
func (_ *FakeValidator) SubmitSignedContributionAndProof(_ context.Context, _ types.Slot, _ [fieldparams.BLSPubkeyLength]byte) {
|
||||
}
|
||||
|
||||
// UpdateFeeRecipient for mocking
|
||||
func (_ *FakeValidator) UpdateFeeRecipient(_ context.Context, _ keymanager.IKeymanager) error {
|
||||
// PushProposerSettings for mocking
|
||||
func (_ *FakeValidator) PushProposerSettings(_ context.Context, _ keymanager.IKeymanager) error {
|
||||
log.Infoln("Mock updated proposer settings")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ type validator struct {
|
||||
graffiti []byte
|
||||
voteStats voteStats
|
||||
Web3SignerConfig *remote_web3signer.SetupConfig
|
||||
feeRecipientConfig *validator_service_config.FeeRecipientConfig
|
||||
ProposerSettings *validator_service_config.ProposerSettings
|
||||
walletIntializedChannel chan *wallet.Wallet
|
||||
}
|
||||
|
||||
@@ -941,10 +941,10 @@ func (v *validator) logDuties(slot types.Slot, duties []*ethpb.DutiesResponse_Du
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateFeeRecipient calls the prepareBeaconProposer RPC to set the fee recipient.
|
||||
func (v *validator) UpdateFeeRecipient(ctx context.Context, km keymanager.IKeymanager) error {
|
||||
// PushProposerSettings calls the prepareBeaconProposer RPC to set the fee recipient and also the register validator API if using a custom builder.
|
||||
func (v *validator) PushProposerSettings(ctx context.Context, km keymanager.IKeymanager) error {
|
||||
// only used after Bellatrix
|
||||
if v.feeRecipientConfig == nil {
|
||||
if v.ProposerSettings == nil {
|
||||
e := params.BeaconConfig().BellatrixForkEpoch
|
||||
if e != math.MaxUint64 && slots.ToEpoch(slots.CurrentSlot(v.genesisTime)) < e {
|
||||
log.Warn("After the Ethereum merge, you will need to specify the Ethereum addresses which will receive transaction fee rewards from proposing blocks. " +
|
||||
@@ -956,6 +956,9 @@ func (v *validator) UpdateFeeRecipient(ctx context.Context, km keymanager.IKeyma
|
||||
}
|
||||
return nil
|
||||
}
|
||||
deadline := v.SlotDeadline(slots.RoundUpToNearestEpoch(slots.CurrentSlot(v.genesisTime)))
|
||||
ctx, cancel := context.WithDeadline(ctx, deadline)
|
||||
defer cancel()
|
||||
if km == nil {
|
||||
return errors.New("keymanager is nil when calling PrepareBeaconProposer")
|
||||
}
|
||||
@@ -963,7 +966,7 @@ func (v *validator) UpdateFeeRecipient(ctx context.Context, km keymanager.IKeyma
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
feeRecipients, err := v.feeRecipients(ctx, pubkeys)
|
||||
feeRecipients, registerValidatorRequests, err := v.buildProposerSettingsRequests(ctx, pubkeys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -977,47 +980,73 @@ func (v *validator) UpdateFeeRecipient(ctx context.Context, km keymanager.IKeyma
|
||||
return err
|
||||
}
|
||||
log.Infoln("Successfully prepared beacon proposer with fee recipient to validator index mapping.")
|
||||
failedRegistrationCount := 0
|
||||
for _, request := range registerValidatorRequests {
|
||||
// calls beacon API but used for custom builders
|
||||
if err := SubmitValidatorRegistration(ctx, v.validatorClient, v.node, km.Sign, request); err != nil {
|
||||
// log the error and keep going
|
||||
failedRegistrationCount++
|
||||
log.Warnf("failed to register validator for custom builder for %s, error: %v ", hexutil.Encode(request.Pubkey), err)
|
||||
}
|
||||
}
|
||||
if failedRegistrationCount != 0 {
|
||||
return errors.Errorf("Register validator requests failed %d times out of %d requests", failedRegistrationCount, len(registerValidatorRequests))
|
||||
}
|
||||
log.Infoln("Successfully submitted builder validator registration settings for custom builders.")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *validator) feeRecipients(ctx context.Context, pubkeys [][fieldparams.BLSPubkeyLength]byte) ([]*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer, error) {
|
||||
var validatorToFeeRecipientArray []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer
|
||||
func (v *validator) buildProposerSettingsRequests(ctx context.Context, pubkeys [][fieldparams.BLSPubkeyLength]byte) ([]*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer, []*ethpb.ValidatorRegistrationV1, error) {
|
||||
var validatorToFeeRecipients []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer
|
||||
var registerValidatorRequests []*ethpb.ValidatorRegistrationV1
|
||||
// need to check for pubkey to validator index mappings
|
||||
for _, key := range pubkeys {
|
||||
feeRecipient := common.HexToAddress(fieldparams.EthBurnAddressHex)
|
||||
skipAppendToFeeRecipientArray := false
|
||||
feeRecipient := common.HexToAddress(params.BeaconConfig().EthBurnAddressHex)
|
||||
gasLimit := params.BeaconConfig().DefaultBuilderGasLimit
|
||||
validatorIndex, found := v.pubkeyToValidatorIndex[key]
|
||||
// ignore updating fee recipient if validator index is not found
|
||||
if !found {
|
||||
ind, foundIndex, err := v.cacheValidatorPubkeyHexToValidatorIndex(ctx, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if !foundIndex {
|
||||
//if still not found, skip this validator
|
||||
continue
|
||||
skipAppendToFeeRecipientArray = true
|
||||
}
|
||||
validatorIndex = ind
|
||||
v.pubkeyToValidatorIndex[key] = validatorIndex
|
||||
}
|
||||
if v.feeRecipientConfig.DefaultConfig != nil {
|
||||
feeRecipient = v.feeRecipientConfig.DefaultConfig.FeeRecipient
|
||||
if v.ProposerSettings.DefaultConfig != nil {
|
||||
feeRecipient = v.ProposerSettings.DefaultConfig.FeeRecipient
|
||||
gasLimit = v.ProposerSettings.DefaultConfig.GasLimit
|
||||
}
|
||||
if v.feeRecipientConfig.ProposeConfig != nil {
|
||||
option, ok := v.feeRecipientConfig.ProposeConfig[key]
|
||||
if v.ProposerSettings.ProposeConfig != nil {
|
||||
option, ok := v.ProposerSettings.ProposeConfig[key]
|
||||
if ok && option != nil {
|
||||
// override the default if a proposeconfig is set
|
||||
feeRecipient = option.FeeRecipient
|
||||
gasLimit = option.GasLimit
|
||||
}
|
||||
}
|
||||
if hexutil.Encode(feeRecipient.Bytes()) == fieldparams.EthBurnAddressHex {
|
||||
if hexutil.Encode(feeRecipient.Bytes()) == params.BeaconConfig().EthBurnAddressHex {
|
||||
log.Warnln("Fee recipient is set to the burn address. You will not be rewarded transaction fees on this setting. Please set a different fee recipient.")
|
||||
}
|
||||
validatorToFeeRecipientArray = append(validatorToFeeRecipientArray, ðpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
ValidatorIndex: validatorIndex,
|
||||
FeeRecipient: feeRecipient[:],
|
||||
if !skipAppendToFeeRecipientArray {
|
||||
validatorToFeeRecipients = append(validatorToFeeRecipients, ðpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
ValidatorIndex: validatorIndex,
|
||||
FeeRecipient: feeRecipient[:],
|
||||
})
|
||||
}
|
||||
registerValidatorRequests = append(registerValidatorRequests, ðpb.ValidatorRegistrationV1{
|
||||
FeeRecipient: feeRecipient[:],
|
||||
GasLimit: gasLimit,
|
||||
Timestamp: uint64(time.Now().UTC().Unix()),
|
||||
Pubkey: key[:],
|
||||
})
|
||||
|
||||
}
|
||||
return validatorToFeeRecipientArray, nil
|
||||
return validatorToFeeRecipients, registerValidatorRequests, nil
|
||||
}
|
||||
|
||||
func (v *validator) cacheValidatorPubkeyHexToValidatorIndex(ctx context.Context, pubkey [fieldparams.BLSPubkeyLength]byte) (types.ValidatorIndex, bool, error) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/prysmaticlabs/prysm/async/event"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
@@ -39,6 +40,7 @@ import (
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -357,6 +359,7 @@ func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := mock2.NewMockBeaconNodeValidatorClient(ctrl)
|
||||
nodeClient := mock2.NewMockNodeClient(ctrl)
|
||||
privKey, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
||||
@@ -369,11 +372,12 @@ func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) {
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
keyManager: km,
|
||||
node: nodeClient,
|
||||
genesisTime: 1,
|
||||
pubkeyToValidatorIndex: map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex{pubKey: 1},
|
||||
feeRecipientConfig: &validator_service_config.FeeRecipientConfig{
|
||||
ProposerSettings: &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
},
|
||||
},
|
||||
@@ -392,11 +396,32 @@ func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) {
|
||||
resp,
|
||||
nil,
|
||||
)
|
||||
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A").Bytes(), ValidatorIndex: 1},
|
||||
},
|
||||
}).Return(nil, nil)
|
||||
|
||||
require.NoError(t, v.WaitForActivation(ctx, nil), "Could not wait for activation")
|
||||
require.LogsContain(t, hook, "Validator activated")
|
||||
}
|
||||
@@ -405,7 +430,7 @@ func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := mock2.NewMockBeaconNodeValidatorClient(ctrl)
|
||||
|
||||
nodeClient := mock2.NewMockNodeClient(ctrl)
|
||||
privKey, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
||||
@@ -417,12 +442,13 @@ func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) {
|
||||
}
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
keyManager: km,
|
||||
genesisTime: 1,
|
||||
pubkeyToValidatorIndex: map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex{pubKey: 1},
|
||||
feeRecipientConfig: &validator_service_config.FeeRecipientConfig{
|
||||
ProposerSettings: &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
},
|
||||
},
|
||||
@@ -442,6 +468,24 @@ func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) {
|
||||
resp,
|
||||
nil,
|
||||
)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A").Bytes(), ValidatorIndex: 1},
|
||||
@@ -1464,17 +1508,29 @@ func TestValidator_WaitForKeymanagerInitialization_Interop(t *testing.T) {
|
||||
require.NotNil(t, km)
|
||||
}
|
||||
|
||||
func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
func TestValidator_PushProposerSettings(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
ctx := context.Background()
|
||||
db := dbTest.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{})
|
||||
client := mock2.NewMockBeaconNodeValidatorClient(ctrl)
|
||||
nodeClient := mock2.NewMockNodeClient(ctrl)
|
||||
defaultFeeHex := "0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"
|
||||
byteValueAddress, err := hexutil.Decode("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9")
|
||||
require.NoError(t, err)
|
||||
|
||||
type ExpectedValidatorRegistration struct {
|
||||
FeeRecipient []byte
|
||||
GasLimit uint64
|
||||
Timestamp uint64
|
||||
Pubkey []byte
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
validatorSetter func(t *testing.T) *validator
|
||||
feeRecipientMap map[types.ValidatorIndex]string
|
||||
err string
|
||||
name string
|
||||
validatorSetter func(t *testing.T) *validator
|
||||
feeRecipientMap map[types.ValidatorIndex]string
|
||||
mockExpectedRequests []ExpectedValidatorRegistration
|
||||
err string
|
||||
}{
|
||||
{
|
||||
name: " Happy Path",
|
||||
@@ -1482,6 +1538,7 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
db: db,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
useWeb: false,
|
||||
@@ -1499,10 +1556,11 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
keys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
require.NoError(t, err)
|
||||
v.feeRecipientConfig = &validator_service_config.FeeRecipientConfig{
|
||||
v.ProposerSettings = &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress(defaultFeeHex),
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
}
|
||||
client.EXPECT().ValidatorIndex(
|
||||
@@ -1511,6 +1569,24 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
).Return(ðpb.ValidatorIndexResponse{
|
||||
Index: 1,
|
||||
}, nil)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 1},
|
||||
@@ -1521,6 +1597,12 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
feeRecipientMap: map[types.ValidatorIndex]string{
|
||||
1: defaultFeeHex,
|
||||
},
|
||||
mockExpectedRequests: []ExpectedValidatorRegistration{
|
||||
{
|
||||
FeeRecipient: byteValueAddress,
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: " Skip if no config",
|
||||
@@ -1547,6 +1629,7 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
db: db,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
useWeb: false,
|
||||
@@ -1557,9 +1640,9 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
}
|
||||
err := v.WaitForKeymanagerInitialization(ctx)
|
||||
require.NoError(t, err)
|
||||
v.feeRecipientConfig = &validator_service_config.FeeRecipientConfig{
|
||||
v.ProposerSettings = &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress(defaultFeeHex),
|
||||
},
|
||||
}
|
||||
@@ -1573,6 +1656,24 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
).Return(ðpb.ValidatorIndexResponse{
|
||||
Index: 1,
|
||||
}, nil)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 1},
|
||||
@@ -1583,6 +1684,12 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
feeRecipientMap: map[types.ValidatorIndex]string{
|
||||
1: defaultFeeHex,
|
||||
},
|
||||
mockExpectedRequests: []ExpectedValidatorRegistration{
|
||||
{
|
||||
FeeRecipient: byteValueAddress,
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: " Happy Path proposer config not nil",
|
||||
@@ -1590,6 +1697,7 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
db: db,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
useWeb: false,
|
||||
@@ -1600,7 +1708,7 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
}
|
||||
err := v.WaitForKeymanagerInitialization(ctx)
|
||||
require.NoError(t, err)
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.FeeRecipientOptions)
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.ProposerOption)
|
||||
km, err := v.Keymanager()
|
||||
require.NoError(t, err)
|
||||
keys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
@@ -1623,21 +1731,52 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
{FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 2},
|
||||
},
|
||||
}).Return(nil, nil)
|
||||
config[keys[0]] = &validator_service_config.FeeRecipientOptions{
|
||||
config[keys[0]] = &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
GasLimit: uint64(40000000),
|
||||
}
|
||||
v.feeRecipientConfig = &validator_service_config.FeeRecipientConfig{
|
||||
v.ProposerSettings = &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: config,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress(defaultFeeHex),
|
||||
GasLimit: uint64(35000000),
|
||||
},
|
||||
}
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Times(2).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(&empty.Empty{}, nil)
|
||||
return &v
|
||||
},
|
||||
feeRecipientMap: map[types.ValidatorIndex]string{
|
||||
1: "0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9",
|
||||
2: defaultFeeHex,
|
||||
},
|
||||
mockExpectedRequests: []ExpectedValidatorRegistration{
|
||||
|
||||
{
|
||||
FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(),
|
||||
GasLimit: uint64(40000000),
|
||||
},
|
||||
{
|
||||
FeeRecipient: byteValueAddress,
|
||||
GasLimit: uint64(35000000),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: " proposer config not nil but fee recipient empty ",
|
||||
@@ -1645,6 +1784,7 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
db: db,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
useWeb: false,
|
||||
@@ -1655,13 +1795,13 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
}
|
||||
err := v.WaitForKeymanagerInitialization(ctx)
|
||||
require.NoError(t, err)
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.FeeRecipientOptions)
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.ProposerOption)
|
||||
km, err := v.Keymanager()
|
||||
require.NoError(t, err)
|
||||
keys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
require.NoError(t, err)
|
||||
client.EXPECT().ValidatorIndex(
|
||||
ctx, // ctx
|
||||
gomock.Any(), // ctx
|
||||
ðpb.ValidatorIndexRequest{PublicKey: keys[0][:]},
|
||||
).Return(ðpb.ValidatorIndexResponse{
|
||||
Index: 1,
|
||||
@@ -1671,16 +1811,33 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
{FeeRecipient: common.HexToAddress("0x0").Bytes(), ValidatorIndex: 1},
|
||||
},
|
||||
}).Return(nil, nil)
|
||||
config[keys[0]] = &validator_service_config.FeeRecipientOptions{
|
||||
config[keys[0]] = &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.Address{},
|
||||
}
|
||||
v.feeRecipientConfig = &validator_service_config.FeeRecipientConfig{
|
||||
v.ProposerSettings = &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: config,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress(defaultFeeHex),
|
||||
},
|
||||
}
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
return &v
|
||||
},
|
||||
},
|
||||
@@ -1700,21 +1857,21 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
}
|
||||
err := v.WaitForKeymanagerInitialization(ctx)
|
||||
require.NoError(t, err)
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.FeeRecipientOptions)
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.ProposerOption)
|
||||
km, err := v.Keymanager()
|
||||
require.NoError(t, err)
|
||||
keys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
require.NoError(t, err)
|
||||
client.EXPECT().ValidatorIndex(
|
||||
ctx, // ctx
|
||||
gomock.Any(), // ctx
|
||||
ðpb.ValidatorIndexRequest{PublicKey: keys[0][:]},
|
||||
).Return(nil, errors.New("Could not find validator index for public key"))
|
||||
config[keys[0]] = &validator_service_config.FeeRecipientOptions{
|
||||
config[keys[0]] = &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
}
|
||||
v.feeRecipientConfig = &validator_service_config.FeeRecipientConfig{
|
||||
v.ProposerSettings = &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: config,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress(defaultFeeHex),
|
||||
},
|
||||
}
|
||||
@@ -1740,6 +1897,70 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
return &v
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "register validator batch failed ",
|
||||
validatorSetter: func(t *testing.T) *validator {
|
||||
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
db: db,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
useWeb: false,
|
||||
interopKeysConfig: &local.InteropKeymanagerConfig{
|
||||
NumValidatorKeys: 1,
|
||||
Offset: 1,
|
||||
},
|
||||
}
|
||||
err := v.WaitForKeymanagerInitialization(ctx)
|
||||
require.NoError(t, err)
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.ProposerOption)
|
||||
km, err := v.Keymanager()
|
||||
require.NoError(t, err)
|
||||
keys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
require.NoError(t, err)
|
||||
client.EXPECT().ValidatorIndex(
|
||||
gomock.Any(), // ctx
|
||||
ðpb.ValidatorIndexRequest{PublicKey: keys[0][:]},
|
||||
).Return(ðpb.ValidatorIndexResponse{
|
||||
Index: 1,
|
||||
}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress("0x0").Bytes(), ValidatorIndex: 1},
|
||||
},
|
||||
}).Return(nil, nil)
|
||||
config[keys[0]] = &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.Address{},
|
||||
}
|
||||
v.ProposerSettings = &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: config,
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress(defaultFeeHex),
|
||||
},
|
||||
}
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, errors.New("request failed"))
|
||||
return &v
|
||||
},
|
||||
err: "Register validator requests failed",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -1749,18 +1970,21 @@ func TestValidator_UpdateFeeRecipient(t *testing.T) {
|
||||
pubkeys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
require.NoError(t, err)
|
||||
if tt.feeRecipientMap != nil {
|
||||
feeRecipients, err := v.feeRecipients(ctx, pubkeys)
|
||||
feeRecipients, registerValidatorRequests, err := v.buildProposerSettingsRequests(ctx, pubkeys)
|
||||
require.NoError(t, err)
|
||||
for _, recipient := range feeRecipients {
|
||||
require.Equal(t, strings.ToLower(tt.feeRecipientMap[recipient.ValidatorIndex]), strings.ToLower(hexutil.Encode(recipient.FeeRecipient)))
|
||||
}
|
||||
require.Equal(t, len(tt.feeRecipientMap), len(feeRecipients))
|
||||
for i, request := range tt.mockExpectedRequests {
|
||||
require.Equal(t, tt.mockExpectedRequests[i].GasLimit, request.GasLimit)
|
||||
require.Equal(t, hexutil.Encode(tt.mockExpectedRequests[i].FeeRecipient), hexutil.Encode(request.FeeRecipient))
|
||||
}
|
||||
require.Equal(t, len(tt.mockExpectedRequests), len(registerValidatorRequests))
|
||||
}
|
||||
|
||||
if err := v.UpdateFeeRecipient(ctx, km); tt.err != "" {
|
||||
if err := v.PushProposerSettings(ctx, km); tt.err != "" {
|
||||
assert.ErrorContains(t, tt.err, err)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,6 @@ func (v *validator) waitForActivation(ctx context.Context, accountsChangedChan <
|
||||
if ctx.Err() == context.Canceled {
|
||||
return errors.Wrap(ctx.Err(), "context canceled, not waiting for activation anymore")
|
||||
}
|
||||
|
||||
validatingKeys, err = remoteKm.ReloadPublicKeys(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, msgCouldNotFetchKeys)
|
||||
@@ -133,7 +132,7 @@ func (v *validator) waitForActivation(ctx context.Context, accountsChangedChan <
|
||||
if valActivated {
|
||||
logActiveValidatorStatus(statuses)
|
||||
// Set properties on the beacon node like the fee recipient for validators that are being used & active.
|
||||
if err := v.UpdateFeeRecipient(ctx, remoteKm); err != nil {
|
||||
if err := v.PushProposerSettings(ctx, remoteKm); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@@ -180,8 +179,9 @@ func (v *validator) waitForActivation(ctx context.Context, accountsChangedChan <
|
||||
valActivated := v.checkAndLogValidatorStatus(statuses)
|
||||
if valActivated {
|
||||
logActiveValidatorStatus(statuses)
|
||||
|
||||
// Set properties on the beacon node like the fee recipient for validators that are being used & active.
|
||||
if err := v.UpdateFeeRecipient(ctx, v.keyManager); err != nil {
|
||||
if err := v.PushProposerSettings(ctx, v.keyManager); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/pkg/errors"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
validator_service_config "github.com/prysmaticlabs/prysm/config/validator/service"
|
||||
@@ -27,6 +28,8 @@ import (
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
"github.com/tyler-smith/go-bip39"
|
||||
util "github.com/wealdtech/go-eth2-util"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
func TestWaitActivation_ContextCanceled(t *testing.T) {
|
||||
@@ -67,6 +70,7 @@ func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
||||
nodeClient := mock.NewMockNodeClient(ctrl)
|
||||
privKey, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
||||
@@ -78,11 +82,12 @@ func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) {
|
||||
}
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
keyManager: km,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
feeRecipientConfig: &validator_service_config.FeeRecipientConfig{
|
||||
ProposerSettings: &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
@@ -103,6 +108,24 @@ func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) {
|
||||
resp := generateMockStatusResponse([][]byte{pubKey[:]})
|
||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
||||
clientStream.EXPECT().Recv().Return(resp, nil)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
|
||||
}
|
||||
|
||||
@@ -110,7 +133,7 @@ func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testin
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
||||
|
||||
nodeClient := mock.NewMockNodeClient(ctrl)
|
||||
privKey, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
||||
@@ -122,11 +145,12 @@ func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testin
|
||||
}
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
keyManager: km,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
feeRecipientConfig: &validator_service_config.FeeRecipientConfig{
|
||||
ProposerSettings: &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
@@ -151,6 +175,24 @@ func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testin
|
||||
nil,
|
||||
errors.New("fails"),
|
||||
).Return(resp, nil)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
|
||||
}
|
||||
|
||||
@@ -159,6 +201,7 @@ func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
||||
nodeClient := mock.NewMockNodeClient(ctrl)
|
||||
privKey, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
||||
@@ -170,12 +213,13 @@ func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
|
||||
}
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
keyManager: km,
|
||||
genesisTime: 1,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
feeRecipientConfig: &validator_service_config.FeeRecipientConfig{
|
||||
ProposerSettings: &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
@@ -194,6 +238,24 @@ func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
|
||||
resp,
|
||||
nil,
|
||||
)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
||||
@@ -207,6 +269,7 @@ func TestWaitForActivation_Exiting(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
||||
nodeClient := mock.NewMockNodeClient(ctrl)
|
||||
privKey, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
||||
@@ -218,12 +281,13 @@ func TestWaitForActivation_Exiting(t *testing.T) {
|
||||
}
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
keyManager: km,
|
||||
genesisTime: 1,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
feeRecipientConfig: &validator_service_config.FeeRecipientConfig{
|
||||
ProposerSettings: &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
@@ -242,6 +306,24 @@ func TestWaitForActivation_Exiting(t *testing.T) {
|
||||
resp,
|
||||
nil,
|
||||
)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
||||
@@ -261,6 +343,7 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
||||
nodeClient := mock.NewMockNodeClient(ctrl)
|
||||
privKey, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
||||
@@ -273,12 +356,13 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
|
||||
}
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
keyManager: km,
|
||||
genesisTime: 1,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
feeRecipientConfig: &validator_service_config.FeeRecipientConfig{
|
||||
ProposerSettings: &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
@@ -295,8 +379,25 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
|
||||
).Return(clientStream, nil)
|
||||
clientStream.EXPECT().Recv().Return(
|
||||
resp,
|
||||
nil,
|
||||
)
|
||||
nil)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
||||
@@ -328,14 +429,16 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
||||
},
|
||||
}
|
||||
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
||||
nodeClient := mock.NewMockNodeClient(ctrl)
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
keyManager: km,
|
||||
genesisTime: 1,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
feeRecipientConfig: &validator_service_config.FeeRecipientConfig{
|
||||
ProposerSettings: &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
@@ -375,6 +478,24 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
||||
activeResp,
|
||||
nil,
|
||||
)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Times(2).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(&empty.Empty{}, nil)
|
||||
|
||||
go func() {
|
||||
// We add the active key into the keymanager and simulate a key refresh.
|
||||
@@ -415,14 +536,16 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
||||
err = km.RecoverAccountsFromMnemonic(ctx, constant.TestMnemonic, "", 1)
|
||||
require.NoError(t, err)
|
||||
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
||||
nodeClient := mock.NewMockNodeClient(ctrl)
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
keyManager: km,
|
||||
genesisTime: 1,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
feeRecipientConfig: &validator_service_config.FeeRecipientConfig{
|
||||
ProposerSettings: &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
@@ -463,6 +586,24 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
||||
activeResp,
|
||||
nil,
|
||||
)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Times(2).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(&empty.Empty{}, nil)
|
||||
|
||||
channel := make(chan [][fieldparams.BLSPubkeyLength]byte)
|
||||
go func() {
|
||||
@@ -504,19 +645,20 @@ func TestWaitForActivation_RemoteKeymanager(t *testing.T) {
|
||||
t.Run("activated", func(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
hook := logTest.NewGlobal()
|
||||
|
||||
nodeClient := mock.NewMockNodeClient(ctrl)
|
||||
tickerChan := make(chan types.Slot)
|
||||
ticker := &slotutilmock.MockTicker{
|
||||
Channel: tickerChan,
|
||||
}
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
keyManager: &km,
|
||||
ticker: ticker,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
feeRecipientConfig: &validator_service_config.FeeRecipientConfig{
|
||||
ProposerSettings: &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
@@ -539,6 +681,23 @@ func TestWaitForActivation_RemoteKeymanager(t *testing.T) {
|
||||
PublicKeys: [][]byte{inactiveKey[:], activeKey[:]},
|
||||
},
|
||||
).Return(resp, nil /* err */)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Times(2).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(&empty.Empty{}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 2},
|
||||
@@ -577,19 +736,20 @@ func TestWaitForActivation_RemoteKeymanager(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
remoteKm := remotekeymanagermock.NewMock()
|
||||
remoteKm.PublicKeys = [][fieldparams.BLSPubkeyLength]byte{inactiveKey}
|
||||
|
||||
nodeClient := mock.NewMockNodeClient(ctrl)
|
||||
tickerChan := make(chan types.Slot)
|
||||
ticker := &slotutilmock.MockTicker{
|
||||
Channel: tickerChan,
|
||||
}
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
node: nodeClient,
|
||||
keyManager: &remoteKm,
|
||||
ticker: ticker,
|
||||
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
||||
feeRecipientConfig: &validator_service_config.FeeRecipientConfig{
|
||||
ProposerSettings: &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
||||
},
|
||||
},
|
||||
@@ -623,6 +783,24 @@ func TestWaitForActivation_RemoteKeymanager(t *testing.T) {
|
||||
PublicKeys: [][]byte{inactiveKey[:], activeKey[:]},
|
||||
},
|
||||
).Return(resp2, nil /* err */)
|
||||
nodeClient.EXPECT().GetGenesis(
|
||||
gomock.Any(),
|
||||
&emptypb.Empty{},
|
||||
).Times(2).Return(
|
||||
ðpb.Genesis{GenesisTime: timestamppb.Now()}, nil)
|
||||
|
||||
client.EXPECT().DomainData(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(
|
||||
ðpb.DomainResponse{
|
||||
SignatureDomain: make([]byte, 32),
|
||||
},
|
||||
nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(&empty.Empty{}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 2},
|
||||
|
||||
@@ -8,10 +8,14 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//async/event:go_default_library",
|
||||
"//beacon-chain/core/signing:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/eth/service:go_default_library",
|
||||
"//proto/prysm/v1alpha1/validator-client:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"//validator/keymanager:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -5,10 +5,14 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/async/event"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/signing"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpbservice "github.com/prysmaticlabs/prysm/proto/eth/service"
|
||||
validatorpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/validator-client"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager"
|
||||
)
|
||||
|
||||
@@ -33,8 +37,18 @@ func (m *MockKeymanager) FetchValidatingPublicKeys(context.Context) ([][fieldpar
|
||||
}
|
||||
|
||||
// Sign --
|
||||
func (*MockKeymanager) Sign(context.Context, *validatorpb.SignRequest) (bls.Signature, error) {
|
||||
panic("implement me")
|
||||
func (*MockKeymanager) Sign(_ context.Context, s *validatorpb.SignRequest) (bls.Signature, error) {
|
||||
key, err := bls.RandKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st, _ := util.DeterministicGenesisState(nil, 1)
|
||||
e := slots.ToEpoch(st.Slot())
|
||||
byteValue, err := signing.ComputeDomainAndSign(st, e, s.SigningSlot, bytesutil.ToBytes4(s.SignatureDomain), key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bls.SignatureFromBytes(byteValue)
|
||||
}
|
||||
|
||||
// SubscribeAccountChanges --
|
||||
|
||||
@@ -9,6 +9,7 @@ go_test(
|
||||
deps = [
|
||||
"//cmd/validator/flags:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//config/validator/service:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
@@ -72,6 +73,7 @@ go_library(
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
"@in_gopkg_yaml_v2//:go_default_library",
|
||||
"@org_golang_google_protobuf//encoding/protojson:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -54,6 +54,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// ValidatorClient defines an instance of an Ethereum validator that manages
|
||||
@@ -401,7 +402,7 @@ func (c *ValidatorClient) registerValidatorService(cliCtx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
bpc, err := feeRecipientConfig(c.cliCtx)
|
||||
bpc, err := proposerSettings(c.cliCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -425,7 +426,7 @@ func (c *ValidatorClient) registerValidatorService(cliCtx *cli.Context) error {
|
||||
GraffitiStruct: gStruct,
|
||||
LogDutyCountDown: c.cliCtx.Bool(flags.EnableDutyCountDown.Name),
|
||||
Web3SignerConfig: wsc,
|
||||
FeeRecipientConfig: bpc,
|
||||
ProposerSettings: bpc,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize validator service")
|
||||
@@ -470,29 +471,44 @@ func web3SignerConfig(cliCtx *cli.Context) (*remote_web3signer.SetupConfig, erro
|
||||
return web3signerConfig, nil
|
||||
}
|
||||
|
||||
func feeRecipientConfig(cliCtx *cli.Context) (*validatorServiceConfig.FeeRecipientConfig, error) {
|
||||
var fileConfig *validatorServiceConfig.FeeRecipientFileConfig
|
||||
func proposerSettings(cliCtx *cli.Context) (*validatorServiceConfig.ProposerSettings, error) {
|
||||
var fileConfig *validatorServiceConfig.ProposerSettingsPayload
|
||||
//TODO(10809): remove when fully deprecated
|
||||
if cliCtx.IsSet(flags.FeeRecipientConfigFileFlag.Name) && cliCtx.IsSet(flags.FeeRecipientConfigURLFlag.Name) {
|
||||
return nil, fmt.Errorf("cannot specify both --%s and --%s", flags.FeeRecipientConfigFileFlag.Name, flags.FeeRecipientConfigURLFlag.Name)
|
||||
}
|
||||
|
||||
if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) && cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
|
||||
return nil, errors.New("cannot specify both " + flags.ProposerSettingsFlag.Name + " and " + flags.ProposerSettingsURLFlag.Name)
|
||||
}
|
||||
|
||||
// is overridden by file and URL flags
|
||||
if cliCtx.IsSet(flags.SuggestedFeeRecipientFlag.Name) {
|
||||
suggestedFee := cliCtx.String(flags.SuggestedFeeRecipientFlag.Name)
|
||||
fileConfig = &validatorServiceConfig.FeeRecipientFileConfig{
|
||||
fileConfig = &validatorServiceConfig.ProposerSettingsPayload{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validatorServiceConfig.FeeRecipientFileOptions{
|
||||
DefaultConfig: &validatorServiceConfig.ProposerOptionPayload{
|
||||
FeeRecipient: suggestedFee,
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if cliCtx.IsSet(flags.FeeRecipientConfigFileFlag.Name) {
|
||||
if err := unmarshalFromFile(cliCtx.Context, cliCtx.String(flags.FeeRecipientConfigFileFlag.Name), &fileConfig); err != nil {
|
||||
return nil, errors.New(flags.FeeRecipientConfigFileFlag.Usage)
|
||||
}
|
||||
|
||||
if cliCtx.IsSet(flags.FeeRecipientConfigURLFlag.Name) {
|
||||
return nil, errors.New(flags.FeeRecipientConfigURLFlag.Usage)
|
||||
}
|
||||
|
||||
if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) {
|
||||
if err := unmarshalFromFile(cliCtx.Context, cliCtx.String(flags.ProposerSettingsFlag.Name), &fileConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if cliCtx.IsSet(flags.FeeRecipientConfigURLFlag.Name) {
|
||||
if err := unmarshalFromURL(cliCtx.Context, cliCtx.String(flags.FeeRecipientConfigURLFlag.Name), &fileConfig); err != nil {
|
||||
if cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
|
||||
if err := unmarshalFromURL(cliCtx.Context, cliCtx.String(flags.ProposerSettingsURLFlag.Name), &fileConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -502,7 +518,7 @@ func feeRecipientConfig(cliCtx *cli.Context) (*validatorServiceConfig.FeeRecipie
|
||||
return nil, nil
|
||||
}
|
||||
//convert file config to proposer config for internal use
|
||||
frConfig := &validatorServiceConfig.FeeRecipientConfig{}
|
||||
vpSettings := &validatorServiceConfig.ProposerSettings{}
|
||||
|
||||
// default fileConfig is mandatory
|
||||
if fileConfig.DefaultConfig == nil {
|
||||
@@ -515,12 +531,14 @@ func feeRecipientConfig(cliCtx *cli.Context) (*validatorServiceConfig.FeeRecipie
|
||||
if !common.IsHexAddress(fileConfig.DefaultConfig.FeeRecipient) {
|
||||
return nil, errors.New("default fileConfig fee recipient is not a valid eth1 address")
|
||||
}
|
||||
frConfig.DefaultConfig = &validatorServiceConfig.FeeRecipientOptions{
|
||||
|
||||
vpSettings.DefaultConfig = &validatorServiceConfig.ProposerOption{
|
||||
FeeRecipient: common.BytesToAddress(bytes),
|
||||
GasLimit: reviewGasLimit(fileConfig.DefaultConfig.GasLimit),
|
||||
}
|
||||
|
||||
if fileConfig.ProposeConfig != nil {
|
||||
frConfig.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*validatorServiceConfig.FeeRecipientOptions)
|
||||
vpSettings.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*validatorServiceConfig.ProposerOption)
|
||||
for key, option := range fileConfig.ProposeConfig {
|
||||
decodedKey, err := hexutil.Decode(key)
|
||||
if err != nil {
|
||||
@@ -550,13 +568,23 @@ func feeRecipientConfig(cliCtx *cli.Context) (*validatorServiceConfig.FeeRecipie
|
||||
"We recommend using a mixed-case address (checksum) "+
|
||||
"to prevent spelling mistakes in your fee recipient Ethereum address", option.FeeRecipient, checksumAddress.Hex())
|
||||
}
|
||||
frConfig.ProposeConfig[bytesutil.ToBytes48(decodedKey)] = &validatorServiceConfig.FeeRecipientOptions{
|
||||
vpSettings.ProposeConfig[bytesutil.ToBytes48(decodedKey)] = &validatorServiceConfig.ProposerOption{
|
||||
FeeRecipient: checksumAddress,
|
||||
GasLimit: reviewGasLimit(option.GasLimit),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frConfig, nil
|
||||
return vpSettings, nil
|
||||
}
|
||||
|
||||
func reviewGasLimit(gasLimit uint64) uint64 {
|
||||
// sets gas limit to default if not defined or set to 0
|
||||
if gasLimit == 0 {
|
||||
return params.BeaconConfig().DefaultBuilderGasLimit
|
||||
}
|
||||
//TODO(10810): add in warning for ranges
|
||||
return gasLimit
|
||||
}
|
||||
|
||||
func (c *ValidatorClient) registerRPCService(cliCtx *cli.Context) error {
|
||||
@@ -784,27 +812,14 @@ func unmarshalFromFile(ctx context.Context, from string, to interface{}) error {
|
||||
return errors.New("node: nil context passed to unmarshalFromFile")
|
||||
}
|
||||
cleanpath := filepath.Clean(from)
|
||||
fileExtension := filepath.Ext(cleanpath)
|
||||
if fileExtension != ".json" {
|
||||
return errors.Errorf("unsupported file extension %s , (ex. '.json')", fileExtension)
|
||||
b, err := os.ReadFile(cleanpath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to open file")
|
||||
}
|
||||
jsonFile, jsonerr := os.Open(cleanpath)
|
||||
if jsonerr != nil {
|
||||
return errors.Wrap(jsonerr, "failed to open json file")
|
||||
}
|
||||
// defer the closing of our jsonFile so that we can parse it later on
|
||||
defer func(jsonFile *os.File) {
|
||||
err := jsonFile.Close()
|
||||
if err != nil {
|
||||
log.WithError(err).Error("failed to close json file")
|
||||
}
|
||||
}(jsonFile)
|
||||
byteValue, readerror := io.ReadAll(jsonFile)
|
||||
if readerror != nil {
|
||||
return errors.Wrap(readerror, "failed to read json file")
|
||||
}
|
||||
if unmarshalerr := json.Unmarshal(byteValue, &to); unmarshalerr != nil {
|
||||
return errors.Wrap(unmarshalerr, "failed to unmarshal json file")
|
||||
|
||||
if err := yaml.Unmarshal(b, to); err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal yaml file")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/cmd/validator/flags"
|
||||
@@ -190,143 +192,22 @@ func newWeb3SignerCli(t *testing.T, baseUrl string, publicKeysOrURL string) *cli
|
||||
return cli.NewContext(&app, set, nil)
|
||||
}
|
||||
|
||||
type test struct {
|
||||
Foo string `json:"foo"`
|
||||
Bar int `json:"bar"`
|
||||
}
|
||||
|
||||
func TestUnmarshalFromFile(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
type args struct {
|
||||
File string
|
||||
To interface{}
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want interface{}
|
||||
urlResponse string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Happy Path File",
|
||||
args: args{
|
||||
File: "./testdata/test-unmarshal-good.json",
|
||||
To: &test{},
|
||||
},
|
||||
want: &test{
|
||||
Foo: "foo",
|
||||
Bar: 1,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Bad File Path, not json",
|
||||
args: args{
|
||||
File: "./jsontools.go",
|
||||
To: &test{},
|
||||
},
|
||||
want: &test{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Bad File Path",
|
||||
args: args{
|
||||
File: "./testdata/test-unmarshal-bad.json",
|
||||
To: &test{},
|
||||
},
|
||||
want: &test{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Bad File Path, not found",
|
||||
args: args{
|
||||
File: "./test-notfound.json",
|
||||
To: &test{},
|
||||
},
|
||||
want: &test{},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := unmarshalFromFile(ctx, tt.args.File, tt.args.To); (err != nil) != tt.wantErr {
|
||||
t.Errorf(" error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
require.DeepEqual(t, tt.want, tt.args.To)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalFromURL(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, err := fmt.Fprintf(w, `{ "foo": "foo", "bar": 1}`)
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
defer srv.Close()
|
||||
ctx := context.Background()
|
||||
type args struct {
|
||||
URL string
|
||||
To interface{}
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want interface{}
|
||||
urlResponse string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Happy Path URL",
|
||||
args: args{
|
||||
URL: srv.URL,
|
||||
To: &test{},
|
||||
},
|
||||
want: &test{
|
||||
Foo: "foo",
|
||||
Bar: 1,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Bad URL",
|
||||
args: args{
|
||||
URL: "sadjflksdjflksadjflkdj",
|
||||
To: &test{},
|
||||
},
|
||||
want: &test{},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := unmarshalFromURL(ctx, tt.args.URL, tt.args.To); (err != nil) != tt.wantErr {
|
||||
t.Errorf(" error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
require.DeepEqual(t, tt.want, tt.args.To)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFeeRecipientConfig(t *testing.T) {
|
||||
func TestProposerSettings(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
|
||||
type feeRecipientFlag struct {
|
||||
type proposerSettingsFlag struct {
|
||||
dir string
|
||||
url string
|
||||
defaultfee string
|
||||
}
|
||||
|
||||
type args struct {
|
||||
feeRecipientFlagValues *feeRecipientFlag
|
||||
proposerSettingsFlagValues *proposerSettingsFlag
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want func() *validator_service_config.FeeRecipientConfig
|
||||
want func() *validator_service_config.ProposerSettings
|
||||
urlResponse string
|
||||
wantErr string
|
||||
wantLog string
|
||||
@@ -334,23 +215,25 @@ func TestFeeRecipientConfig(t *testing.T) {
|
||||
{
|
||||
name: "Happy Path Config file File, bad checksum",
|
||||
args: args{
|
||||
feeRecipientFlagValues: &feeRecipientFlag{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "./testdata/good-prepare-beacon-proposer-config-badchecksum.json",
|
||||
url: "",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *validator_service_config.FeeRecipientConfig {
|
||||
want: func() *validator_service_config.ProposerSettings {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
return &validator_service_config.FeeRecipientConfig{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.FeeRecipientOptions{
|
||||
return &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
},
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -360,28 +243,31 @@ func TestFeeRecipientConfig(t *testing.T) {
|
||||
{
|
||||
name: "Happy Path Config file File multiple fee recipients",
|
||||
args: args{
|
||||
feeRecipientFlagValues: &feeRecipientFlag{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "./testdata/good-prepare-beacon-proposer-config-multiple.json",
|
||||
url: "",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *validator_service_config.FeeRecipientConfig {
|
||||
want: func() *validator_service_config.ProposerSettings {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
key2, err := hexutil.Decode("0xb057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7b")
|
||||
require.NoError(t, err)
|
||||
return &validator_service_config.FeeRecipientConfig{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.FeeRecipientOptions{
|
||||
return &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
bytesutil.ToBytes48(key2): {
|
||||
FeeRecipient: common.HexToAddress("0x60155530FCE8a85ec7055A5F8b2bE214B3DaeFd4"),
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
},
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -390,23 +276,52 @@ func TestFeeRecipientConfig(t *testing.T) {
|
||||
{
|
||||
name: "Happy Path Config URL File",
|
||||
args: args{
|
||||
feeRecipientFlagValues: &feeRecipientFlag{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "",
|
||||
url: "./testdata/good-prepare-beacon-proposer-config.json",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *validator_service_config.FeeRecipientConfig {
|
||||
want: func() *validator_service_config.ProposerSettings {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
return &validator_service_config.FeeRecipientConfig{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.FeeRecipientOptions{
|
||||
return &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
},
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
}
|
||||
},
|
||||
wantErr: "",
|
||||
},
|
||||
{
|
||||
name: "Happy Path Config YAML file with custom Gas Limit",
|
||||
args: args{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "./testdata/good-prepare-beacon-proposer-config.yaml",
|
||||
url: "",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *validator_service_config.ProposerSettings {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
return &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
GasLimit: uint64(40000000),
|
||||
},
|
||||
},
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
GasLimit: uint64(45000000),
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -415,17 +330,18 @@ func TestFeeRecipientConfig(t *testing.T) {
|
||||
{
|
||||
name: "Happy Path Suggested Fee File",
|
||||
args: args{
|
||||
feeRecipientFlagValues: &feeRecipientFlag{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "",
|
||||
url: "",
|
||||
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89A",
|
||||
},
|
||||
},
|
||||
want: func() *validator_service_config.FeeRecipientConfig {
|
||||
return &validator_service_config.FeeRecipientConfig{
|
||||
want: func() *validator_service_config.ProposerSettings {
|
||||
return &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: nil,
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -434,23 +350,25 @@ func TestFeeRecipientConfig(t *testing.T) {
|
||||
{
|
||||
name: "Suggested Fee does not Override Config",
|
||||
args: args{
|
||||
feeRecipientFlagValues: &feeRecipientFlag{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "./testdata/good-prepare-beacon-proposer-config.json",
|
||||
url: "",
|
||||
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89B",
|
||||
},
|
||||
},
|
||||
want: func() *validator_service_config.FeeRecipientConfig {
|
||||
want: func() *validator_service_config.ProposerSettings {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
return &validator_service_config.FeeRecipientConfig{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.FeeRecipientOptions{
|
||||
return &validator_service_config.ProposerSettings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validator_service_config.ProposerOption{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
},
|
||||
DefaultConfig: &validator_service_config.FeeRecipientOptions{
|
||||
DefaultConfig: &validator_service_config.ProposerOption{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -459,28 +377,42 @@ func TestFeeRecipientConfig(t *testing.T) {
|
||||
{
|
||||
name: "No flags set means empty config",
|
||||
args: args{
|
||||
feeRecipientFlagValues: &feeRecipientFlag{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "",
|
||||
url: "",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *validator_service_config.FeeRecipientConfig {
|
||||
want: func() *validator_service_config.ProposerSettings {
|
||||
return nil
|
||||
},
|
||||
wantErr: "",
|
||||
},
|
||||
{
|
||||
name: "Bad File Path",
|
||||
args: args{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "./testdata/bad-prepare-beacon-proposer-config.json",
|
||||
url: "",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *validator_service_config.ProposerSettings {
|
||||
return nil
|
||||
},
|
||||
wantErr: "failed to unmarshal yaml file",
|
||||
},
|
||||
{
|
||||
name: "Both URL and Dir flags used resulting in error",
|
||||
args: args{
|
||||
feeRecipientFlagValues: &feeRecipientFlag{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "./testdata/good-prepare-beacon-proposer-config.json",
|
||||
url: "./testdata/good-prepare-beacon-proposer-config.json",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *validator_service_config.FeeRecipientConfig {
|
||||
return &validator_service_config.FeeRecipientConfig{}
|
||||
want: func() *validator_service_config.ProposerSettings {
|
||||
return &validator_service_config.ProposerSettings{}
|
||||
},
|
||||
wantErr: "cannot specify both",
|
||||
},
|
||||
@@ -489,12 +421,12 @@ func TestFeeRecipientConfig(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
if tt.args.feeRecipientFlagValues.dir != "" {
|
||||
set.String(flags.FeeRecipientConfigFileFlag.Name, tt.args.feeRecipientFlagValues.dir, "")
|
||||
require.NoError(t, set.Set(flags.FeeRecipientConfigFileFlag.Name, tt.args.feeRecipientFlagValues.dir))
|
||||
if tt.args.proposerSettingsFlagValues.dir != "" {
|
||||
set.String(flags.ProposerSettingsFlag.Name, tt.args.proposerSettingsFlagValues.dir, "")
|
||||
require.NoError(t, set.Set(flags.ProposerSettingsFlag.Name, tt.args.proposerSettingsFlagValues.dir))
|
||||
}
|
||||
if tt.args.feeRecipientFlagValues.url != "" {
|
||||
content, err := os.ReadFile(tt.args.feeRecipientFlagValues.url)
|
||||
if tt.args.proposerSettingsFlagValues.url != "" {
|
||||
content, err := os.ReadFile(tt.args.proposerSettingsFlagValues.url)
|
||||
require.NoError(t, err)
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
@@ -504,15 +436,15 @@ func TestFeeRecipientConfig(t *testing.T) {
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
set.String(flags.FeeRecipientConfigURLFlag.Name, tt.args.feeRecipientFlagValues.url, "")
|
||||
require.NoError(t, set.Set(flags.FeeRecipientConfigURLFlag.Name, srv.URL))
|
||||
set.String(flags.ProposerSettingsURLFlag.Name, tt.args.proposerSettingsFlagValues.url, "")
|
||||
require.NoError(t, set.Set(flags.ProposerSettingsURLFlag.Name, srv.URL))
|
||||
}
|
||||
if tt.args.feeRecipientFlagValues.defaultfee != "" {
|
||||
set.String(flags.SuggestedFeeRecipientFlag.Name, tt.args.feeRecipientFlagValues.defaultfee, "")
|
||||
require.NoError(t, set.Set(flags.SuggestedFeeRecipientFlag.Name, tt.args.feeRecipientFlagValues.defaultfee))
|
||||
if tt.args.proposerSettingsFlagValues.defaultfee != "" {
|
||||
set.String(flags.SuggestedFeeRecipientFlag.Name, tt.args.proposerSettingsFlagValues.defaultfee, "")
|
||||
require.NoError(t, set.Set(flags.SuggestedFeeRecipientFlag.Name, tt.args.proposerSettingsFlagValues.defaultfee))
|
||||
}
|
||||
cliCtx := cli.NewContext(&app, set, nil)
|
||||
got, err := feeRecipientConfig(cliCtx)
|
||||
got, err := proposerSettings(cliCtx)
|
||||
if tt.wantErr != "" {
|
||||
require.ErrorContains(t, tt.wantErr, err)
|
||||
return
|
||||
|
||||
4
validator/node/testdata/bad-prepare-beacon-proposer-config.json
vendored
Normal file
4
validator/node/testdata/bad-prepare-beacon-proposer-config.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"proposer_config": {
|
||||
"0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a": {
|
||||
|
||||
8
validator/node/testdata/good-prepare-beacon-proposer-config.yaml
vendored
Normal file
8
validator/node/testdata/good-prepare-beacon-proposer-config.yaml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
proposer_config:
|
||||
'0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a':
|
||||
fee_recipient: '0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3'
|
||||
gas_limit: 40000000
|
||||
default_config:
|
||||
fee_recipient: '0x6e35733c5af9B61374A128e6F85f553aF09ff89A'
|
||||
gas_limit: 45000000
|
||||
@@ -1,2 +0,0 @@
|
||||
{
|
||||
"foo": "bar"
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"foo": "foo",
|
||||
"bar": 1
|
||||
}
|
||||
Reference in New Issue
Block a user