mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 22:23:11 +00:00
The block results include validator updates in ABCI protobuf format, which does not encode "correctly" according to the expected Amino style RPC clients expect. - Write a regression test for this issue. - Add JSON marshaling overrides for ABCI ValidatorUpdate messages. Patches for v0.35.x: - Replace jsontypes with tmjson (removed in v0.36) - Regress test data for BeginBlock / EndBlock
This commit is contained in:
@@ -12,6 +12,8 @@ Special thanks to external contributors on this release:
|
||||
|
||||
- CLI/RPC/Config
|
||||
|
||||
- [rpc] \#8594 fix encoding of block_results responses (@creachadair)
|
||||
|
||||
- Apps
|
||||
|
||||
- P2P Protocol
|
||||
|
||||
@@ -5,6 +5,9 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gogo/protobuf/jsonpb"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/encoding"
|
||||
tmjson "github.com/tendermint/tendermint/libs/json"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -102,6 +105,48 @@ func (r *EventAttribute) UnmarshalJSON(b []byte) error {
|
||||
return jsonpbUnmarshaller.Unmarshal(reader, r)
|
||||
}
|
||||
|
||||
// validatorUpdateJSON is the JSON encoding of a validator update.
|
||||
//
|
||||
// It handles translation of public keys from the protobuf representation to
|
||||
// the legacy Amino-compatible format expected by RPC clients.
|
||||
type validatorUpdateJSON struct {
|
||||
PubKey json.RawMessage `json:"pub_key,omitempty"`
|
||||
Power int64 `json:"power,string"`
|
||||
}
|
||||
|
||||
func (v *ValidatorUpdate) MarshalJSON() ([]byte, error) {
|
||||
key, err := encoding.PubKeyFromProto(v.PubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
jkey, err := tmjson.Marshal(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(validatorUpdateJSON{
|
||||
PubKey: jkey,
|
||||
Power: v.GetPower(),
|
||||
})
|
||||
}
|
||||
|
||||
func (v *ValidatorUpdate) UnmarshalJSON(data []byte) error {
|
||||
var vu validatorUpdateJSON
|
||||
if err := json.Unmarshal(data, &vu); err != nil {
|
||||
return err
|
||||
}
|
||||
var key crypto.PubKey
|
||||
if err := tmjson.Unmarshal(vu.PubKey, &key); err != nil {
|
||||
return err
|
||||
}
|
||||
pkey, err := encoding.PubKeyToProto(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.PubKey = pkey
|
||||
v.Power = vu.Power
|
||||
return nil
|
||||
}
|
||||
|
||||
// Some compile time assertions to ensure we don't
|
||||
// have accidental runtime surprises later on.
|
||||
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
package coretypes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
pbcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
@@ -32,3 +41,54 @@ func TestStatusIndexer(t *testing.T) {
|
||||
assert.Equal(t, tc.expected, status.TxIndexEnabled())
|
||||
}
|
||||
}
|
||||
|
||||
// A regression test for https://github.com/tendermint/tendermint/issues/8583.
|
||||
func TestResultBlockResults_regression8583(t *testing.T) {
|
||||
const keyData = "0123456789abcdef0123456789abcdef" // 32 bytes
|
||||
wantKey := base64.StdEncoding.EncodeToString([]byte(keyData))
|
||||
|
||||
rsp := &ResultBlockResults{
|
||||
ValidatorUpdates: []abci.ValidatorUpdate{{
|
||||
PubKey: pbcrypto.PublicKey{
|
||||
Sum: &pbcrypto.PublicKey_Ed25519{Ed25519: []byte(keyData)},
|
||||
},
|
||||
Power: 400,
|
||||
}},
|
||||
}
|
||||
|
||||
// Use compact here so the test data remain legible. The output from the
|
||||
// marshaler will have whitespace folded out so we need to do that too for
|
||||
// the comparison to be valid.
|
||||
var buf bytes.Buffer
|
||||
require.NoError(t, json.Compact(&buf, []byte(fmt.Sprintf(`
|
||||
{
|
||||
"height": 0,
|
||||
"txs_results": null,
|
||||
"total_gas_used": 0,
|
||||
"begin_block_events": null,
|
||||
"end_block_events": null,
|
||||
"validator_updates": [
|
||||
{
|
||||
"pub_key":{"type": "tendermint/PubKeyEd25519", "value": "%s"},
|
||||
"power": "400"
|
||||
}
|
||||
],
|
||||
"consensus_param_updates": null
|
||||
}`, wantKey))))
|
||||
|
||||
bits, err := json.Marshal(rsp)
|
||||
if err != nil {
|
||||
t.Fatalf("Encoding block result: %v", err)
|
||||
}
|
||||
if diff := cmp.Diff(buf.String(), string(bits)); diff != "" {
|
||||
t.Errorf("Marshaled result (-want, +got):\n%s", diff)
|
||||
}
|
||||
|
||||
back := new(ResultBlockResults)
|
||||
if err := json.Unmarshal(bits, back); err != nil {
|
||||
t.Fatalf("Unmarshaling: %v", err)
|
||||
}
|
||||
if diff := cmp.Diff(rsp, back); diff != "" {
|
||||
t.Errorf("Unmarshaled result (-want, +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user