From 644d5bbb1a4a2095394af35b3cc75e247825a868 Mon Sep 17 00:00:00 2001 From: Alexander Mollohan Date: Thu, 10 Jun 2021 12:54:24 -0400 Subject: [PATCH] Graffiti hex support (#8894) * more or less feature complete, needs unit tests * Test support and concomitant refactors * Resolving requested changes on PR * minor fix before trying to figure out bazel * bazel change * minor changes requested in pr * fixing build errors * fixing build errors * fixing PR feedback * fixing PR feedback * resolving nitpicks * resolving nitpicks * build failures REEEEE * tests fail if its not this way, so this way it is * getting the tests to pass Co-authored-by: Raul Jordan Co-authored-by: Preston Van Loon --- validator/graffiti/BUILD.bazel | 7 ++- validator/graffiti/log.go | 5 ++ validator/graffiti/parse_graffiti.go | 48 ++++++++++++++++++ validator/graffiti/parse_graffiti_test.go | 62 +++++++++++++++++++++++ validator/node/node.go | 4 +- 5 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 validator/graffiti/log.go diff --git a/validator/graffiti/BUILD.bazel b/validator/graffiti/BUILD.bazel index 672fb4fa0..eff9a265b 100644 --- a/validator/graffiti/BUILD.bazel +++ b/validator/graffiti/BUILD.bazel @@ -3,12 +3,16 @@ load("@prysm//tools/go:def.bzl", "go_library") go_library( name = "go_default_library", - srcs = ["parse_graffiti.go"], + srcs = [ + "log.go", + "parse_graffiti.go", + ], importpath = "github.com/prysmaticlabs/prysm/validator/graffiti", visibility = ["//validator:__subpackages__"], deps = [ "//shared/hashutil:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", "@in_gopkg_yaml_v2//:go_default_library", ], ) @@ -19,6 +23,7 @@ go_test( embed = [":go_default_library"], deps = [ "//shared/hashutil:go_default_library", + "//shared/testutil/assert:go_default_library", "//shared/testutil/require:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", ], diff --git a/validator/graffiti/log.go b/validator/graffiti/log.go new file mode 100644 index 000000000..b689212ba --- /dev/null +++ b/validator/graffiti/log.go @@ -0,0 +1,5 @@ +package graffiti + +import "github.com/sirupsen/logrus" + +var log = logrus.WithField("prefix", "graffiti") diff --git a/validator/graffiti/parse_graffiti.go b/validator/graffiti/parse_graffiti.go index 9e23dfebc..118c9218d 100644 --- a/validator/graffiti/parse_graffiti.go +++ b/validator/graffiti/parse_graffiti.go @@ -1,13 +1,20 @@ package graffiti import ( + "encoding/hex" "io/ioutil" + "strings" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/shared/hashutil" "gopkg.in/yaml.v2" ) +const ( + hexGraffitiPrefix = "hex" + hex0xPrefix = "0x" +) + // Graffiti is a graffiti container. type Graffiti struct { Hash [32]byte @@ -27,6 +34,47 @@ func ParseGraffitiFile(f string) (*Graffiti, error) { if err := yaml.Unmarshal(yamlFile, g); err != nil { return nil, err } + + for i, o := range g.Specific { + g.Specific[types.ValidatorIndex(i)] = ParseHexGraffiti(o) + } + + for i, v := range g.Ordered { + g.Ordered[i] = ParseHexGraffiti(v) + } + + for i, v := range g.Random { + g.Random[i] = ParseHexGraffiti(v) + } + + g.Default = ParseHexGraffiti(g.Default) g.Hash = hashutil.Hash(yamlFile) + return g, nil } + +// ParseHexGraffiti checks if a graffiti input is being represented in hex and converts it to ASCII if so +func ParseHexGraffiti(rawGraffiti string) string { + splitGraffiti := strings.SplitN(rawGraffiti, ":", 2) + if strings.ToLower(splitGraffiti[0]) == hexGraffitiPrefix { + target := splitGraffiti[1] + if target == "" { + log.WithField("graffiti", rawGraffiti).Debug("Blank hex tag to be interpreted as itself") + return rawGraffiti + } + if len(target) > 3 && target[:2] == hex0xPrefix { + target = target[2:] + } + if target == "" { + log.WithField("graffiti", rawGraffiti).Debug("Nothing after 0x prefix, hex tag to be interpreted as itself") + return rawGraffiti + } + graffiti, err := hex.DecodeString(target) + if err != nil { + log.WithError(err).Debug("Error while decoding hex string") + return rawGraffiti + } + return string(graffiti) + } + return rawGraffiti +} diff --git a/validator/graffiti/parse_graffiti_test.go b/validator/graffiti/parse_graffiti_test.go index 46c8cea1c..35e3ce4e0 100644 --- a/validator/graffiti/parse_graffiti_test.go +++ b/validator/graffiti/parse_graffiti_test.go @@ -8,6 +8,7 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/shared/hashutil" + "github.com/prysmaticlabs/prysm/shared/testutil/assert" "github.com/prysmaticlabs/prysm/shared/testutil/require" ) @@ -157,3 +158,64 @@ specific: } require.DeepEqual(t, wanted, got) } + +func TestParseHexGraffiti(t *testing.T) { + tests := []struct { + name string + want string + input string + }{ + { + name: "standard", + want: "hola mundo!", + input: "hola mundo!", + }, + { + name: "standard with hex tag", + want: "hola mundo!", + input: "hex:686f6c61206d756e646f21", + }, + { + name: "irregularly cased hex tag", + want: "hola mundo!", + input: "HEX:686f6c61206d756e646f21", + }, + { + name: "hex tag without accompanying data", + want: "hex:", + input: "hex:", + }, + { + name: "Passing non-hex data with hex tag", + want: "hex:hola mundo!", + input: "hex:hola mundo!", + }, + { + name: "unmarked hex input", + want: "0x686f6c61206d756e646f21", + input: "0x686f6c61206d756e646f21", + }, + { + name: "Properly tagged hex data with 0x prefix", + want: "hola mundo!", + input: "hex:0x686f6c61206d756e646f21", + }, + { + name: "hex tag with 0x prefix and no other data", + want: "hex:0x", + input: "hex:0x", + }, + { + name: "hex tag with 0x prefix and invalid hex data", + want: "hex:0xhola mundo", + input: "hex:0xhola mundo", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + out := ParseHexGraffiti(tt.input) + assert.Equal(t, out, tt.want) + }) + } +} diff --git a/validator/node/node.go b/validator/node/node.go index 27adbbd52..20cc74020 100644 --- a/validator/node/node.go +++ b/validator/node/node.go @@ -409,7 +409,7 @@ func (c *ValidatorClient) registerValidatorService( LogValidatorBalances: logValidatorBalances, EmitAccountMetrics: emitAccountMetrics, CertFlag: cert, - GraffitiFlag: graffiti, + GraffitiFlag: g.ParseHexGraffiti(graffiti), GrpcMaxCallRecvMsgSizeFlag: maxCallRecvMsgSize, GrpcRetriesFlag: grpcRetries, GrpcRetryDelay: grpcRetryDelay, @@ -421,10 +421,10 @@ func (c *ValidatorClient) registerValidatorService( GraffitiStruct: gStruct, LogDutyCountDown: c.cliCtx.Bool(flags.EnableDutyCountDown.Name), }) - if err != nil { return errors.Wrap(err, "could not initialize validator service") } + return c.services.RegisterService(v) } func (c *ValidatorClient) registerSlasherService() error {