[#421] morph/client: Add committee list getter

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2021-03-09 17:45:35 +03:00 committed by Alex Vanin
parent 65c04284e7
commit 0cd7fa415f
2 changed files with 57 additions and 0 deletions

View file

@ -2,10 +2,12 @@ package client
import ( import (
"context" "context"
"crypto/elliptic"
"time" "time"
"github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/native"
"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/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/rpc/client" "github.com/nspcc-dev/neo-go/pkg/rpc/client"
sc "github.com/nspcc-dev/neo-go/pkg/smartcontract" sc "github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -33,6 +35,8 @@ type Client struct {
gas util.Uint160 // native gas script-hash gas util.Uint160 // native gas script-hash
neo util.Uint160 // native neo script-hash
waitInterval time.Duration waitInterval time.Duration
notary *notary notary *notary
@ -45,6 +49,10 @@ var ErrNilClient = errors.New("client is nil")
// HaltState returned if TestInvoke function processed without panic. // HaltState returned if TestInvoke function processed without panic.
const HaltState = "HALT" const HaltState = "HALT"
const (
committeeList = "getCommittee"
)
var errEmptyInvocationScript = errors.New("got empty invocation script from neo node") var errEmptyInvocationScript = errors.New("got empty invocation script from neo node")
var errScriptDecode = errors.New("could not decode invocation script from neo node") var errScriptDecode = errors.New("could not decode invocation script from neo node")
@ -191,6 +199,21 @@ func (c *Client) GasBalance() (int64, error) {
return c.client.NEP17BalanceOf(c.gas, c.acc.PrivateKey().GetScriptHash()) return c.client.NEP17BalanceOf(c.gas, c.acc.PrivateKey().GetScriptHash())
} }
// Committee returns keys of chain committee from neo native contract.
func (c *Client) Committee() (keys.PublicKeys, error) {
items, err := c.TestInvoke(c.neo, committeeList)
if err != nil {
return nil, err
}
roleKeys, err := keysFromStack(items)
if err != nil {
return nil, errors.Wrap(err, "can't get committee keys")
}
return roleKeys, nil
}
func toStackParameter(value interface{}) (sc.Parameter, error) { func toStackParameter(value interface{}) (sc.Parameter, error) {
var result = sc.Parameter{ var result = sc.Parameter{
Value: value, Value: value,
@ -237,6 +260,34 @@ func toStackParameter(value interface{}) (sc.Parameter, error) {
return result, nil return result, nil
} }
func keysFromStack(data []stackitem.Item) (keys.PublicKeys, error) {
if len(data) == 0 {
return nil, nil
}
arr, err := ArrayFromStackItem(data[0])
if err != nil {
return nil, errors.Wrap(err, "non array element on stack")
}
res := make([]*keys.PublicKey, 0, len(arr))
for i := range arr {
rawKey, err := BytesFromStackItem(arr[i])
if err != nil {
return nil, errors.Wrap(err, "key is not slice of bytes")
}
key, err := keys.NewPublicKeyFromBytes(rawKey, elliptic.P256())
if err != nil {
return nil, errors.Wrap(err, "can't parse key")
}
res = append(res, key)
}
return res, nil
}
// MagicNumber returns the magic number of the network // MagicNumber returns the magic number of the network
// to which the underlying RPC node client is connected. // to which the underlying RPC node client is connected.
func (c *Client) MagicNumber() uint64 { func (c *Client) MagicNumber() uint64 {

View file

@ -100,11 +100,17 @@ func New(key *ecdsa.PrivateKey, endpoint string, opts ...Option) (*Client, error
return nil, err return nil, err
} }
neo, err := cli.GetNativeContractHash(nativenames.Neo)
if err != nil {
return nil, err
}
return &Client{ return &Client{
logger: cfg.logger, logger: cfg.logger,
client: cli, client: cli,
acc: account, acc: account,
gas: gas, gas: gas,
neo: neo,
waitInterval: cfg.waitInterval, waitInterval: cfg.waitInterval,
}, nil }, nil
} }