rpc: make getnextvalidators behavior compliant with C# node
Turns out, our getnextvalidators implementation already works the way getcandidates is supposed to work, but original getnextvalidators works a bit differently. It only returns validators, it doesn't return Active flag (all of them are active) and it represents votes as a number. So for the maximum compatibility: * drop non-validator keys from getnextvalidators server-side * drop Active flag client-side (sorry, it doesn't exist) * allow unmarshalling old answers along with the new one This technically breaks `query candidates` CLI command, but it'll be fixed when getcandidates are to be introduced.
This commit is contained in:
parent
2f55070a57
commit
0da0bb21ee
5 changed files with 69 additions and 13 deletions
|
@ -177,19 +177,21 @@ func queryCandidates(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
sort.Slice(vals, func(i, j int) bool {
|
||||
if vals[i].Active != vals[j].Active {
|
||||
return vals[i].Active
|
||||
}
|
||||
if vals[i].Votes != vals[j].Votes {
|
||||
return vals[i].Votes > vals[j].Votes
|
||||
}
|
||||
/*
|
||||
if vals[i].Active != vals[j].Active {
|
||||
return vals[i].Active
|
||||
}
|
||||
if vals[i].Votes != vals[j].Votes {
|
||||
return vals[i].Votes > vals[j].Votes
|
||||
}
|
||||
*/
|
||||
return vals[i].PublicKey.Cmp(&vals[j].PublicKey) == -1
|
||||
})
|
||||
buf := bytes.NewBuffer(nil)
|
||||
tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
|
||||
_, _ = tw.Write([]byte("Key\tVotes\tCommittee\tConsensus\n"))
|
||||
for _, val := range vals {
|
||||
_, _ = tw.Write([]byte(fmt.Sprintf("%s\t%d\t%t\t%t\n", hex.EncodeToString(val.PublicKey.Bytes()), val.Votes, comm.Contains(&val.PublicKey), val.Active)))
|
||||
_, _ = tw.Write([]byte(fmt.Sprintf("%s\t%d\t%t\t%t\n", hex.EncodeToString(val.PublicKey.Bytes()), val.Votes, comm.Contains(&val.PublicKey), true)))
|
||||
}
|
||||
_ = tw.Flush()
|
||||
fmt.Fprint(ctx.App.Writer, buf.String())
|
||||
|
|
|
@ -557,7 +557,7 @@ func (c *Client) GetUnclaimedGas(address string) (result.UnclaimedGas, error) {
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
// GetNextBlockValidators returns the current NEO consensus nodes information and voting status.
|
||||
// GetNextBlockValidators returns the current NEO consensus nodes information and voting data.
|
||||
func (c *Client) GetNextBlockValidators() ([]result.Validator, error) {
|
||||
var (
|
||||
params = request.NewRawParams()
|
||||
|
|
|
@ -1,13 +1,43 @@
|
|||
package result
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
)
|
||||
|
||||
// Validator used for the representation of
|
||||
// state.Validator on the RPC Server.
|
||||
// Validator is used for the representation of consensus node data in the JSON-RPC
|
||||
// protocol.
|
||||
type Validator struct {
|
||||
PublicKey keys.PublicKey `json:"publickey"`
|
||||
Votes int64 `json:"votes,string"`
|
||||
Active bool `json:"active"`
|
||||
Votes int64 `json:"votes"`
|
||||
}
|
||||
|
||||
type newValidator struct {
|
||||
PublicKey keys.PublicKey `json:"publickey"`
|
||||
Votes int64 `json:"votes"`
|
||||
}
|
||||
|
||||
type oldValidator struct {
|
||||
PublicKey keys.PublicKey `json:"publickey"`
|
||||
Votes int64 `json:"votes,string"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||
func (v *Validator) UnmarshalJSON(data []byte) error {
|
||||
var nv = new(newValidator)
|
||||
err := json.Unmarshal(data, nv)
|
||||
if err != nil {
|
||||
var ov = new(oldValidator)
|
||||
err := json.Unmarshal(data, ov)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.PublicKey = ov.PublicKey
|
||||
v.Votes = ov.Votes
|
||||
return nil
|
||||
}
|
||||
v.PublicKey = nv.PublicKey
|
||||
v.Votes = nv.Votes
|
||||
return nil
|
||||
}
|
||||
|
|
22
pkg/rpc/response/result/validator_test.go
Normal file
22
pkg/rpc/response/result/validator_test.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package result
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestValidatorUnmarshal(t *testing.T) {
|
||||
old := []byte(`{"publickey":"02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62","votes":"100500","active":true}`)
|
||||
v := new(Validator)
|
||||
require.NoError(t, json.Unmarshal(old, v))
|
||||
require.Equal(t, int64(100500), v.Votes)
|
||||
|
||||
new := []byte(`{"publickey":"02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62","votes":42}`)
|
||||
require.NoError(t, json.Unmarshal(new, v))
|
||||
require.Equal(t, int64(42), v.Votes)
|
||||
|
||||
bad := []byte(`{"publickey":"02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62","votes":"notanumber"}`)
|
||||
require.Error(t, json.Unmarshal(bad, v))
|
||||
}
|
|
@ -1552,10 +1552,12 @@ func (s *Server) getNextBlockValidators(_ request.Params) (interface{}, *respons
|
|||
}
|
||||
var res = make([]result.Validator, 0)
|
||||
for _, v := range enrollments {
|
||||
if !validators.Contains(v.Key) {
|
||||
continue
|
||||
}
|
||||
res = append(res, result.Validator{
|
||||
PublicKey: *v.Key,
|
||||
Votes: v.Votes.Int64(),
|
||||
Active: validators.Contains(v.Key),
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
|
|
Loading…
Reference in a new issue