From bc4a6a6babee07f46561cf50b22c6aa2e535fd9d Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Sun, 26 Apr 2020 13:42:05 +0300 Subject: [PATCH] core/native: move NextValidators storage to NEO contract --- pkg/core/dao/dao.go | 34 --------------------- pkg/core/native/native_neo.go | 57 ++++++++++++++++++----------------- pkg/core/storage/store.go | 1 - pkg/crypto/keys/publickey.go | 10 ++++++ 4 files changed, 40 insertions(+), 62 deletions(-) diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index 4618808c9..23fab4fc8 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -34,7 +34,6 @@ type DAO interface { GetHeaderHashes() ([]util.Uint256, error) GetNEP5Balances(acc util.Uint160) (*state.NEP5Balances, error) GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.NEP5TransferLog, error) - GetNextBlockValidators() (keys.PublicKeys, error) GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error) GetStorageItemsWithPrefix(hash util.Uint160, prefix []byte) (map[string]*state.StorageItem, error) @@ -56,7 +55,6 @@ type DAO interface { PutCurrentHeader(hashAndIndex []byte) error PutNEP5Balances(acc util.Uint160, bs *state.NEP5Balances) error PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.NEP5TransferLog) error - PutNextBlockValidators(keys.PublicKeys) error PutStorageItem(scripthash util.Uint160, key []byte, si *state.StorageItem) error PutUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin) error PutValidatorState(vs *state.Validator) error @@ -311,38 +309,6 @@ func (dao *Simple) putUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin // -- start validator. -// GetNextBlockValidators retrieves next block validators from store or nil if they are missing. -func (dao *Simple) GetNextBlockValidators() (keys.PublicKeys, error) { - key := []byte{byte(storage.STNextValidators)} - buf, err := dao.Store.Get(key) - if err != nil { - if err == storage.ErrKeyNotFound { - return nil, nil - } - return nil, err - } - - var pubs keys.PublicKeys - r := io.NewBinReaderFromBuf(buf) - r.ReadArray(&pubs) - if r.Err != nil { - return nil, r.Err - } - return pubs, nil -} - -// PutNextBlockValidators puts next block validators to store. -func (dao *Simple) PutNextBlockValidators(pubs keys.PublicKeys) error { - w := io.NewBufBinWriter() - w.WriteArray(pubs) - if w.Err != nil { - return w.Err - } - - key := []byte{byte(storage.STNextValidators)} - return dao.Store.Put(key, w.Bytes()) -} - // 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) diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 9ce5523d2..3f7400dd0 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -147,10 +147,9 @@ func (n *NEO) OnPersist(ic *interop.Context) error { if err != nil { return err } - if err := ic.DAO.PutNextBlockValidators(pubs); err != nil { - return err - } - return nil + si := new(state.StorageItem) + si.Value = pubs.Bytes() + return ic.DAO.PutStorageItem(n.Hash, nextValidatorsKey, si) } func (n *NEO) increaseBalance(ic *interop.Context, h util.Uint160, si *state.StorageItem, amount *big.Int) error { @@ -171,23 +170,24 @@ func (n *NEO) increaseBalance(ic *interop.Context, h util.Uint160, si *state.Sto if err != nil { return err } - if err := n.ModifyAccountVotes(oldAcc, ic.DAO, new(big.Int).Neg(&acc.Balance)); err != nil { - return err + if len(oldAcc.Votes) > 0 { + if err := n.ModifyAccountVotes(oldAcc, ic.DAO, new(big.Int).Neg(&acc.Balance)); err != nil { + return err + } + siVC := ic.DAO.GetStorageItem(n.Hash, validatorsCountKey) + if siVC == nil { + return errors.New("validators count uninitialized") + } + vc, err := ValidatorsCountFromBytes(siVC.Value) + if err != nil { + return err + } + vc[len(oldAcc.Votes)-1].Add(&vc[len(oldAcc.Votes)-1], amount) + siVC.Value = vc.Bytes() + if err := ic.DAO.PutStorageItem(n.Hash, validatorsCountKey, siVC); err != nil { + return err + } } - siVC := ic.DAO.GetStorageItem(n.Hash, validatorsCountKey) - if siVC == nil { - return errors.New("validators count uninitialized") - } - vc, err := ValidatorsCountFromBytes(siVC.Value) - if err != nil { - return err - } - vc[len(oldAcc.Votes)-1].Add(&vc[len(oldAcc.Votes)-1], amount) - siVC.Value = vc.Bytes() - if err := ic.DAO.PutStorageItem(n.Hash, validatorsCountKey, siVC); err != nil { - return err - } - acc.Balance.Add(&acc.Balance, amount) si.Value = acc.Bytes() return nil @@ -372,7 +372,7 @@ func (n *NEO) getRegisteredValidatorsCall(ic *interop.Context, _ []vm.StackItem) } // GetValidatorsInternal returns a list of current validators. -func (n *NEO) GetValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) ([]*keys.PublicKey, error) { +func (n *NEO) GetValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) (keys.PublicKeys, error) { si := d.GetStorageItem(n.Hash, validatorsCountKey) if si == nil { return nil, errors.New("validators count uninitialized") @@ -450,14 +450,17 @@ func (n *NEO) getNextBlockValidators(ic *interop.Context, _ []vm.StackItem) vm.S } // GetNextBlockValidatorsInternal returns next block validators. -func (n *NEO) GetNextBlockValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) ([]*keys.PublicKey, error) { - result, err := d.GetNextBlockValidators() - if err != nil { - return nil, err - } else if result == nil { +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 result, nil + pubs := keys.PublicKeys{} + err := pubs.DecodeBytes(si.Value) + if err != nil { + return nil, err + } + return pubs, nil } func pubsToArray(pubs keys.PublicKeys) vm.StackItem { diff --git a/pkg/core/storage/store.go b/pkg/core/storage/store.go index 6726ff58c..12a46dd69 100644 --- a/pkg/core/storage/store.go +++ b/pkg/core/storage/store.go @@ -12,7 +12,6 @@ const ( STAccount KeyPrefix = 0x40 STCoin KeyPrefix = 0x44 STSpentCoin KeyPrefix = 0x45 - STNextValidators KeyPrefix = 0x47 STValidator KeyPrefix = 0x48 STAsset KeyPrefix = 0x4c STNotification KeyPrefix = 0x4d diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index 063995201..d03bdb22b 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -35,6 +35,16 @@ func (keys *PublicKeys) DecodeBytes(data []byte) error { return b.Err } +// Bytes encodes PublicKeys to the new slice of bytes. +func (keys *PublicKeys) Bytes() []byte { + buf := io.NewBufBinWriter() + buf.WriteArray(*keys) + if buf.Err != nil { + panic(buf.Err) + } + return buf.Bytes() +} + // Contains checks whether passed param contained in PublicKeys. func (keys PublicKeys) Contains(pKey *PublicKey) bool { for _, key := range keys {