forked from TrueCloudLab/neoneo-go
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 {
|
sort.Slice(vals, func(i, j int) bool {
|
||||||
|
/*
|
||||||
if vals[i].Active != vals[j].Active {
|
if vals[i].Active != vals[j].Active {
|
||||||
return vals[i].Active
|
return vals[i].Active
|
||||||
}
|
}
|
||||||
if vals[i].Votes != vals[j].Votes {
|
if vals[i].Votes != vals[j].Votes {
|
||||||
return vals[i].Votes > vals[j].Votes
|
return vals[i].Votes > vals[j].Votes
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return vals[i].PublicKey.Cmp(&vals[j].PublicKey) == -1
|
return vals[i].PublicKey.Cmp(&vals[j].PublicKey) == -1
|
||||||
})
|
})
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
|
tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
|
||||||
_, _ = tw.Write([]byte("Key\tVotes\tCommittee\tConsensus\n"))
|
_, _ = tw.Write([]byte("Key\tVotes\tCommittee\tConsensus\n"))
|
||||||
for _, val := range vals {
|
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()
|
_ = tw.Flush()
|
||||||
fmt.Fprint(ctx.App.Writer, buf.String())
|
fmt.Fprint(ctx.App.Writer, buf.String())
|
||||||
|
|
|
@ -557,7 +557,7 @@ func (c *Client) GetUnclaimedGas(address string) (result.UnclaimedGas, error) {
|
||||||
return resp, nil
|
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) {
|
func (c *Client) GetNextBlockValidators() ([]result.Validator, error) {
|
||||||
var (
|
var (
|
||||||
params = request.NewRawParams()
|
params = request.NewRawParams()
|
||||||
|
|
|
@ -1,13 +1,43 @@
|
||||||
package result
|
package result
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Validator used for the representation of
|
// Validator is used for the representation of consensus node data in the JSON-RPC
|
||||||
// state.Validator on the RPC Server.
|
// protocol.
|
||||||
type Validator struct {
|
type Validator struct {
|
||||||
PublicKey keys.PublicKey `json:"publickey"`
|
PublicKey keys.PublicKey `json:"publickey"`
|
||||||
Votes int64 `json:"votes,string"`
|
Votes int64 `json:"votes"`
|
||||||
Active bool `json:"active"`
|
}
|
||||||
|
|
||||||
|
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)
|
var res = make([]result.Validator, 0)
|
||||||
for _, v := range enrollments {
|
for _, v := range enrollments {
|
||||||
|
if !validators.Contains(v.Key) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
res = append(res, result.Validator{
|
res = append(res, result.Validator{
|
||||||
PublicKey: *v.Key,
|
PublicKey: *v.Key,
|
||||||
Votes: v.Votes.Int64(),
|
Votes: v.Votes.Int64(),
|
||||||
Active: validators.Contains(v.Key),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
|
|
Loading…
Reference in a new issue