core, rpc: add GetCommittee method

Closes #1414
This commit is contained in:
Anna Shaleva 2020-09-21 15:34:04 +03:00
parent dbfdfd8e9b
commit 770c8d774c
7 changed files with 74 additions and 0 deletions

View file

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"math/big"
"sort"
"sync"
"sync/atomic"
"time"
@ -1403,6 +1404,16 @@ func (bc *Blockchain) GetStandByCommittee() keys.PublicKeys {
return bc.sbCommittee.Copy()
}
// GetCommittee returns the sorted list of public keys of nodes in committee.
func (bc *Blockchain) GetCommittee() (keys.PublicKeys, error) {
pubs, err := bc.contracts.NEO.GetCommitteeMembers(bc, bc.dao)
if err != nil {
return nil, err
}
sort.Sort(pubs)
return pubs, nil
}
// GetValidators returns current validators.
func (bc *Blockchain) GetValidators() ([]*keys.PublicKey, error) {
return bc.contracts.NEO.GetValidatorsInternal(bc, bc.dao)

View file

@ -26,6 +26,7 @@ type Blockchainer interface {
Close()
HeaderHeight() uint32
GetBlock(hash util.Uint256) (*block.Block, error)
GetCommittee() (keys.PublicKeys, error)
GetContractState(hash util.Uint160) *state.Contract
GetContractScriptHash(id int32) (util.Uint160, error)
GetEnrollments() ([]state.Validator, error)

View file

@ -76,6 +76,9 @@ func (chain testChain) GetAppExecResult(hash util.Uint256) (*state.AppExecResult
func (chain testChain) GetBlock(hash util.Uint256) (*block.Block, error) {
panic("TODO")
}
func (chain testChain) GetCommittee() (keys.PublicKeys, error) {
panic("TODO")
}
func (chain testChain) GetContractState(hash util.Uint160) *state.Contract {
panic("TODO")
}

View file

@ -9,6 +9,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/block"
"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/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
@ -179,6 +180,18 @@ func (c *Client) GetConnectionCount() (int, error) {
return resp, nil
}
// GetCommittee returns the current public keys of NEO nodes in committee.
func (c *Client) GetCommittee() (keys.PublicKeys, error) {
var (
params = request.NewRawParams()
resp = new(keys.PublicKeys)
)
if err := c.performRequest("getcommittee", params, resp); err != nil {
return nil, err
}
return *resp, nil
}
// GetContractState queries contract information, according to the contract script hash.
func (c *Client) GetContractState(hash util.Uint160) (*state.Contract, error) {
var (

View file

@ -19,6 +19,7 @@ import (
"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/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/internal/testserdes"
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
@ -30,6 +31,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -284,6 +286,22 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
},
},
},
"getcommittee": {
{
name: "positive",
invoke: func(c *Client) (interface{}, error) {
return c.GetCommittee()
},
serverResponse: `{"jsonrpc":"2.0","id":1,"result":["02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e"]}`,
result: func(c *Client) interface{} {
member, err := keys.NewPublicKeyFromString("02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e")
if err != nil {
panic(errors.Wrap(err, "failed to decode public key"))
}
return keys.PublicKeys{member}
},
},
},
"getconnectioncount": {
{
name: "positive",
@ -1068,6 +1086,12 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{
return c.GetBlockSysFee(1)
},
},
{
name: "getcommittee_unmarshalling_error",
invoke: func(c *Client) (interface{}, error) {
return c.GetCommittee()
},
},
{
name: "getconnectioncount_unmarshalling_error",
invoke: func(c *Client) (interface{}, error) {

View file

@ -87,6 +87,7 @@ var rpcHandlers = map[string]func(*Server, request.Params) (interface{}, *respon
"getblockhash": (*Server).getBlockHash,
"getblockheader": (*Server).getBlockHeader,
"getblocksysfee": (*Server).getBlockSysFee,
"getcommittee": (*Server).getCommittee,
"getconnectioncount": (*Server).getConnectionCount,
"getcontractstate": (*Server).getContractState,
"getnep5balances": (*Server).getNEP5Balances,
@ -881,6 +882,15 @@ func (s *Server) getValidators(_ request.Params) (interface{}, *response.Error)
return res, nil
}
// getCommittee returns the current list of NEO committee members
func (s *Server) getCommittee(_ request.Params) (interface{}, *response.Error) {
keys, err := s.chain.GetCommittee()
if err != nil {
return nil, response.NewInternalServerError("can't get committee members", err)
}
return keys, nil
}
// invokeFunction implements the `invokeFunction` RPC call.
func (s *Server) invokeFunction(reqParams request.Params) (interface{}, *response.Error) {
scriptHash, err := reqParams.ValueWithType(0, request.StringT).GetUint160FromHex()

View file

@ -10,6 +10,7 @@ import (
"net/http"
"net/http/httptest"
"reflect"
"sort"
"strconv"
"strings"
"testing"
@ -353,6 +354,17 @@ var rpcTestCases = map[string][]rpcTestCase{
fail: true,
},
},
"getcommittee": {
{
params: "[]",
result: func(e *executor) interface{} {
// it's a test chain, so committee is a sorted standby committee
expected := e.chain.GetStandByCommittee()
sort.Sort(expected)
return &expected
},
},
},
"getconnectioncount": {
{
params: "[]",