core: switch to the new voting system (via native NEO contract)
It has all the methods required now, so you can register, vote and get voting results. Fixes #865.
This commit is contained in:
parent
2fa3bdf6a9
commit
b83e84ca08
13 changed files with 42 additions and 399 deletions
|
@ -479,22 +479,12 @@ func (s *service) getVerifiedTx(count int) []block.Transaction {
|
|||
return res
|
||||
}
|
||||
|
||||
func (s *service) getValidators(txx ...block.Transaction) []crypto.PublicKey {
|
||||
func (s *service) getValidators(_ ...block.Transaction) []crypto.PublicKey {
|
||||
var (
|
||||
pKeys []*keys.PublicKey
|
||||
err error
|
||||
)
|
||||
if len(txx) == 0 {
|
||||
pKeys, err = s.Chain.GetValidators()
|
||||
} else {
|
||||
ntxx := make([]*transaction.Transaction, len(txx))
|
||||
for i := range ntxx {
|
||||
ntxx[i] = txx[i].(*transaction.Transaction)
|
||||
}
|
||||
|
||||
pKeys, err = s.Chain.GetValidators(ntxx...)
|
||||
}
|
||||
|
||||
pKeys, err = s.Chain.GetValidators()
|
||||
if err != nil {
|
||||
s.log.Error("error while trying to get validators", zap.Error(err))
|
||||
}
|
||||
|
|
|
@ -630,14 +630,6 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
case *transaction.EnrollmentTX:
|
||||
if err := processEnrollmentTX(cache, t); err != nil {
|
||||
return err
|
||||
}
|
||||
case *transaction.StateTX:
|
||||
if err := bc.processStateTX(cache, tx, t); err != nil {
|
||||
return err
|
||||
}
|
||||
case *transaction.InvocationTX:
|
||||
systemInterop := bc.newInteropContext(trigger.Application, cache, block, tx)
|
||||
v := SpawnVM(systemInterop)
|
||||
|
@ -839,26 +831,6 @@ func processOutputs(tx *transaction.Transaction, dao *dao.Cached) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func processValidatorStateDescriptor(descriptor *transaction.StateDescriptor, dao *dao.Cached) error {
|
||||
publicKey := &keys.PublicKey{}
|
||||
err := publicKey.DecodeBytes(descriptor.Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
validatorState, err := dao.GetValidatorStateOrNew(publicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if descriptor.Field == "Registered" {
|
||||
if len(descriptor.Value) == 1 {
|
||||
validatorState.Registered = descriptor.Value[0] != 0
|
||||
return dao.PutValidatorState(validatorState)
|
||||
}
|
||||
return errors.New("bad descriptor value")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bc *Blockchain) processAccountStateDescriptor(descriptor *transaction.StateDescriptor, t *transaction.Transaction, dao *dao.Cached) error {
|
||||
hash, err := util.Uint160DecodeBytesBE(descriptor.Key)
|
||||
if err != nil {
|
||||
|
@ -1335,7 +1307,7 @@ func (bc *Blockchain) verifyTx(t *transaction.Transaction, block *block.Block) e
|
|||
for _, k := range votes {
|
||||
var isRegistered bool
|
||||
for i := range validators {
|
||||
if k.Equal(validators[i].PublicKey) {
|
||||
if k.Equal(validators[i].Key) {
|
||||
isRegistered = true
|
||||
break
|
||||
}
|
||||
|
@ -1631,128 +1603,14 @@ func (bc *Blockchain) GetStandByValidators() (keys.PublicKeys, error) {
|
|||
return getValidators(bc.config)
|
||||
}
|
||||
|
||||
// GetValidators returns validators.
|
||||
// Golang implementation of GetValidators method in C# (https://github.com/neo-project/neo/blob/c64748ecbac3baeb8045b16af0d518398a6ced24/neo/Persistence/Snapshot.cs#L182)
|
||||
func (bc *Blockchain) GetValidators(txes ...*transaction.Transaction) ([]*keys.PublicKey, error) {
|
||||
cache := dao.NewCached(bc.dao)
|
||||
if len(txes) > 0 {
|
||||
for _, tx := range txes {
|
||||
// iterate through outputs
|
||||
for index, output := range tx.Outputs {
|
||||
accountState, err := cache.GetAccountStateOrNew(output.ScriptHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accountState.Balances[output.AssetID] = append(accountState.Balances[output.AssetID], state.UnspentBalance{
|
||||
Tx: tx.Hash(),
|
||||
Index: uint16(index),
|
||||
Value: output.Amount,
|
||||
})
|
||||
if err := cache.PutAccountState(accountState); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// group inputs by the same previous hash and iterate through inputs
|
||||
group := make(map[util.Uint256][]*transaction.Input)
|
||||
for i := range tx.Inputs {
|
||||
hash := tx.Inputs[i].PrevHash
|
||||
group[hash] = append(group[hash], &tx.Inputs[i])
|
||||
}
|
||||
|
||||
for hash, inputs := range group {
|
||||
unspent, err := cache.GetUnspentCoinState(hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// process inputs
|
||||
for _, input := range inputs {
|
||||
prevOutput := &unspent.States[input.PrevIndex].Output
|
||||
accountState, err := cache.GetAccountStateOrNew(prevOutput.ScriptHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
delete(accountState.Balances, prevOutput.AssetID)
|
||||
if err = cache.PutAccountState(accountState); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch t := tx.Data.(type) {
|
||||
case *transaction.EnrollmentTX:
|
||||
if err := processEnrollmentTX(cache, t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *transaction.StateTX:
|
||||
if err := bc.processStateTX(cache, tx, t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bc.contracts.NEO.GetValidatorsInternal(bc, cache)
|
||||
// GetValidators returns next block validators.
|
||||
func (bc *Blockchain) GetValidators() ([]*keys.PublicKey, error) {
|
||||
return bc.contracts.NEO.GetNextBlockValidatorsInternal(bc, bc.dao)
|
||||
}
|
||||
|
||||
// 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 (bc *Blockchain) processStateTX(dao *dao.Cached, t *transaction.Transaction, tx *transaction.StateTX) error {
|
||||
for _, desc := range tx.Descriptors {
|
||||
switch desc.Type {
|
||||
case transaction.Account:
|
||||
if err := bc.processAccountStateDescriptor(desc, t, dao); err != nil {
|
||||
return err
|
||||
}
|
||||
case transaction.Validator:
|
||||
if err := processValidatorStateDescriptor(desc, dao); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func processEnrollmentTX(dao *dao.Cached, tx *transaction.EnrollmentTX) error {
|
||||
validatorState, err := dao.GetValidatorStateOrNew(&tx.PublicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
validatorState.Registered = true
|
||||
return dao.PutValidatorState(validatorState)
|
||||
// GetEnrollments returns all registered validators.
|
||||
func (bc *Blockchain) GetEnrollments() ([]state.Validator, error) {
|
||||
return bc.contracts.NEO.GetRegisteredValidators(bc.dao)
|
||||
}
|
||||
|
||||
// GetScriptHashesForVerifying returns all the ScriptHashes of a transaction which will be use
|
||||
|
|
|
@ -24,7 +24,7 @@ type Blockchainer interface {
|
|||
HeaderHeight() uint32
|
||||
GetBlock(hash util.Uint256) (*block.Block, error)
|
||||
GetContractState(hash util.Uint160) *state.Contract
|
||||
GetEnrollments() ([]*state.Validator, error)
|
||||
GetEnrollments() ([]state.Validator, error)
|
||||
GetHeaderHash(int) util.Uint256
|
||||
GetHeader(hash util.Uint256) (*block.Header, error)
|
||||
CurrentHeaderHash() util.Uint256
|
||||
|
@ -36,7 +36,7 @@ type Blockchainer interface {
|
|||
GetAppExecResult(util.Uint256) (*state.AppExecResult, error)
|
||||
GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog
|
||||
GetNEP5Balances(util.Uint160) *state.NEP5Balances
|
||||
GetValidators(txes ...*transaction.Transaction) ([]*keys.PublicKey, error)
|
||||
GetValidators() ([]*keys.PublicKey, error)
|
||||
GetStandByValidators() (keys.PublicKeys, error)
|
||||
GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error)
|
||||
GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||
"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/util"
|
||||
)
|
||||
|
@ -20,7 +19,6 @@ type DAO interface {
|
|||
AppendNEP5Transfer(acc util.Uint160, index uint32, tr *state.NEP5Transfer) (bool, error)
|
||||
DeleteContractState(hash util.Uint160) error
|
||||
DeleteStorageItem(scripthash util.Uint160, key []byte) error
|
||||
DeleteValidatorState(vs *state.Validator) error
|
||||
GetAccountState(hash util.Uint160) (*state.Account, error)
|
||||
GetAccountStateOrNew(hash util.Uint160) (*state.Account, error)
|
||||
GetAndDecode(entity io.Serializable, key []byte) error
|
||||
|
@ -39,9 +37,6 @@ type DAO interface {
|
|||
GetStorageItemsWithPrefix(hash util.Uint160, prefix []byte) (map[string]*state.StorageItem, error)
|
||||
GetTransaction(hash util.Uint256) (*transaction.Transaction, uint32, error)
|
||||
GetUnspentCoinState(hash util.Uint256) (*state.UnspentCoin, error)
|
||||
GetValidatorState(publicKey *keys.PublicKey) (*state.Validator, error)
|
||||
GetValidatorStateOrNew(publicKey *keys.PublicKey) (*state.Validator, error)
|
||||
GetValidators() []*state.Validator
|
||||
GetVersion() (string, error)
|
||||
GetWrapped() DAO
|
||||
HasTransaction(hash util.Uint256) bool
|
||||
|
@ -57,7 +52,6 @@ type DAO interface {
|
|||
PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.NEP5TransferLog) error
|
||||
PutStorageItem(scripthash util.Uint160, key []byte, si *state.StorageItem) error
|
||||
PutUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin) error
|
||||
PutValidatorState(vs *state.Validator) error
|
||||
PutVersion(v string) error
|
||||
StoreAsBlock(block *block.Block, sysFee uint32) error
|
||||
StoreAsCurrentBlock(block *block.Block) error
|
||||
|
@ -307,61 +301,6 @@ func (dao *Simple) putUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin
|
|||
|
||||
// -- end unspent coins.
|
||||
|
||||
// -- start validator.
|
||||
|
||||
// GetValidatorStateOrNew gets validator from store or created new one in case of error.
|
||||
func (dao *Simple) GetValidatorStateOrNew(publicKey *keys.PublicKey) (*state.Validator, error) {
|
||||
validatorState, err := dao.GetValidatorState(publicKey)
|
||||
if err != nil {
|
||||
if err != storage.ErrKeyNotFound {
|
||||
return nil, err
|
||||
}
|
||||
validatorState = &state.Validator{PublicKey: publicKey}
|
||||
}
|
||||
return validatorState, nil
|
||||
|
||||
}
|
||||
|
||||
// GetValidators returns all validators from store.
|
||||
func (dao *Simple) GetValidators() []*state.Validator {
|
||||
var validators []*state.Validator
|
||||
dao.Store.Seek(storage.STValidator.Bytes(), func(k, v []byte) {
|
||||
r := io.NewBinReaderFromBuf(v)
|
||||
validator := &state.Validator{}
|
||||
validator.DecodeBinary(r)
|
||||
if r.Err != nil {
|
||||
return
|
||||
}
|
||||
validators = append(validators, validator)
|
||||
})
|
||||
return validators
|
||||
}
|
||||
|
||||
// GetValidatorState returns validator by publicKey.
|
||||
func (dao *Simple) GetValidatorState(publicKey *keys.PublicKey) (*state.Validator, error) {
|
||||
validatorState := &state.Validator{}
|
||||
key := storage.AppendPrefix(storage.STValidator, publicKey.Bytes())
|
||||
err := dao.GetAndDecode(validatorState, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return validatorState, nil
|
||||
}
|
||||
|
||||
// PutValidatorState puts given Validator into the given store.
|
||||
func (dao *Simple) PutValidatorState(vs *state.Validator) error {
|
||||
key := storage.AppendPrefix(storage.STValidator, vs.PublicKey.Bytes())
|
||||
return dao.Put(vs, key)
|
||||
}
|
||||
|
||||
// DeleteValidatorState deletes given Validator into the given store.
|
||||
func (dao *Simple) DeleteValidatorState(vs *state.Validator) error {
|
||||
key := storage.AppendPrefix(storage.STValidator, vs.PublicKey.Bytes())
|
||||
return dao.Store.Delete(key)
|
||||
}
|
||||
|
||||
// -- end validator.
|
||||
|
||||
// -- start notification event.
|
||||
|
||||
// GetAppExecResult gets application execution result from the
|
||||
|
|
|
@ -113,61 +113,6 @@ func TestPutGetUnspentCoinState(t *testing.T) {
|
|||
require.Equal(t, unspentCoinState, gotUnspentCoinState)
|
||||
}
|
||||
|
||||
func TestGetValidatorStateOrNew_New(t *testing.T) {
|
||||
dao := NewSimple(storage.NewMemoryStore())
|
||||
publicKey := &keys.PublicKey{}
|
||||
validatorState, err := dao.GetValidatorStateOrNew(publicKey)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, validatorState)
|
||||
}
|
||||
|
||||
func TestPutGetValidatorState(t *testing.T) {
|
||||
dao := NewSimple(storage.NewMemoryStore())
|
||||
publicKey := &keys.PublicKey{}
|
||||
validatorState := &state.Validator{
|
||||
PublicKey: publicKey,
|
||||
Registered: false,
|
||||
Votes: 0,
|
||||
}
|
||||
err := dao.PutValidatorState(validatorState)
|
||||
require.NoError(t, err)
|
||||
gotValidatorState, err := dao.GetValidatorState(publicKey)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, validatorState, gotValidatorState)
|
||||
}
|
||||
|
||||
func TestDeleteValidatorState(t *testing.T) {
|
||||
dao := NewSimple(storage.NewMemoryStore())
|
||||
publicKey := &keys.PublicKey{}
|
||||
validatorState := &state.Validator{
|
||||
PublicKey: publicKey,
|
||||
Registered: false,
|
||||
Votes: 0,
|
||||
}
|
||||
err := dao.PutValidatorState(validatorState)
|
||||
require.NoError(t, err)
|
||||
err = dao.DeleteValidatorState(validatorState)
|
||||
require.NoError(t, err)
|
||||
gotValidatorState, err := dao.GetValidatorState(publicKey)
|
||||
require.Error(t, err)
|
||||
require.Nil(t, gotValidatorState)
|
||||
}
|
||||
|
||||
func TestGetValidators(t *testing.T) {
|
||||
dao := NewSimple(storage.NewMemoryStore())
|
||||
publicKey := &keys.PublicKey{}
|
||||
validatorState := &state.Validator{
|
||||
PublicKey: publicKey,
|
||||
Registered: false,
|
||||
Votes: 0,
|
||||
}
|
||||
err := dao.PutValidatorState(validatorState)
|
||||
require.NoError(t, err)
|
||||
validators := dao.GetValidators()
|
||||
require.Equal(t, validatorState, validators[0])
|
||||
require.Len(t, validators, 1)
|
||||
}
|
||||
|
||||
func TestPutGetAppExecResult(t *testing.T) {
|
||||
dao := NewSimple(storage.NewMemoryStore())
|
||||
hash := random.Uint256()
|
||||
|
|
|
@ -236,13 +236,6 @@ func witnessGetVerificationScript(ic *interop.Context, v *vm.VM) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// bcGetValidators returns validators.
|
||||
func bcGetValidators(ic *interop.Context, v *vm.VM) error {
|
||||
validators := ic.DAO.GetValidators()
|
||||
v.Estack().PushVal(validators)
|
||||
return nil
|
||||
}
|
||||
|
||||
// popInputFromVM returns transaction.Input from the first estack element.
|
||||
func popInputFromVM(v *vm.VM) (*transaction.Input, error) {
|
||||
inInterface := v.Estack().Pop().Value()
|
||||
|
|
|
@ -139,7 +139,6 @@ var neoInterops = []interop.Function{
|
|||
{Name: "Neo.Blockchain.GetHeight", Func: bcGetHeight, Price: 1},
|
||||
{Name: "Neo.Blockchain.GetTransaction", Func: bcGetTransaction, Price: 100},
|
||||
{Name: "Neo.Blockchain.GetTransactionHeight", Func: bcGetTransactionHeight, Price: 100},
|
||||
{Name: "Neo.Blockchain.GetValidators", Func: bcGetValidators, Price: 200},
|
||||
{Name: "Neo.Contract.Create", Func: contractCreate, Price: 0},
|
||||
{Name: "Neo.Contract.Destroy", Func: contractDestroy, Price: 1},
|
||||
{Name: "Neo.Contract.GetScript", Func: contractGetScript, Price: 1},
|
||||
|
@ -225,7 +224,6 @@ var neoInterops = []interop.Function{
|
|||
{Name: "AntShares.Blockchain.GetHeader", Func: bcGetHeader, Price: 100},
|
||||
{Name: "AntShares.Blockchain.GetHeight", Func: bcGetHeight, Price: 1},
|
||||
{Name: "AntShares.Blockchain.GetTransaction", Func: bcGetTransaction, Price: 100},
|
||||
{Name: "AntShares.Blockchain.GetValidators", Func: bcGetValidators, Price: 200},
|
||||
{Name: "AntShares.Contract.Create", Func: contractCreate, Price: 0},
|
||||
{Name: "AntShares.Contract.Destroy", Func: contractDestroy, Price: 1},
|
||||
{Name: "AntShares.Contract.GetScript", Func: contractGetScript, Price: 1},
|
||||
|
|
|
@ -31,12 +31,6 @@ type keyWithVotes struct {
|
|||
Votes *big.Int
|
||||
}
|
||||
|
||||
// pkeyWithVotes is a deserialized key with votes balance.
|
||||
type pkeyWithVotes struct {
|
||||
Key *keys.PublicKey
|
||||
Votes *big.Int
|
||||
}
|
||||
|
||||
const (
|
||||
neoSyscallName = "Neo.Native.Tokens.NEO"
|
||||
// NEOTotalSupply is the total amount of NEO in the system.
|
||||
|
@ -349,6 +343,24 @@ func (n *NEO) getRegisteredValidators(d dao.DAO) ([]keyWithVotes, error) {
|
|||
return arr, nil
|
||||
}
|
||||
|
||||
// GetRegisteredValidators returns current registered validators list with keys
|
||||
// and votes.
|
||||
func (n *NEO) GetRegisteredValidators(d dao.DAO) ([]state.Validator, error) {
|
||||
kvs, err := n.getRegisteredValidators(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arr := make([]state.Validator, len(kvs))
|
||||
for i := range kvs {
|
||||
arr[i].Key, err = keys.NewPublicKeyFromBytes([]byte(kvs[i].Key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arr[i].Votes = kvs[i].Votes
|
||||
}
|
||||
return arr, nil
|
||||
}
|
||||
|
||||
func (n *NEO) getRegisteredValidatorsCall(ic *interop.Context, _ []vm.StackItem) vm.StackItem {
|
||||
validators, err := n.getRegisteredValidators(ic.DAO)
|
||||
if err != nil {
|
||||
|
@ -374,18 +386,10 @@ func (n *NEO) GetValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) (ke
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
validatorsBytes, err := n.getRegisteredValidators(d)
|
||||
validators, err := n.GetRegisteredValidators(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
validators := make([]pkeyWithVotes, len(validatorsBytes))
|
||||
for i := range validatorsBytes {
|
||||
validators[i].Key, err = keys.NewPublicKeyFromBytes([]byte(validatorsBytes[i].Key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
validators[i].Votes = validatorsBytes[i].Votes
|
||||
}
|
||||
sort.Slice(validators, func(i, j int) bool {
|
||||
// The most-voted validators should end up in the front of the list.
|
||||
cmp := validators[i].Votes.Cmp(validators[j].Votes)
|
||||
|
@ -446,7 +450,7 @@ func (n *NEO) getNextBlockValidators(ic *interop.Context, _ []vm.StackItem) vm.S
|
|||
func (n *NEO) GetNextBlockValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) (keys.PublicKeys, error) {
|
||||
si := d.GetStorageItem(n.Hash, nextValidatorsKey)
|
||||
if si == nil {
|
||||
return bc.GetStandByValidators()
|
||||
return n.GetValidatorsInternal(bc, d)
|
||||
}
|
||||
pubs := keys.PublicKeys{}
|
||||
err := pubs.DecodeBytes(si.Value)
|
||||
|
|
|
@ -1,39 +1,13 @@
|
|||
package state
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
// Validator holds the state of a validator.
|
||||
// Validator holds the state of a validator (its key and votes balance).
|
||||
type Validator struct {
|
||||
PublicKey *keys.PublicKey
|
||||
Registered bool
|
||||
Votes util.Fixed8
|
||||
}
|
||||
|
||||
// RegisteredAndHasVotes returns true or false whether Validator is registered and has votes.
|
||||
func (vs *Validator) RegisteredAndHasVotes() bool {
|
||||
return vs.Registered && vs.Votes > util.Fixed8(0)
|
||||
}
|
||||
|
||||
// UnregisteredAndHasNoVotes returns true when Validator is not registered and has no votes.
|
||||
func (vs *Validator) UnregisteredAndHasNoVotes() bool {
|
||||
return !vs.Registered && vs.Votes == 0
|
||||
}
|
||||
|
||||
// EncodeBinary encodes Validator to the given BinWriter.
|
||||
func (vs *Validator) EncodeBinary(bw *io.BinWriter) {
|
||||
vs.PublicKey.EncodeBinary(bw)
|
||||
bw.WriteBool(vs.Registered)
|
||||
vs.Votes.EncodeBinary(bw)
|
||||
}
|
||||
|
||||
// DecodeBinary decodes Validator from the given BinReader.
|
||||
func (vs *Validator) DecodeBinary(reader *io.BinReader) {
|
||||
vs.PublicKey = &keys.PublicKey{}
|
||||
vs.PublicKey.DecodeBinary(reader)
|
||||
vs.Registered = reader.ReadBool()
|
||||
vs.Votes.DecodeBinary(reader)
|
||||
Key *keys.PublicKey
|
||||
Votes *big.Int
|
||||
}
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
package state
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestValidatorState_DecodeEncodeBinary(t *testing.T) {
|
||||
state := &Validator{
|
||||
PublicKey: &keys.PublicKey{},
|
||||
Registered: false,
|
||||
Votes: util.Fixed8(10),
|
||||
}
|
||||
|
||||
testserdes.EncodeDecodeBinary(t, state, new(Validator))
|
||||
}
|
||||
|
||||
func TestRegisteredAndHasVotes_Registered(t *testing.T) {
|
||||
state := &Validator{
|
||||
PublicKey: &keys.PublicKey{
|
||||
X: big.NewInt(1),
|
||||
Y: big.NewInt(1),
|
||||
},
|
||||
Registered: true,
|
||||
Votes: 0,
|
||||
}
|
||||
require.False(t, state.RegisteredAndHasVotes())
|
||||
}
|
||||
|
||||
func TestRegisteredAndHasVotes_RegisteredWithVotes(t *testing.T) {
|
||||
state := &Validator{
|
||||
PublicKey: &keys.PublicKey{
|
||||
X: big.NewInt(1),
|
||||
Y: big.NewInt(1),
|
||||
},
|
||||
Registered: true,
|
||||
Votes: 1,
|
||||
}
|
||||
require.True(t, state.RegisteredAndHasVotes())
|
||||
}
|
||||
|
||||
func TestRegisteredAndHasVotes_NotRegisteredWithVotes(t *testing.T) {
|
||||
state := &Validator{
|
||||
PublicKey: &keys.PublicKey{
|
||||
X: big.NewInt(1),
|
||||
Y: big.NewInt(1),
|
||||
},
|
||||
Registered: false,
|
||||
Votes: 1,
|
||||
}
|
||||
require.False(t, state.RegisteredAndHasVotes())
|
||||
}
|
|
@ -96,13 +96,13 @@ func (chain testChain) GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog {
|
|||
func (chain testChain) GetNEP5Balances(util.Uint160) *state.NEP5Balances {
|
||||
panic("TODO")
|
||||
}
|
||||
func (chain testChain) GetValidators(...*transaction.Transaction) ([]*keys.PublicKey, error) {
|
||||
func (chain testChain) GetValidators() ([]*keys.PublicKey, error) {
|
||||
panic("TODO")
|
||||
}
|
||||
func (chain testChain) GetStandByValidators() (keys.PublicKeys, error) {
|
||||
panic("TODO")
|
||||
}
|
||||
func (chain testChain) GetEnrollments() ([]*state.Validator, error) {
|
||||
func (chain testChain) GetEnrollments() ([]state.Validator, error) {
|
||||
panic("TODO")
|
||||
}
|
||||
func (chain testChain) GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error) {
|
||||
|
|
|
@ -2,13 +2,12 @@ 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"`
|
||||
Votes int64 `json:"votes,string"`
|
||||
Active bool `json:"active"`
|
||||
}
|
||||
|
|
|
@ -815,9 +815,9 @@ func (s *Server) getValidators(_ request.Params) (interface{}, error) {
|
|||
var res []result.Validator
|
||||
for _, v := range enrollments {
|
||||
res = append(res, result.Validator{
|
||||
PublicKey: *v.PublicKey,
|
||||
Votes: v.Votes,
|
||||
Active: validators.Contains(v.PublicKey),
|
||||
PublicKey: *v.Key,
|
||||
Votes: v.Votes.Int64(),
|
||||
Active: validators.Contains(v.Key),
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
|
|
Loading…
Reference in a new issue