From fa411df3779023f0d1282ddf609fe11c370874f5 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Tue, 24 Mar 2026 20:13:09 +0100 Subject: [PATCH] fixed ValidatorInfo json encoding (#3114) There were 2 issues: * for backward compatibility with CosmJS, PubKey needs to be a 0 key in case of non-validator node. * decoding was broken altogether, because it always returned the zero value of ValidatorInfo (cherry picked from commit be7fb0279bfe22d38ce584cb130034983eead15d) --- sei-tendermint/rpc/coretypes/responses.go | 32 +++++++++++-------- .../rpc/coretypes/responses_test.go | 27 ++++++++++++++++ 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/sei-tendermint/rpc/coretypes/responses.go b/sei-tendermint/rpc/coretypes/responses.go index 4351d04069..9222eadf5b 100644 --- a/sei-tendermint/rpc/coretypes/responses.go +++ b/sei-tendermint/rpc/coretypes/responses.go @@ -129,6 +129,7 @@ type ValidatorInfo struct { VotingPower int64 } +// CosmJS compatible response, which contains a public key = 0 in case of non-validator nodes. type validatorInfoJSON struct { Address bytes.HexBytes `json:"address"` PubKey json.RawMessage `json:"pub_key"` @@ -136,25 +137,28 @@ type validatorInfoJSON struct { } func (v ValidatorInfo) MarshalJSON() ([]byte, error) { - j := validatorInfoJSON{VotingPower: v.VotingPower} - if k, ok := v.PubKey.Get(); ok { - pk, err := jsontypes.Marshal(k) - if err != nil { - return nil, err - } - j.PubKey = pk - j.Address = k.Address() + k := v.PubKey.Or(crypto.PubKey{}) + pk, err := jsontypes.Marshal(k) + if err != nil { + return nil, err } - return json.Marshal(j) + return json.Marshal(validatorInfoJSON{ + VotingPower: v.VotingPower, + PubKey: pk, + Address: k.Address(), + }) } func (v *ValidatorInfo) UnmarshalJSON(data []byte) error { var val validatorInfoJSON - if len(val.PubKey) != 0 { - var pk crypto.PubKey - if err := jsontypes.Unmarshal(val.PubKey, &pk); err != nil { - return err - } + if err := json.Unmarshal(data, &val); err != nil { + return err + } + var pk crypto.PubKey + if err := jsontypes.Unmarshal(val.PubKey, &pk); err != nil { + return err + } + if pk != (crypto.PubKey{}) { v.PubKey = utils.Some(pk) } v.VotingPower = val.VotingPower diff --git a/sei-tendermint/rpc/coretypes/responses_test.go b/sei-tendermint/rpc/coretypes/responses_test.go index 91e7bc14e1..3fedc4b260 100644 --- a/sei-tendermint/rpc/coretypes/responses_test.go +++ b/sei-tendermint/rpc/coretypes/responses_test.go @@ -12,6 +12,9 @@ import ( "github.com/stretchr/testify/require" abci "github.com/sei-protocol/sei-chain/sei-tendermint/abci/types" + "github.com/sei-protocol/sei-chain/sei-tendermint/crypto" + "github.com/sei-protocol/sei-chain/sei-tendermint/crypto/ed25519" + "github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils" pbcrypto "github.com/sei-protocol/sei-chain/sei-tendermint/proto/tendermint/crypto" "github.com/sei-protocol/sei-chain/sei-tendermint/types" ) @@ -91,3 +94,27 @@ func TestResultBlockResults_regression8583(t *testing.T) { t.Errorf("Unmarshaled result (-want, +got):\n%s", diff) } } + +func TestValidatorInfoJSONReencoding(t *testing.T) { + cases := map[string]ValidatorInfo{ + "non-validator": { + PubKey: utils.None[crypto.PubKey](), + VotingPower: 0, + }, + "validator": { + PubKey: utils.Some(ed25519.TestSecretKey([]byte("validator-info-json")).Public()), + VotingPower: 123, + }, + } + + for name, want := range cases { + t.Run(name, func(t *testing.T) { + raw, err := json.Marshal(want) + require.NoError(t, err) + + var got ValidatorInfo + require.NoError(t, json.Unmarshal(raw, &got)) + require.NoError(t, utils.TestDiff(want, got)) + }) + } +}