mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 13:41:37 +00:00
core/native: move Votes from account to native NEO state
This commit is contained in:
parent
bc4a6a6bab
commit
2fa3bdf6a9
10 changed files with 18 additions and 72 deletions
|
@ -404,24 +404,6 @@ func accountGetScriptHash(ic *interop.Context, v *vm.VM) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// accountGetVotes returns votes of a given account.
|
||||
func accountGetVotes(ic *interop.Context, v *vm.VM) error {
|
||||
accInterface := v.Estack().Pop().Value()
|
||||
acc, ok := accInterface.(*state.Account)
|
||||
if !ok {
|
||||
return fmt.Errorf("%T is not an account state", acc)
|
||||
}
|
||||
if len(acc.Votes) > vm.MaxArraySize {
|
||||
return errors.New("too many votes")
|
||||
}
|
||||
votes := make([]vm.StackItem, 0, len(acc.Votes))
|
||||
for _, key := range acc.Votes {
|
||||
votes = append(votes, vm.NewByteArrayItem(key.Bytes()))
|
||||
}
|
||||
v.Estack().PushVal(votes)
|
||||
return nil
|
||||
}
|
||||
|
||||
// accountIsStandard checks whether given account is standard.
|
||||
func accountIsStandard(ic *interop.Context, v *vm.VM) error {
|
||||
accbytes := v.Estack().Pop().Bytes()
|
||||
|
|
|
@ -417,17 +417,6 @@ func TestAccountGetScriptHash(t *testing.T) {
|
|||
require.Equal(t, accState.ScriptHash.BytesBE(), hash)
|
||||
}
|
||||
|
||||
func TestAccountGetVotes(t *testing.T) {
|
||||
v, accState, context, chain := createVMAndAccState(t)
|
||||
defer chain.Close()
|
||||
v.Estack().PushVal(vm.NewInteropItem(accState))
|
||||
|
||||
err := accountGetVotes(context, v)
|
||||
require.NoError(t, err)
|
||||
votes := v.Estack().Pop().Value().([]vm.StackItem)
|
||||
require.Equal(t, vm.NewByteArrayItem(accState.Votes[0].Bytes()), votes[0])
|
||||
}
|
||||
|
||||
func TestContractGetScript(t *testing.T) {
|
||||
v, contractState, context, chain := createVMAndContractState(t)
|
||||
defer chain.Close()
|
||||
|
@ -603,9 +592,6 @@ func createVMAndAccState(t *testing.T) (*vm.VM, *state.Account, *interop.Context
|
|||
hash, err := util.Uint160DecodeStringBE(rawHash)
|
||||
accountState := state.NewAccount(hash)
|
||||
|
||||
key := &keys.PublicKey{X: big.NewInt(1), Y: big.NewInt(1)}
|
||||
accountState.Votes = []*keys.PublicKey{key}
|
||||
|
||||
require.NoError(t, err)
|
||||
chain := newTestChain(t)
|
||||
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, nil)
|
||||
|
|
|
@ -115,7 +115,6 @@ var systemInterops = []interop.Function{
|
|||
var neoInterops = []interop.Function{
|
||||
{Name: "Neo.Account.GetBalance", Func: accountGetBalance, Price: 1},
|
||||
{Name: "Neo.Account.GetScriptHash", Func: accountGetScriptHash, Price: 1},
|
||||
{Name: "Neo.Account.GetVotes", Func: accountGetVotes, Price: 1},
|
||||
{Name: "Neo.Account.IsStandard", Func: accountIsStandard, Price: 100},
|
||||
{Name: "Neo.Asset.Create", Func: assetCreate, Price: 0},
|
||||
{Name: "Neo.Asset.GetAdmin", Func: assetGetAdmin, Price: 1},
|
||||
|
@ -204,7 +203,6 @@ var neoInterops = []interop.Function{
|
|||
// Old compatibility APIs.
|
||||
{Name: "AntShares.Account.GetBalance", Func: accountGetBalance, Price: 1},
|
||||
{Name: "AntShares.Account.GetScriptHash", Func: accountGetScriptHash, Price: 1},
|
||||
{Name: "AntShares.Account.GetVotes", Func: accountGetVotes, Price: 1},
|
||||
{Name: "AntShares.Asset.Create", Func: assetCreate, Price: 0},
|
||||
{Name: "AntShares.Asset.GetAdmin", Func: assetGetAdmin, Price: 1},
|
||||
{Name: "AntShares.Asset.GetAmount", Func: assetGetAmount, Price: 1},
|
||||
|
|
|
@ -34,7 +34,6 @@ func TestUnexpectedNonInterops(t *testing.T) {
|
|||
funcs := []func(*interop.Context, *vm.VM) error{
|
||||
accountGetBalance,
|
||||
accountGetScriptHash,
|
||||
accountGetVotes,
|
||||
assetGetAdmin,
|
||||
assetGetAmount,
|
||||
assetGetAssetID,
|
||||
|
|
|
@ -166,12 +166,8 @@ func (n *NEO) increaseBalance(ic *interop.Context, h util.Uint160, si *state.Sto
|
|||
if amount.Sign() == 0 {
|
||||
return nil
|
||||
}
|
||||
oldAcc, err := ic.DAO.GetAccountState(h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(oldAcc.Votes) > 0 {
|
||||
if err := n.ModifyAccountVotes(oldAcc, ic.DAO, new(big.Int).Neg(&acc.Balance)); err != nil {
|
||||
if len(acc.Votes) > 0 {
|
||||
if err := n.ModifyAccountVotes(acc, ic.DAO, new(big.Int).Neg(&acc.Balance)); err != nil {
|
||||
return err
|
||||
}
|
||||
siVC := ic.DAO.GetStorageItem(n.Hash, validatorsCountKey)
|
||||
|
@ -182,7 +178,7 @@ func (n *NEO) increaseBalance(ic *interop.Context, h util.Uint160, si *state.Sto
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vc[len(oldAcc.Votes)-1].Add(&vc[len(oldAcc.Votes)-1], amount)
|
||||
vc[len(acc.Votes)-1].Add(&vc[len(acc.Votes)-1], amount)
|
||||
siVC.Value = vc.Bytes()
|
||||
if err := ic.DAO.PutStorageItem(n.Hash, validatorsCountKey, siVC); err != nil {
|
||||
return err
|
||||
|
@ -276,11 +272,7 @@ func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pubs keys.Public
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldAcc, err := ic.DAO.GetAccountState(h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := n.ModifyAccountVotes(oldAcc, ic.DAO, new(big.Int).Neg(&acc.Balance)); err != nil {
|
||||
if err := n.ModifyAccountVotes(acc, ic.DAO, new(big.Int).Neg(&acc.Balance)); err != nil {
|
||||
return err
|
||||
}
|
||||
pubs = pubs.Unique()
|
||||
|
@ -292,7 +284,7 @@ func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pubs keys.Public
|
|||
}
|
||||
newPubs = append(newPubs, pub)
|
||||
}
|
||||
if lp, lv := len(newPubs), len(oldAcc.Votes); lp != lv {
|
||||
if lp, lv := len(newPubs), len(acc.Votes); lp != lv {
|
||||
si := ic.DAO.GetStorageItem(n.Hash, validatorsCountKey)
|
||||
if si == nil {
|
||||
return errors.New("validators count uninitialized")
|
||||
|
@ -312,15 +304,16 @@ func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pubs keys.Public
|
|||
return err
|
||||
}
|
||||
}
|
||||
oldAcc.Votes = newPubs
|
||||
if err := n.ModifyAccountVotes(oldAcc, ic.DAO, &acc.Balance); err != nil {
|
||||
acc.Votes = newPubs
|
||||
if err := n.ModifyAccountVotes(acc, ic.DAO, &acc.Balance); err != nil {
|
||||
return err
|
||||
}
|
||||
return ic.DAO.PutAccountState(oldAcc)
|
||||
si.Value = acc.Bytes()
|
||||
return ic.DAO.PutStorageItem(n.Hash, key, si)
|
||||
}
|
||||
|
||||
// ModifyAccountVotes modifies votes of the specified account by value (can be negative).
|
||||
func (n *NEO) ModifyAccountVotes(acc *state.Account, d dao.DAO, value *big.Int) error {
|
||||
func (n *NEO) ModifyAccountVotes(acc *state.NEOBalanceState, d dao.DAO, value *big.Int) error {
|
||||
for _, vote := range acc.Votes {
|
||||
key := makeValidatorKey(vote)
|
||||
si := d.GetStorageItem(n.Hash, key)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package state
|
||||
|
||||
import (
|
||||
"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"
|
||||
)
|
||||
|
@ -32,7 +31,6 @@ type Account struct {
|
|||
Version uint8
|
||||
ScriptHash util.Uint160
|
||||
IsFrozen bool
|
||||
Votes []*keys.PublicKey
|
||||
Balances map[util.Uint256][]UnspentBalance
|
||||
Unclaimed UnclaimedBalances
|
||||
}
|
||||
|
@ -43,7 +41,6 @@ func NewAccount(scriptHash util.Uint160) *Account {
|
|||
Version: 0,
|
||||
ScriptHash: scriptHash,
|
||||
IsFrozen: false,
|
||||
Votes: []*keys.PublicKey{},
|
||||
Balances: make(map[util.Uint256][]UnspentBalance),
|
||||
Unclaimed: UnclaimedBalances{Raw: []byte{}},
|
||||
}
|
||||
|
@ -54,7 +51,6 @@ func (s *Account) DecodeBinary(br *io.BinReader) {
|
|||
s.Version = uint8(br.ReadB())
|
||||
br.ReadBytes(s.ScriptHash[:])
|
||||
s.IsFrozen = br.ReadBool()
|
||||
br.ReadArray(&s.Votes)
|
||||
|
||||
s.Balances = make(map[util.Uint256][]UnspentBalance)
|
||||
lenBalances := br.ReadVarUint()
|
||||
|
@ -79,7 +75,6 @@ func (s *Account) EncodeBinary(bw *io.BinWriter) {
|
|||
bw.WriteB(byte(s.Version))
|
||||
bw.WriteBytes(s.ScriptHash[:])
|
||||
bw.WriteBool(s.IsFrozen)
|
||||
bw.WriteArray(s.Votes)
|
||||
|
||||
bw.WriteVarUint(uint64(len(s.Balances)))
|
||||
for k, v := range s.Balances {
|
||||
|
|
|
@ -3,7 +3,6 @@ package state
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/internal/random"
|
||||
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
|
@ -14,7 +13,6 @@ func TestDecodeEncodeAccountState(t *testing.T) {
|
|||
var (
|
||||
n = 10
|
||||
balances = make(map[util.Uint256][]UnspentBalance)
|
||||
votes = make([]*keys.PublicKey, n)
|
||||
)
|
||||
for i := 0; i < n; i++ {
|
||||
asset := random.Uint256()
|
||||
|
@ -25,16 +23,12 @@ func TestDecodeEncodeAccountState(t *testing.T) {
|
|||
Value: util.Fixed8(int64(random.Int(1, 10000))),
|
||||
})
|
||||
}
|
||||
k, err := keys.NewPrivateKey()
|
||||
assert.Nil(t, err)
|
||||
votes[i] = k.PublicKey()
|
||||
}
|
||||
|
||||
a := &Account{
|
||||
Version: 0,
|
||||
ScriptHash: random.Uint160(),
|
||||
IsFrozen: true,
|
||||
Votes: votes,
|
||||
Balances: balances,
|
||||
Unclaimed: UnclaimedBalances{Raw: []byte{}},
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ 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/vm/emit"
|
||||
)
|
||||
|
@ -16,6 +17,7 @@ type NEP5BalanceState struct {
|
|||
type NEOBalanceState struct {
|
||||
NEP5BalanceState
|
||||
BalanceHeight uint32
|
||||
Votes keys.PublicKeys
|
||||
}
|
||||
|
||||
// NEP5BalanceStateFromBytes converts serialized NEP5BalanceState to structure.
|
||||
|
@ -85,10 +87,12 @@ func (s *NEOBalanceState) Bytes() []byte {
|
|||
func (s *NEOBalanceState) EncodeBinary(w *io.BinWriter) {
|
||||
s.NEP5BalanceState.EncodeBinary(w)
|
||||
w.WriteU32LE(s.BalanceHeight)
|
||||
w.WriteArray(s.Votes)
|
||||
}
|
||||
|
||||
// DecodeBinary implements io.Serializable interface.
|
||||
func (s *NEOBalanceState) DecodeBinary(r *io.BinReader) {
|
||||
s.NEP5BalanceState.DecodeBinary(r)
|
||||
s.BalanceHeight = r.ReadU32LE()
|
||||
r.ReadArray(&s.Votes)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"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/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
||||
|
@ -49,7 +48,6 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
Version: 0,
|
||||
ScriptHash: scriptHash,
|
||||
IsFrozen: false,
|
||||
Votes: []*keys.PublicKey{},
|
||||
Balances: result.Balances{
|
||||
result.Balance{
|
||||
Asset: core.GoverningTokenID(),
|
||||
|
|
|
@ -5,18 +5,16 @@ import (
|
|||
"sort"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
// AccountState wrapper used for the representation of
|
||||
// state.Account on the RPC Server.
|
||||
type AccountState struct {
|
||||
Version uint8 `json:"version"`
|
||||
ScriptHash util.Uint160 `json:"script_hash"`
|
||||
IsFrozen bool `json:"frozen"`
|
||||
Votes []*keys.PublicKey `json:"votes"`
|
||||
Balances []Balance `json:"balances"`
|
||||
Version uint8 `json:"version"`
|
||||
ScriptHash util.Uint160 `json:"script_hash"`
|
||||
IsFrozen bool `json:"frozen"`
|
||||
Balances []Balance `json:"balances"`
|
||||
}
|
||||
|
||||
// Balances type for sorting balances in rpc response.
|
||||
|
@ -48,7 +46,6 @@ func NewAccountState(a *state.Account) AccountState {
|
|||
Version: a.Version,
|
||||
ScriptHash: a.ScriptHash,
|
||||
IsFrozen: a.IsFrozen,
|
||||
Votes: a.Votes,
|
||||
Balances: balances,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue