rpc: implement getvalidators

closes #714
This commit is contained in:
Anna Shaleva 2020-03-05 17:48:30 +03:00 committed by AnnaShaleva
parent f8eee778f4
commit 456a2d55fd
8 changed files with 113 additions and 1 deletions

View file

@ -57,7 +57,7 @@ which would yield the response:
| `gettxout` | Yes | | `gettxout` | Yes |
| `getunclaimed` | No (#712) | | `getunclaimed` | No (#712) |
| `getunspents` | Yes | | `getunspents` | Yes |
| `getvalidators` | No (#714) | | `getvalidators` | Yes |
| `getversion` | Yes | | `getversion` | Yes |
| `invoke` | Yes | | `invoke` | Yes |
| `invokefunction` | Yes | | `invokefunction` | Yes |

View file

@ -1804,6 +1804,40 @@ func (bc *Blockchain) GetValidators(txes ...*transaction.Transaction) ([]*keys.P
return result, nil return result, nil
} }
// GetEnrollments returns all registered validators and non-registered SB validators
func (bc *Blockchain) GetEnrollments() ([]*state.Validator, error) {
validators := bc.dao.GetValidators()
standByValidators, err := bc.GetStandByValidators()
if err != nil {
return nil, err
}
uniqueSBValidators := standByValidators.Unique()
var result []*state.Validator
for _, validator := range validators {
if validator.Registered {
result = append(result, validator)
}
}
for _, sBValidator := range uniqueSBValidators {
isAdded := false
for _, v := range result {
if v.PublicKey == sBValidator {
isAdded = true
break
}
}
if !isAdded {
result = append(result, &state.Validator{
PublicKey: sBValidator,
Registered: false,
Votes: 0,
})
}
}
return result, nil
}
func processStateTX(dao *cachedDao, tx *transaction.StateTX) error { func processStateTX(dao *cachedDao, tx *transaction.StateTX) error {
for _, desc := range tx.Descriptors { for _, desc := range tx.Descriptors {
switch desc.Type { switch desc.Type {

View file

@ -25,6 +25,7 @@ type Blockchainer interface {
HeaderHeight() uint32 HeaderHeight() uint32
GetBlock(hash util.Uint256) (*block.Block, error) GetBlock(hash util.Uint256) (*block.Block, error)
GetContractState(hash util.Uint160) *state.Contract GetContractState(hash util.Uint160) *state.Contract
GetEnrollments() ([]*state.Validator, error)
GetHeaderHash(int) util.Uint256 GetHeaderHash(int) util.Uint256
GetHeader(hash util.Uint256) (*block.Header, error) GetHeader(hash util.Uint256) (*block.Header, error)
CurrentHeaderHash() util.Uint256 CurrentHeaderHash() util.Uint256

View file

@ -98,6 +98,9 @@ func (chain testChain) GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog {
func (chain testChain) GetValidators(...*transaction.Transaction) ([]*keys.PublicKey, error) { func (chain testChain) GetValidators(...*transaction.Transaction) ([]*keys.PublicKey, error) {
panic("TODO") panic("TODO")
} }
func (chain testChain) GetEnrollments() ([]*state.Validator, error) {
panic("TODO")
}
func (chain testChain) GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error) { func (chain testChain) GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error) {
panic("TODO") panic("TODO")
} }

View file

@ -0,0 +1,14 @@
package result
import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// Validator used for the representation of
// state.Validator on the RPC Server.
type Validator struct {
PublicKey keys.PublicKey `json:"publickey"`
Votes util.Fixed8 `json:"votes"`
Active bool `json:"active"`
}

View file

@ -82,6 +82,13 @@ var (
Namespace: "neogo", Namespace: "neogo",
}, },
) )
getvalidatorsCalled = prometheus.NewCounter(
prometheus.CounterOpts{
Help: "Number of calls to getvalidators rpc endpoint",
Name: "getvalidators_called",
Namespace: "neogo",
},
)
getnep5balancesCalled = prometheus.NewCounter( getnep5balancesCalled = prometheus.NewCounter(
prometheus.CounterOpts{ prometheus.CounterOpts{
@ -215,6 +222,7 @@ func init() {
getblocksysfeeCalled, getblocksysfeeCalled,
getconnectioncountCalled, getconnectioncountCalled,
getcontractstateCalled, getcontractstateCalled,
getvalidatorsCalled,
getversionCalled, getversionCalled,
getpeersCalled, getpeersCalled,
getrawmempoolCalled, getrawmempoolCalled,

View file

@ -16,6 +16,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/network" "github.com/nspcc-dev/neo-go/pkg/network"
@ -214,6 +215,9 @@ Methods:
case "getnep5transfers": case "getnep5transfers":
getnep5transfersCalled.Inc() getnep5transfersCalled.Inc()
results, resultsErr = s.getNEP5Transfers(reqParams) results, resultsErr = s.getNEP5Transfers(reqParams)
case "getvalidators":
getvalidatorsCalled.Inc()
results, resultsErr = s.getValidators()
case "getversion": case "getversion":
getversionCalled.Inc() getversionCalled.Inc()
@ -764,6 +768,29 @@ func (s *Server) getBlockHeader(reqParams request.Params) (interface{}, error) {
return hex.EncodeToString(buf.Bytes()), nil return hex.EncodeToString(buf.Bytes()), nil
} }
// getValidators returns the current NEO consensus nodes information and voting status.
func (s *Server) getValidators() (interface{}, error) {
var validators keys.PublicKeys
validators, err := s.chain.GetValidators()
if err != nil {
return nil, err
}
enrollments, err := s.chain.GetEnrollments()
if err != nil {
return nil, err
}
var res []result.Validator
for _, v := range enrollments {
res = append(res, result.Validator{
PublicKey: *v.PublicKey,
Votes: v.Votes,
Active: validators.Contains(v.PublicKey),
})
}
return res, nil
}
// invoke implements the `invoke` RPC call. // invoke implements the `invoke` RPC call.
func (s *Server) invoke(reqParams request.Params) (interface{}, error) { func (s *Server) invoke(reqParams request.Params) (interface{}, error) {
scriptHashHex, ok := reqParams.ValueWithType(0, request.StringT) scriptHashHex, ok := reqParams.ValueWithType(0, request.StringT)

View file

@ -624,6 +624,31 @@ var rpcTestCases = map[string][]rpcTestCase{
}, },
}, },
}, },
"getvalidators": {
{
params: "[]",
result: func(*executor) interface{} {
return &[]result.Validator{}
},
check: func(t *testing.T, e *executor, validators interface{}) {
var expected []result.Validator
sBValidators, err := e.chain.GetStandByValidators()
require.NoError(t, err)
for _, sbValidator := range sBValidators {
expected = append(expected, result.Validator{
PublicKey: *sbValidator,
Votes: 0,
Active: true,
})
}
actual, ok := validators.(*[]result.Validator)
require.True(t, ok)
assert.ElementsMatch(t, expected, *actual)
},
},
},
"getversion": { "getversion": {
{ {
params: "[]", params: "[]",