mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-21 19:20:38 +00:00
Keymanager APIs - get,post,delete graffiti (#13474)
* wip * adding set and delete graffiti * fixing mock * fixing mock linting and putting in scaffolds for unit tests * adding some tests * gaz * adding tests * updating missing unit test * fixing unit test * Update validator/rpc/handlers_keymanager.go Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com> * Update validator/client/propose.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/rpc/handlers_keymanager.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/client/propose.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * radek's feedback * fixing tests * using wrapper for graffiti * fixing linting * wip * fixing setting proposer settings * more partial fixes to tests * gaz * fixing tests and setting logic * changing keymanager * fixing tests and making graffiti optional in the proposer file * remove unneeded lines * reverting unintended changes * Update validator/client/propose.go Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com> * addressing feedback * removing uneeded line * fixing bad merge resolution * gofmt * gaz --------- Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com> Co-authored-by: Radosław Kapka <rkapka@wp.pl> Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com>
This commit is contained in:
parent
fda4589251
commit
7f931bf65b
@ -49,6 +49,82 @@ func TestProposerSettingsLoader(t *testing.T) {
|
||||
validatorRegistrationEnabled bool
|
||||
skipDBSavedCheck bool
|
||||
}{
|
||||
{
|
||||
name: "graffiti in db without fee recipient",
|
||||
args: args{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "",
|
||||
url: "",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *proposer.Settings {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
return &proposer.Settings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "specific graffiti",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
withdb: func(db iface.ValidatorDB) error {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
settings := &proposer.Settings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "specific graffiti",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return db.SaveProposerSettings(context.Background(), settings)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "graffiti from file",
|
||||
args: args{
|
||||
proposerSettingsFlagValues: &proposerSettingsFlag{
|
||||
dir: "./testdata/good-graffiti-settings.json",
|
||||
url: "",
|
||||
defaultfee: "",
|
||||
},
|
||||
},
|
||||
want: func() *proposer.Settings {
|
||||
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
|
||||
require.NoError(t, err)
|
||||
return &proposer.Settings{
|
||||
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{
|
||||
bytesutil.ToBytes48(key1): {
|
||||
FeeRecipientConfig: &proposer.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
|
||||
},
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "some graffiti",
|
||||
},
|
||||
BuilderConfig: &proposer.BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(30000000),
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultConfig: &proposer.Option{
|
||||
FeeRecipientConfig: &proposer.FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
|
||||
},
|
||||
BuilderConfig: &proposer.BuilderConfig{
|
||||
Enabled: true,
|
||||
GasLimit: validator.Uint64(40000000),
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "db settings override file settings if file default config is missing",
|
||||
args: args{
|
||||
@ -875,6 +951,8 @@ func TestProposerSettingsLoader(t *testing.T) {
|
||||
if tt.wantErr != "" {
|
||||
require.ErrorContains(t, tt.wantErr, err)
|
||||
return
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
if tt.wantLog != "" {
|
||||
assert.LogsContain(t, hook,
|
||||
|
19
config/proposer/loader/testdata/good-graffiti-settings.json
vendored
Normal file
19
config/proposer/loader/testdata/good-graffiti-settings.json
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"proposer_config": {
|
||||
"0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a": {
|
||||
"fee_recipient": "0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3",
|
||||
"graffiti": "some graffiti",
|
||||
"builder": {
|
||||
"enabled": true,
|
||||
"gas_limit": "30000000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default_config": {
|
||||
"fee_recipient": "0x6e35733c5af9B61374A128e6F85f553aF09ff89A",
|
||||
"builder": {
|
||||
"enabled": true,
|
||||
"gas_limit": 40000000
|
||||
}
|
||||
}
|
||||
}
|
@ -19,9 +19,6 @@ func SettingFromConsensus(ps *validatorpb.ProposerSettingsPayload) (*Settings, e
|
||||
if ps.ProposerConfig != nil && len(ps.ProposerConfig) != 0 {
|
||||
settings.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*Option)
|
||||
for key, optionPayload := range ps.ProposerConfig {
|
||||
if optionPayload.FeeRecipient == "" {
|
||||
continue
|
||||
}
|
||||
decodedKey, err := hexutil.Decode(key)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("cannot decode public key %s", key))
|
||||
@ -29,13 +26,15 @@ func SettingFromConsensus(ps *validatorpb.ProposerSettingsPayload) (*Settings, e
|
||||
if len(decodedKey) != fieldparams.BLSPubkeyLength {
|
||||
return nil, fmt.Errorf("%v is not a bls public key", key)
|
||||
}
|
||||
if err := verifyOption(key, optionPayload); err != nil {
|
||||
return nil, err
|
||||
p := &Option{}
|
||||
if optionPayload.Graffiti != nil {
|
||||
p.GraffitiConfig = &GraffitiConfig{*optionPayload.Graffiti}
|
||||
}
|
||||
p := &Option{
|
||||
FeeRecipientConfig: &FeeRecipientConfig{
|
||||
FeeRecipient: common.HexToAddress(optionPayload.FeeRecipient),
|
||||
},
|
||||
if optionPayload.FeeRecipient != "" {
|
||||
if err := verifyOption(key, optionPayload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.FeeRecipientConfig = &FeeRecipientConfig{FeeRecipient: common.HexToAddress(optionPayload.FeeRecipient)}
|
||||
}
|
||||
if optionPayload.Builder != nil {
|
||||
p.BuilderConfig = BuilderConfigFromConsensus(optionPayload.Builder)
|
||||
@ -141,10 +140,16 @@ type FeeRecipientConfig struct {
|
||||
FeeRecipient common.Address
|
||||
}
|
||||
|
||||
// GraffitiConfig is a prysm internal representation to see if the graffiti was set.
|
||||
type GraffitiConfig struct {
|
||||
Graffiti string
|
||||
}
|
||||
|
||||
// Option is a Prysm internal representation of the ProposerOptionPayload on the validator client in bytes format instead of hex.
|
||||
type Option struct {
|
||||
FeeRecipientConfig *FeeRecipientConfig
|
||||
BuilderConfig *BuilderConfig
|
||||
GraffitiConfig *GraffitiConfig
|
||||
}
|
||||
|
||||
// Clone creates a deep copy of proposer option
|
||||
@ -159,6 +164,9 @@ func (po *Option) Clone() *Option {
|
||||
if po.BuilderConfig != nil {
|
||||
p.BuilderConfig = po.BuilderConfig.Clone()
|
||||
}
|
||||
if po.GraffitiConfig != nil {
|
||||
p.GraffitiConfig = po.GraffitiConfig.Clone()
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
@ -173,6 +181,9 @@ func (po *Option) ToConsensus() *validatorpb.ProposerOptionPayload {
|
||||
if po.BuilderConfig != nil {
|
||||
p.Builder = po.BuilderConfig.ToConsensus()
|
||||
}
|
||||
if po.GraffitiConfig != nil {
|
||||
p.Graffiti = &po.GraffitiConfig.Graffiti
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
@ -222,6 +233,14 @@ func (bc *BuilderConfig) Clone() *BuilderConfig {
|
||||
return c
|
||||
}
|
||||
|
||||
// Clone creates a deep copy of graffiti config
|
||||
func (gc *GraffitiConfig) Clone() *GraffitiConfig {
|
||||
if gc == nil {
|
||||
return nil
|
||||
}
|
||||
return &GraffitiConfig{gc.Graffiti}
|
||||
}
|
||||
|
||||
// ToConsensus converts Builder Config to the protobuf object
|
||||
func (bc *BuilderConfig) ToConsensus() *validatorpb.BuilderConfig {
|
||||
if bc == nil {
|
||||
|
@ -76,26 +76,14 @@ func Test_Proposer_Setting_Cloning(t *testing.T) {
|
||||
require.Equal(t, option.FeeRecipientConfig.FeeRecipient.Hex(), potion.FeeRecipient)
|
||||
require.Equal(t, settings.DefaultConfig.FeeRecipientConfig.FeeRecipient.Hex(), payload.DefaultConfig.FeeRecipient)
|
||||
require.Equal(t, settings.DefaultConfig.BuilderConfig.Enabled, payload.DefaultConfig.Builder.Enabled)
|
||||
potion.FeeRecipient = ""
|
||||
potion.FeeRecipient = fee
|
||||
newSettings, err := SettingFromConsensus(payload)
|
||||
require.NoError(t, err)
|
||||
|
||||
// when converting to settings if a fee recipient is empty string then it will be skipped
|
||||
noption, ok := newSettings.ProposeConfig[bytesutil.ToBytes48(key1)]
|
||||
require.Equal(t, false, ok)
|
||||
require.Equal(t, true, noption == nil)
|
||||
require.DeepEqual(t, newSettings.DefaultConfig, settings.DefaultConfig)
|
||||
|
||||
// if fee recipient is set it will not skip
|
||||
potion.FeeRecipient = fee
|
||||
newSettings, err = SettingFromConsensus(payload)
|
||||
require.NoError(t, err)
|
||||
noption, ok = newSettings.ProposeConfig[bytesutil.ToBytes48(key1)]
|
||||
require.Equal(t, true, ok)
|
||||
require.Equal(t, option.FeeRecipientConfig.FeeRecipient.Hex(), noption.FeeRecipientConfig.FeeRecipient.Hex())
|
||||
require.Equal(t, option.BuilderConfig.GasLimit, option.BuilderConfig.GasLimit)
|
||||
require.Equal(t, option.BuilderConfig.Enabled, option.BuilderConfig.Enabled)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ proto_library(
|
||||
"@com_google_protobuf//:any_proto",
|
||||
"@com_google_protobuf//:descriptor_proto",
|
||||
"@com_google_protobuf//:empty_proto",
|
||||
"@com_google_protobuf//:wrappers_proto",
|
||||
"@com_google_protobuf//:timestamp_proto",
|
||||
"@googleapis//google/api:annotations_proto",
|
||||
],
|
||||
@ -53,6 +54,7 @@ go_proto_library(
|
||||
"@googleapis//google/api:annotations_go_proto",
|
||||
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
|
||||
"@io_bazel_rules_go//proto/wkt:empty_go_proto",
|
||||
"@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
|
||||
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
|
||||
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
|
||||
"@org_golang_google_protobuf//runtime/protoimpl:go_default_library",
|
||||
@ -78,6 +80,7 @@ go_proto_library(
|
||||
"@googleapis//google/api:annotations_go_proto",
|
||||
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
|
||||
"@io_bazel_rules_go//proto/wkt:empty_go_proto",
|
||||
"@io_bazel_rules_go//proto/wkt:wrappers_go_proto",
|
||||
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
|
||||
],
|
||||
)
|
||||
|
107
proto/prysm/v1alpha1/validator-client/keymanager.pb.go
generated
107
proto/prysm/v1alpha1/validator-client/keymanager.pb.go
generated
@ -16,6 +16,7 @@ import (
|
||||
v1alpha1 "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
_ "google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -462,6 +463,7 @@ type ProposerOptionPayload struct {
|
||||
|
||||
FeeRecipient string `protobuf:"bytes,1,opt,name=fee_recipient,json=feeRecipient,proto3" json:"fee_recipient,omitempty"`
|
||||
Builder *BuilderConfig `protobuf:"bytes,2,opt,name=builder,proto3" json:"builder,omitempty"`
|
||||
Graffiti *string `protobuf:"bytes,3,opt,name=graffiti,proto3,oneof" json:"graffiti,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ProposerOptionPayload) Reset() {
|
||||
@ -510,6 +512,13 @@ func (x *ProposerOptionPayload) GetBuilder() *BuilderConfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ProposerOptionPayload) GetGraffiti() string {
|
||||
if x != nil && x.Graffiti != nil {
|
||||
return *x.Graffiti
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type BuilderConfig struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -636,7 +645,9 @@ var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDesc = []byte
|
||||
0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x6b, 0x65, 0x79, 0x6d, 0x61, 0x6e, 0x61, 0x67,
|
||||
0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
|
||||
0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65,
|
||||
0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
|
||||
0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79,
|
||||
0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x61, 0x74, 0x74, 0x65,
|
||||
@ -771,7 +782,7 @@ var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDesc = []byte
|
||||
0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d,
|
||||
0x0a, 0x09, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a,
|
||||
0x06, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49,
|
||||
0x4c, 0x45, 0x44, 0x10, 0x03, 0x22, 0x85, 0x01, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73,
|
||||
0x4c, 0x45, 0x44, 0x10, 0x03, 0x22, 0xb3, 0x01, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73,
|
||||
0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12,
|
||||
0x23, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70,
|
||||
@ -779,54 +790,57 @@ var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDesc = []byte
|
||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
|
||||
0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x22, 0xa6, 0x01,
|
||||
0x0a, 0x0d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x63, 0x0a, 0x09, 0x67, 0x61, 0x73,
|
||||
0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5,
|
||||
0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79,
|
||||
0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d,
|
||||
0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79,
|
||||
0x70, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x69,
|
||||
0x6e, 0x74, 0x36, 0x34, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06,
|
||||
0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x22, 0xe7, 0x02, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x70, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a,
|
||||
0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x00, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x88, 0x01, 0x01, 0x42, 0x0b,
|
||||
0x0a, 0x09, 0x5f, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x22, 0xa6, 0x01, 0x0a, 0x0d,
|
||||
0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a,
|
||||
0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
|
||||
0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x63, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c,
|
||||
0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42,
|
||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d,
|
||||
0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76,
|
||||
0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65,
|
||||
0x73, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x69, 0x6e, 0x74,
|
||||
0x36, 0x34, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65,
|
||||
0x6c, 0x61, 0x79, 0x73, 0x22, 0xe7, 0x02, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65,
|
||||
0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x12, 0x74, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x65, 0x74, 0x68, 0x65,
|
||||
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61,
|
||||
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f,
|
||||
0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f,
|
||||
0x61, 0x64, 0x12, 0x74, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x65, 0x74,
|
||||
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72,
|
||||
0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f,
|
||||
0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x61, 0x79,
|
||||
0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73,
|
||||
0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5c, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61,
|
||||
0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76,
|
||||
0x32, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x78, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73,
|
||||
0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
|
||||
0x4b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35,
|
||||
0x61, 0x64, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5c, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c,
|
||||
0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35,
|
||||
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
|
||||
0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e,
|
||||
0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61,
|
||||
0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
|
||||
0x42, 0xce, 0x01, 0x0a, 0x22, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
|
||||
0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x42, 0x0f, 0x4b, 0x65, 0x79, 0x6d, 0x61, 0x6e, 0x61,
|
||||
0x67, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x53, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63,
|
||||
0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
|
||||
0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2d, 0x63, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x3b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x70, 0x62, 0xaa,
|
||||
0x02, 0x1e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64,
|
||||
0x61, 0x74, 0x6f, 0x72, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x56, 0x32,
|
||||
0xca, 0x02, 0x1e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x56, 0x61, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x6f, 0x72, 0x5c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5c, 0x56,
|
||||
0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x1a, 0x78, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4b, 0x0a,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65,
|
||||
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
|
||||
0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72,
|
||||
0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c,
|
||||
0x6f, 0x61, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0xce,
|
||||
0x01, 0x0a, 0x22, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
|
||||
0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x73, 0x2e, 0x76, 0x32, 0x42, 0x0f, 0x4b, 0x65, 0x79, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
|
||||
0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61,
|
||||
0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
|
||||
0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x3b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x70, 0x62, 0xaa, 0x02, 0x1e,
|
||||
0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
|
||||
0x6f, 0x72, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x56, 0x32, 0xca, 0x02,
|
||||
0x1e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61,
|
||||
0x74, 0x6f, 0x72, 0x5c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5c, 0x56, 0x32, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@ -979,6 +993,7 @@ func file_proto_prysm_v1alpha1_validator_client_keymanager_proto_init() {
|
||||
(*SignRequest_BlockDeneb)(nil),
|
||||
(*SignRequest_BlindedBlockDeneb)(nil),
|
||||
}
|
||||
file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[2].OneofWrappers = []interface{}{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
|
@ -1,6 +1,7 @@
|
||||
syntax = "proto3";
|
||||
package ethereum.validator.accounts.v2;
|
||||
|
||||
import "google/protobuf/wrappers.proto";
|
||||
import "proto/eth/ext/options.proto";
|
||||
import "proto/prysm/v1alpha1/attestation.proto";
|
||||
import "proto/prysm/v1alpha1/beacon_block.proto";
|
||||
@ -87,6 +88,7 @@ message SignResponse {
|
||||
message ProposerOptionPayload {
|
||||
string fee_recipient = 1;
|
||||
BuilderConfig builder = 2;
|
||||
optional string graffiti = 3;
|
||||
}
|
||||
|
||||
// BuilderConfig is a property of ProposerOptionPayload
|
||||
|
@ -12,6 +12,7 @@ go_library(
|
||||
deps = [
|
||||
"//api/client/beacon:go_default_library",
|
||||
"//api/client/event:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/proposer:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/event"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/proposer"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
@ -91,6 +92,7 @@ func (_ *Wallet) InitializeKeymanager(_ context.Context, _ iface.InitKeymanagerC
|
||||
|
||||
type Validator struct {
|
||||
Km keymanager.IKeymanager
|
||||
graffiti string
|
||||
proposerSettings *proposer.Settings
|
||||
}
|
||||
|
||||
@ -215,6 +217,23 @@ func (m *Validator) SetProposerSettings(_ context.Context, settings *proposer.Se
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGraffiti for mocking
|
||||
func (m *Validator) GetGraffiti(_ context.Context, _ [fieldparams.BLSPubkeyLength]byte) ([]byte, error) {
|
||||
return []byte(m.graffiti), nil
|
||||
}
|
||||
|
||||
// SetGraffiti for mocking
|
||||
func (m *Validator) SetGraffiti(_ context.Context, _ [fieldparams.BLSPubkeyLength]byte, graffiti []byte) error {
|
||||
m.graffiti = string(graffiti)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteGraffiti for mocking
|
||||
func (m *Validator) DeleteGraffiti(_ context.Context, _ [fieldparams.BLSPubkeyLength]byte) error {
|
||||
m.graffiti = ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*Validator) StartEventStream(_ context.Context, _ []string, _ chan<- *event.Event) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
@ -60,10 +60,13 @@ type Validator interface {
|
||||
PushProposerSettings(ctx context.Context, km keymanager.IKeymanager, slot primitives.Slot, deadline time.Time) error
|
||||
SignValidatorRegistrationRequest(ctx context.Context, signer SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error)
|
||||
StartEventStream(ctx context.Context, topics []string, eventsChan chan<- *event.Event)
|
||||
EventStreamIsRunning() bool
|
||||
ProcessEvent(event *event.Event)
|
||||
ProposerSettings() *proposer.Settings
|
||||
SetProposerSettings(context.Context, *proposer.Settings) error
|
||||
EventStreamIsRunning() bool
|
||||
GetGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte) ([]byte, error)
|
||||
SetGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte, graffiti []byte) error
|
||||
DeleteGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte) error
|
||||
HealthTracker() *beacon.NodeHealthTracker
|
||||
}
|
||||
|
||||
|
@ -6,12 +6,14 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/protobuf/ptypes/timestamp"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/async"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/proposer"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
@ -67,7 +69,7 @@ func (v *validator) ProposeBlock(ctx context.Context, slot primitives.Slot, pubK
|
||||
return
|
||||
}
|
||||
|
||||
g, err := v.getGraffiti(ctx, pubKey)
|
||||
g, err := v.GetGraffiti(ctx, pubKey)
|
||||
if err != nil {
|
||||
// Graffiti is not a critical enough to fail block production and cause
|
||||
// validator to miss block reward. When failed, validator should continue
|
||||
@ -385,9 +387,25 @@ func signVoluntaryExit(
|
||||
return sig.Marshal(), nil
|
||||
}
|
||||
|
||||
// Gets the graffiti from cli or file for the validator public key.
|
||||
func (v *validator) getGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte) ([]byte, error) {
|
||||
// When specified, default graffiti from the command line takes the first priority.
|
||||
// GetGraffiti gets the graffiti from cli or file for the validator public key.
|
||||
func (v *validator) GetGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte) ([]byte, error) {
|
||||
if v.proposerSettings != nil {
|
||||
// Check proposer settings for specific key first
|
||||
if v.proposerSettings.ProposeConfig != nil {
|
||||
option, ok := v.proposerSettings.ProposeConfig[pubKey]
|
||||
if ok && option.GraffitiConfig != nil {
|
||||
return []byte(option.GraffitiConfig.Graffiti), nil
|
||||
}
|
||||
}
|
||||
// Check proposer settings for default settings second
|
||||
if v.proposerSettings.DefaultConfig != nil {
|
||||
if v.proposerSettings.DefaultConfig.GraffitiConfig != nil {
|
||||
return []byte(v.proposerSettings.DefaultConfig.GraffitiConfig.Graffiti), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When specified, use default graffiti from the command line.
|
||||
if len(v.graffiti) != 0 {
|
||||
return bytesutil.PadTo(v.graffiti, 32), nil
|
||||
}
|
||||
@ -396,7 +414,7 @@ func (v *validator) getGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubk
|
||||
return nil, errors.New("graffitiStruct can't be nil")
|
||||
}
|
||||
|
||||
// When specified, individual validator specified graffiti takes the second priority.
|
||||
// When specified, individual validator specified graffiti takes the third priority.
|
||||
idx, err := v.validatorClient.ValidatorIndex(ctx, ðpb.ValidatorIndexRequest{PublicKey: pubKey[:]})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -406,7 +424,7 @@ func (v *validator) getGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubk
|
||||
return bytesutil.PadTo([]byte(g), 32), nil
|
||||
}
|
||||
|
||||
// When specified, a graffiti from the ordered list in the file take third priority.
|
||||
// When specified, a graffiti from the ordered list in the file take fourth priority.
|
||||
if v.graffitiOrderedIndex < uint64(len(v.graffitiStruct.Ordered)) {
|
||||
graffiti := v.graffitiStruct.Ordered[v.graffitiOrderedIndex]
|
||||
v.graffitiOrderedIndex = v.graffitiOrderedIndex + 1
|
||||
@ -417,7 +435,7 @@ func (v *validator) getGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubk
|
||||
return bytesutil.PadTo([]byte(graffiti), 32), nil
|
||||
}
|
||||
|
||||
// When specified, a graffiti from the random list in the file take fourth priority.
|
||||
// When specified, a graffiti from the random list in the file take Fifth priority.
|
||||
if len(v.graffitiStruct.Random) != 0 {
|
||||
r := rand.NewGenerator()
|
||||
r.Seed(time.Now().Unix())
|
||||
@ -433,6 +451,44 @@ func (v *validator) getGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubk
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
func (v *validator) SetGraffiti(ctx context.Context, pubkey [fieldparams.BLSPubkeyLength]byte, graffiti []byte) error {
|
||||
if graffiti == nil {
|
||||
return nil
|
||||
}
|
||||
settings := &proposer.Settings{}
|
||||
if v.proposerSettings != nil {
|
||||
settings = v.proposerSettings.Clone()
|
||||
}
|
||||
if settings.ProposeConfig == nil {
|
||||
settings.ProposeConfig = map[[48]byte]*proposer.Option{pubkey: {GraffitiConfig: &proposer.GraffitiConfig{Graffiti: string(graffiti)}}}
|
||||
return v.SetProposerSettings(ctx, settings)
|
||||
}
|
||||
option, ok := settings.ProposeConfig[pubkey]
|
||||
if !ok || option == nil {
|
||||
settings.ProposeConfig[pubkey] = &proposer.Option{GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: string(graffiti),
|
||||
}}
|
||||
} else {
|
||||
option.GraffitiConfig = &proposer.GraffitiConfig{
|
||||
Graffiti: string(graffiti),
|
||||
}
|
||||
}
|
||||
return v.SetProposerSettings(ctx, settings) // save the proposer settings
|
||||
}
|
||||
|
||||
func (v *validator) DeleteGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte) error {
|
||||
if v.proposerSettings == nil || v.proposerSettings.ProposeConfig == nil {
|
||||
return errors.New("attempted to delete graffiti without proposer settings, graffiti will default to flag options")
|
||||
}
|
||||
ps := v.proposerSettings.Clone()
|
||||
option, ok := ps.ProposeConfig[pubKey]
|
||||
if !ok || option == nil {
|
||||
return fmt.Errorf("graffiti not found in proposer settings for pubkey:%s", hexutil.Encode(pubKey[:]))
|
||||
}
|
||||
option.GraffitiConfig = nil
|
||||
return v.SetProposerSettings(ctx, ps) // save the proposer settings
|
||||
}
|
||||
|
||||
func blockLogFields(pubKey [fieldparams.BLSPubkeyLength]byte, blk interfaces.ReadOnlyBeaconBlock, sig []byte) logrus.Fields {
|
||||
fields := logrus.Fields{
|
||||
"proposerPublicKey": fmt.Sprintf("%#x", pubKey),
|
||||
|
@ -8,10 +8,12 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing"
|
||||
lruwrpr "github.com/prysmaticlabs/prysm/v5/cache/lru"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/proposer"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
blocktest "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks/testing"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
@ -955,6 +957,13 @@ func TestGetGraffiti_Ok(t *testing.T) {
|
||||
validatorClient: validatormock.NewMockValidatorClient(ctrl),
|
||||
}
|
||||
pubKey := [fieldparams.BLSPubkeyLength]byte{'a'}
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
|
||||
config[pubKey] = &proposer.Option{
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "specific graffiti",
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
v *validator
|
||||
@ -1014,16 +1023,52 @@ func TestGetGraffiti_Ok(t *testing.T) {
|
||||
},
|
||||
want: []byte{},
|
||||
},
|
||||
{name: "graffiti from proposer settings for specific pubkey",
|
||||
v: &validator{
|
||||
validatorClient: m.validatorClient,
|
||||
proposerSettings: &proposer.Settings{
|
||||
ProposeConfig: config,
|
||||
},
|
||||
},
|
||||
want: []byte("specific graffiti"),
|
||||
},
|
||||
{name: "graffiti from proposer settings default config",
|
||||
v: &validator{
|
||||
validatorClient: m.validatorClient,
|
||||
proposerSettings: &proposer.Settings{
|
||||
DefaultConfig: &proposer.Option{
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "default graffiti",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []byte("default graffiti"),
|
||||
},
|
||||
{name: "graffiti from proposer settings , specific pubkey overrides default config",
|
||||
v: &validator{
|
||||
validatorClient: m.validatorClient,
|
||||
proposerSettings: &proposer.Settings{
|
||||
ProposeConfig: config,
|
||||
DefaultConfig: &proposer.Option{
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "default graffiti",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []byte("specific graffiti"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if !strings.Contains(tt.name, "use default cli graffiti") {
|
||||
if !strings.Contains(tt.name, "use default cli graffiti") && tt.v.proposerSettings == nil {
|
||||
m.validatorClient.EXPECT().
|
||||
ValidatorIndex(gomock.Any(), ðpb.ValidatorIndexRequest{PublicKey: pubKey[:]}).
|
||||
Return(ðpb.ValidatorIndexResponse{Index: 2}, nil)
|
||||
}
|
||||
got, err := tt.v.getGraffiti(context.Background(), pubKey)
|
||||
got, err := tt.v.GetGraffiti(context.Background(), pubKey)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, tt.want, got)
|
||||
})
|
||||
@ -1053,10 +1098,165 @@ func TestGetGraffitiOrdered_Ok(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, want := range [][]byte{bytesutil.PadTo([]byte{'a'}, 32), bytesutil.PadTo([]byte{'b'}, 32), bytesutil.PadTo([]byte{'c'}, 32), bytesutil.PadTo([]byte{'d'}, 32), bytesutil.PadTo([]byte{'d'}, 32)} {
|
||||
got, err := v.getGraffiti(context.Background(), pubKey)
|
||||
got, err := v.GetGraffiti(context.Background(), pubKey)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_validator_DeleteGraffiti(t *testing.T) {
|
||||
pubKey := [fieldparams.BLSPubkeyLength]byte{'a'}
|
||||
tests := []struct {
|
||||
name string
|
||||
proposerSettings *proposer.Settings
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "delete existing graffiti ok",
|
||||
proposerSettings: &proposer.Settings{
|
||||
ProposeConfig: func() map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option {
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
|
||||
config[pubKey] = &proposer.Option{
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "specific graffiti",
|
||||
},
|
||||
}
|
||||
return config
|
||||
}(),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "delete with proposer settings but only default configs",
|
||||
proposerSettings: &proposer.Settings{
|
||||
DefaultConfig: &proposer.Option{
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "default graffiti",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: "attempted to delete graffiti without proposer settings, graffiti will default to flag options",
|
||||
},
|
||||
{
|
||||
name: "delete with proposer settings but without the specific public key setting",
|
||||
proposerSettings: &proposer.Settings{
|
||||
ProposeConfig: func() map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option {
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
|
||||
pk := make([]byte, fieldparams.BLSPubkeyLength)
|
||||
config[bytesutil.ToBytes48(pk)] = &proposer.Option{
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "specific graffiti",
|
||||
},
|
||||
}
|
||||
return config
|
||||
}(),
|
||||
},
|
||||
wantErr: fmt.Sprintf("graffiti not found in proposer settings for pubkey:%s", hexutil.Encode(pubKey[:])),
|
||||
},
|
||||
{
|
||||
name: "delete without proposer settings",
|
||||
wantErr: "attempted to delete graffiti without proposer settings, graffiti will default to flag options",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
v := &validator{
|
||||
db: testing2.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{pubKey}, false),
|
||||
proposerSettings: tt.proposerSettings,
|
||||
}
|
||||
err := v.DeleteGraffiti(context.Background(), pubKey)
|
||||
if tt.wantErr != "" {
|
||||
require.ErrorContains(t, tt.wantErr, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, v.proposerSettings.ProposeConfig[pubKey].GraffitiConfig == nil, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_validator_SetGraffiti(t *testing.T) {
|
||||
pubKey := [fieldparams.BLSPubkeyLength]byte{'a'}
|
||||
tests := []struct {
|
||||
name string
|
||||
graffiti string
|
||||
proposerSettings *proposer.Settings
|
||||
wantProposerSettings *proposer.Settings
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "setting existing graffiti ok",
|
||||
graffiti: "new graffiti",
|
||||
proposerSettings: &proposer.Settings{
|
||||
ProposeConfig: func() map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option {
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
|
||||
config[pubKey] = &proposer.Option{
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "specific graffiti",
|
||||
},
|
||||
}
|
||||
return config
|
||||
}(),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set with proposer settings but only default configs",
|
||||
proposerSettings: &proposer.Settings{
|
||||
DefaultConfig: &proposer.Option{
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "default graffiti",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set with proposer settings but without the specific public key setting",
|
||||
proposerSettings: &proposer.Settings{
|
||||
ProposeConfig: func() map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option {
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
|
||||
pk := make([]byte, fieldparams.BLSPubkeyLength)
|
||||
config[bytesutil.ToBytes48(pk)] = &proposer.Option{
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "specific graffiti",
|
||||
},
|
||||
}
|
||||
return config
|
||||
}(),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set without proposer settings",
|
||||
graffiti: "specific graffiti",
|
||||
wantProposerSettings: func() *proposer.Settings {
|
||||
config := make(map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option)
|
||||
config[pubKey] = &proposer.Option{
|
||||
GraffitiConfig: &proposer.GraffitiConfig{
|
||||
Graffiti: "specific graffiti",
|
||||
},
|
||||
}
|
||||
return &proposer.Settings{ProposeConfig: config}
|
||||
}(),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
v := &validator{
|
||||
db: testing2.SetupDB(t, [][fieldparams.BLSPubkeyLength]byte{pubKey}, false),
|
||||
proposerSettings: tt.proposerSettings,
|
||||
}
|
||||
err := v.SetGraffiti(context.Background(), pubKey, []byte(tt.graffiti))
|
||||
if tt.wantErr != "" {
|
||||
require.ErrorContains(t, tt.wantErr, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
if tt.wantProposerSettings != nil {
|
||||
require.DeepEqual(t, tt.wantProposerSettings, v.proposerSettings)
|
||||
} else {
|
||||
require.Equal(t, v.proposerSettings.ProposeConfig[pubKey].GraffitiConfig.Graffiti, tt.graffiti)
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -358,3 +358,24 @@ func (v *ValidatorService) GenesisInfo(ctx context.Context) (*ethpb.Genesis, err
|
||||
nc := ethpb.NewNodeClient(v.conn.GetGrpcClientConn())
|
||||
return nc.GetGenesis(ctx, &emptypb.Empty{})
|
||||
}
|
||||
|
||||
func (v *ValidatorService) GetGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte) ([]byte, error) {
|
||||
if v.validator == nil {
|
||||
return nil, errors.New("validator is unavailable")
|
||||
}
|
||||
return v.validator.GetGraffiti(ctx, pubKey)
|
||||
}
|
||||
|
||||
func (v *ValidatorService) SetGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte, graffiti []byte) error {
|
||||
if v.validator == nil {
|
||||
return errors.New("validator is unavailable")
|
||||
}
|
||||
return v.validator.SetGraffiti(ctx, pubKey, graffiti)
|
||||
}
|
||||
|
||||
func (v *ValidatorService) DeleteGraffiti(ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte) error {
|
||||
if v.validator == nil {
|
||||
return errors.New("validator is unavailable")
|
||||
}
|
||||
return v.validator.DeleteGraffiti(ctx, pubKey)
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ type FakeValidator struct {
|
||||
proposerSettings *proposer.Settings
|
||||
ProposerSettingWait time.Duration
|
||||
Km keymanager.IKeymanager
|
||||
graffiti string
|
||||
Tracker *beacon.NodeHealthTracker
|
||||
}
|
||||
|
||||
@ -282,7 +283,25 @@ func (fv *FakeValidator) SetProposerSettings(_ context.Context, settings *propos
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGraffiti for mocking
|
||||
func (f *FakeValidator) GetGraffiti(_ context.Context, _ [fieldparams.BLSPubkeyLength]byte) ([]byte, error) {
|
||||
return []byte(f.graffiti), nil
|
||||
}
|
||||
|
||||
// SetGraffiti for mocking
|
||||
func (f *FakeValidator) SetGraffiti(_ context.Context, _ [fieldparams.BLSPubkeyLength]byte, graffiti []byte) error {
|
||||
f.graffiti = string(graffiti)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteGraffiti for mocking
|
||||
func (f *FakeValidator) DeleteGraffiti(_ context.Context, _ [fieldparams.BLSPubkeyLength]byte) error {
|
||||
f.graffiti = ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*FakeValidator) StartEventStream(_ context.Context, _ []string, _ chan<- *event.Event) {
|
||||
|
||||
}
|
||||
|
||||
func (*FakeValidator) ProcessEvent(_ *event.Event) {}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
@ -839,3 +840,86 @@ func (s *Server) DeleteGasLimit(w http.ResponseWriter, r *http.Request) {
|
||||
// we respond "not found".
|
||||
httputil.HandleError(w, fmt.Sprintf("No gas limit found for pubkey %q", rawPubkey), http.StatusNotFound)
|
||||
}
|
||||
|
||||
func (s *Server) GetGraffiti(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "validator.keymanagerAPI.GetGraffiti")
|
||||
defer span.End()
|
||||
|
||||
if s.validatorService == nil {
|
||||
httputil.HandleError(w, "Validator service not ready.", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
rawPubkey, pubkey, ok := shared.HexFromRoute(w, r, "pubkey", fieldparams.BLSPubkeyLength)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
graffiti, err := s.validatorService.GetGraffiti(ctx, bytesutil.ToBytes48(pubkey))
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "unavailable") {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
httputil.HandleError(w, err.Error(), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
httputil.WriteJson(w, &GetGraffitiResponse{
|
||||
Data: &GraffitiData{
|
||||
Pubkey: rawPubkey,
|
||||
Graffiti: string(graffiti),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) SetGraffiti(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "validator.keymanagerAPI.SetGraffiti")
|
||||
defer span.End()
|
||||
|
||||
if s.validatorService == nil {
|
||||
httputil.HandleError(w, "Validator service not ready.", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
_, pubkey, ok := shared.HexFromRoute(w, r, "pubkey", fieldparams.BLSPubkeyLength)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Graffiti string `json:"graffiti"`
|
||||
}
|
||||
err := json.NewDecoder(r.Body).Decode(&req)
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
httputil.HandleError(w, "No data submitted", http.StatusBadRequest)
|
||||
return
|
||||
case err != nil:
|
||||
httputil.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.validatorService.SetGraffiti(ctx, bytesutil.ToBytes48(pubkey), []byte(req.Graffiti)); err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) DeleteGraffiti(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := trace.StartSpan(r.Context(), "validator.keymanagerAPI.DeleteGraffiti")
|
||||
defer span.End()
|
||||
|
||||
if s.validatorService == nil {
|
||||
httputil.HandleError(w, "Validator service not ready.", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
_, pubkey, ok := shared.HexFromRoute(w, r, "pubkey", fieldparams.BLSPubkeyLength)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.validatorService.DeleteGraffiti(ctx, bytesutil.ToBytes48(pubkey)); err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -1898,3 +1898,48 @@ func TestServer_DeleteFeeRecipientByPubkey_InvalidPubKey(t *testing.T) {
|
||||
|
||||
require.StringContains(t, "pubkey is invalid", w.Body.String())
|
||||
}
|
||||
|
||||
func TestServer_Graffiti(t *testing.T) {
|
||||
graffiti := "graffiti"
|
||||
m := &mock.Validator{}
|
||||
vs, err := client.NewValidatorService(context.Background(), &client.Config{
|
||||
Validator: m,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
s := &Server{
|
||||
validatorService: vs,
|
||||
}
|
||||
|
||||
var request struct {
|
||||
Graffiti string `json:"graffiti"`
|
||||
}
|
||||
request.Graffiti = graffiti
|
||||
pubkey := "0xaf2e7ba294e03438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2c06bd3713cb442072ae591493"
|
||||
var buf bytes.Buffer
|
||||
err = json.NewEncoder(&buf).Encode(request)
|
||||
require.NoError(t, err)
|
||||
req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/eth/v1/validator/{pubkey}/graffiti"), &buf)
|
||||
req = mux.SetURLVars(req, map[string]string{"pubkey": pubkey})
|
||||
w := httptest.NewRecorder()
|
||||
w.Body = &bytes.Buffer{}
|
||||
s.SetGraffiti(w, req)
|
||||
require.Equal(t, http.StatusOK, w.Code)
|
||||
|
||||
req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("/eth/v1/validator/{pubkey}/graffiti"), nil)
|
||||
req = mux.SetURLVars(req, map[string]string{"pubkey": pubkey})
|
||||
w = httptest.NewRecorder()
|
||||
w.Body = &bytes.Buffer{}
|
||||
s.GetGraffiti(w, req)
|
||||
require.Equal(t, http.StatusOK, w.Code)
|
||||
resp := &GetGraffitiResponse{}
|
||||
require.NoError(t, json.Unmarshal(w.Body.Bytes(), resp))
|
||||
assert.Equal(t, resp.Data.Graffiti, request.Graffiti)
|
||||
assert.Equal(t, resp.Data.Pubkey, pubkey)
|
||||
|
||||
req = httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/eth/v1/validator/{pubkey}/graffiti"), nil)
|
||||
req = mux.SetURLVars(req, map[string]string{"pubkey": pubkey})
|
||||
w = httptest.NewRecorder()
|
||||
w.Body = &bytes.Buffer{}
|
||||
s.DeleteGraffiti(w, req)
|
||||
require.Equal(t, http.StatusOK, w.Code)
|
||||
}
|
||||
|
@ -230,6 +230,10 @@ func (s *Server) InitializeRoutes() error {
|
||||
s.router.HandleFunc("/eth/v1/validator/{pubkey}/feerecipient", s.SetFeeRecipientByPubkey).Methods(http.MethodPost)
|
||||
s.router.HandleFunc("/eth/v1/validator/{pubkey}/feerecipient", s.DeleteFeeRecipientByPubkey).Methods(http.MethodDelete)
|
||||
s.router.HandleFunc("/eth/v1/validator/{pubkey}/voluntary_exit", s.SetVoluntaryExit).Methods(http.MethodPost)
|
||||
s.router.HandleFunc("/eth/v1/validator/{pubkey}/graffiti", s.GetGraffiti).Methods(http.MethodGet)
|
||||
s.router.HandleFunc("/eth/v1/validator/{pubkey}/graffiti", s.SetGraffiti).Methods(http.MethodPost)
|
||||
s.router.HandleFunc("/eth/v1/validator/{pubkey}/graffiti", s.DeleteGraffiti).Methods(http.MethodDelete)
|
||||
|
||||
// auth endpoint
|
||||
s.router.HandleFunc(api.WebUrlPrefix+"initialize", s.Initialize).Methods(http.MethodGet)
|
||||
// accounts endpoints
|
||||
|
@ -21,6 +21,7 @@ func TestServer_InitializeRoutes(t *testing.T) {
|
||||
"/eth/v1/validator/{pubkey}/gas_limit": {http.MethodGet, http.MethodPost, http.MethodDelete},
|
||||
"/eth/v1/validator/{pubkey}/feerecipient": {http.MethodGet, http.MethodPost, http.MethodDelete},
|
||||
"/eth/v1/validator/{pubkey}/voluntary_exit": {http.MethodPost},
|
||||
"/eth/v1/validator/{pubkey}/graffiti": {http.MethodGet, http.MethodPost, http.MethodDelete},
|
||||
"/v2/validator/health/version": {http.MethodGet},
|
||||
"/v2/validator/health/logs/validator/stream": {http.MethodGet},
|
||||
"/v2/validator/health/logs/beacon/stream": {http.MethodGet},
|
||||
|
@ -99,6 +99,16 @@ type SetFeeRecipientByPubkeyRequest struct {
|
||||
Ethaddress string `json:"ethaddress"`
|
||||
}
|
||||
|
||||
// Graffiti keymanager api
|
||||
type GetGraffitiResponse struct {
|
||||
Data *GraffitiData `json:"data"`
|
||||
}
|
||||
|
||||
type GraffitiData struct {
|
||||
Pubkey string `json:"pubkey"`
|
||||
Graffiti string `json:"graffiti"`
|
||||
}
|
||||
|
||||
type BeaconStatusResponse struct {
|
||||
BeaconNodeEndpoint string `json:"beacon_node_endpoint"`
|
||||
Connected bool `json:"connected"`
|
||||
|
Loading…
Reference in New Issue
Block a user