diff --git a/consensus/oasys/snapshot.go b/consensus/oasys/snapshot.go index 261937bc9..9fdf5ecf5 100644 --- a/consensus/oasys/snapshot.go +++ b/consensus/oasys/snapshot.go @@ -27,18 +27,40 @@ type Snapshot struct { Number uint64 `json:"number"` // Block number where the snapshot was created Hash common.Hash `json:"hash"` // Block hash where the snapshot was created Validators map[common.Address]*ValidatorInfo `json:"validators"` // Set of authorized validators and stakes at this moment - Attestation *types.VoteData `json:"attestation:omitempty"` // Attestation for fast finality, but `Source` used as `Finalized` + Attestation *types.VoteData `json:"attestation,omitempty"` // Attestation for fast finality, but `Source` used as `Finalized` Environment *params.EnvironmentValue `json:"environment"` } type ValidatorInfo struct { // The index is determined by the sorted order of the validator owner address - Stake *big.Int `json:"stake:omitempty"` // The stake amount - Index int `json:"index:omitempty"` // The index should offset by 1 + Stake *big.Int `json:"stake,omitempty"` // The stake amount + Index int `json:"index,omitempty"` // The index should offset by 1 VoteAddress types.BLSPublicKey `json:"vote_address,omitempty"` // The vote address } +// Note: This code can be removed after each validators has been upgraded to v1.6.0. +func (info *ValidatorInfo) UnmarshalJSON(b []byte) error { + // v1.5.0 or earlier + bigint := new(big.Int) + if err := json.Unmarshal(b, bigint); err == nil { + info.Stake = bigint + return nil + } + + // v1.6.0 or later + type Alias ValidatorInfo + alias := new(Alias) + if err := json.Unmarshal(b, alias); err != nil { + return err + } + + info.Stake = alias.Stake + info.Index = alias.Index + info.VoteAddress = alias.VoteAddress + return nil +} + // validatorsAscending implements the sort interface to allow sorting a list of addresses type validatorsAscending []common.Address diff --git a/consensus/oasys/snapshot_test.go b/consensus/oasys/snapshot_test.go new file mode 100644 index 000000000..c6d793e92 --- /dev/null +++ b/consensus/oasys/snapshot_test.go @@ -0,0 +1,44 @@ +package oasys + +import ( + "encoding/json" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +func TestUnmarshalValidatorInfo(t *testing.T) { + jsonbody := []byte(`[ + 1, + { + "stake": 2, + "index": 3, + "vote_address": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004" + } + ]`) + + expects := []*ValidatorInfo{ + &ValidatorInfo{ + Stake: big.NewInt(1), + Index: 0, + VoteAddress: types.BLSPublicKey{}, + }, + &ValidatorInfo{ + Stake: big.NewInt(2), + Index: 3, + VoteAddress: types.BLSPublicKey([]byte{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, + }), + }, + } + + var actuals []*ValidatorInfo + err := json.Unmarshal(jsonbody, &actuals) + require.NoError(t, err) + require.Equal(t, expects, actuals) +} diff --git a/core/types/vote.go b/core/types/vote.go index 75f8166b3..81fe4c794 100644 --- a/core/types/vote.go +++ b/core/types/vote.go @@ -3,12 +3,14 @@ package types import ( "bytes" "math/big" + "reflect" "sync/atomic" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" ) const ( @@ -18,6 +20,10 @@ const ( MaxAttestationExtraLength = 256 ) +var ( + blsPublicKeyT = reflect.TypeOf(BLSPublicKey{}) +) + type BLSPublicKey [BLSPublicKeyLength]byte type BLSSignature [BLSSignatureLength]byte type ValidatorsBitSet uint64 @@ -71,7 +77,19 @@ func (v *VoteEnvelope) calcVoteHash() common.Hash { return rlpHash(vote) } -func (b BLSPublicKey) Bytes() []byte { return b[:] } +func (b BLSPublicKey) Bytes() []byte { return b[:] } +func (b BLSPublicKey) String() string { return hexutil.Encode(b[:]) } + +// MarshalText gets implements encoding.TextMarshaler. Since BLSPublicKey is stored as JSON in the +// consensus engine's snapshot db, it is converted to a hex-string to improve readability and reduce size. +func (b BLSPublicKey) MarshalText() ([]byte, error) { + return hexutil.Bytes(b[:]).MarshalText() +} + +// UnmarshalJSON decodes the input as a string with 0x prefix +func (b *BLSPublicKey) UnmarshalJSON(input []byte) error { + return hexutil.UnmarshalFixedJSON(blsPublicKeyT, input, b[:]) +} // Verify vote using BLS. func (vote *VoteEnvelope) Verify() error {