state: make NEP5Transfer log more generic

This commit is contained in:
Evgenii Stratonikov 2020-08-04 16:55:45 +03:00
parent 49f9c4ad7e
commit e4fcd90b6d
8 changed files with 35 additions and 34 deletions

View file

@ -972,12 +972,12 @@ func (bc *Blockchain) processNEP5Transfer(cache *dao.Cached, tx *transaction.Tra
}
// GetNEP5TransferLog returns NEP5 transfer log for the acc.
func (bc *Blockchain) GetNEP5TransferLog(acc util.Uint160) *state.NEP5TransferLog {
func (bc *Blockchain) GetNEP5TransferLog(acc util.Uint160) *state.TransferLog {
balances, err := bc.dao.GetNEP5Balances(acc)
if err != nil {
return nil
}
result := new(state.NEP5TransferLog)
result := new(state.TransferLog)
for i := uint32(0); i <= balances.NextTransferBatch; i++ {
lg, err := bc.dao.GetNEP5TransferLog(acc, i)
if err != nil {

View file

@ -36,7 +36,7 @@ type Blockchainer interface {
GetAccountState(util.Uint160) *state.Account
GetAppExecResult(util.Uint256) (*state.AppExecResult, error)
GetNEP5Metadata(util.Uint160) (*state.NEP5Metadata, error)
GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog
GetNEP5TransferLog(util.Uint160) *state.TransferLog
GetNEP5Balances(util.Uint160) *state.NEP5Balances
GetValidators(txes ...*transaction.Transaction) ([]*keys.PublicKey, error)
GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error)

View file

@ -20,7 +20,7 @@ type Cached struct {
contracts map[util.Uint160]*state.Contract
unspents map[util.Uint256]*state.UnspentCoin
balances map[util.Uint160]*state.NEP5Balances
nep5transfers map[util.Uint160]map[uint32]*state.NEP5TransferLog
nep5transfers map[util.Uint160]map[uint32]*state.TransferLog
storage *itemCache
dropNEP5Cache bool
@ -32,7 +32,7 @@ func NewCached(d DAO) *Cached {
ctrs := make(map[util.Uint160]*state.Contract)
unspents := make(map[util.Uint256]*state.UnspentCoin)
balances := make(map[util.Uint160]*state.NEP5Balances)
nep5transfers := make(map[util.Uint160]map[uint32]*state.NEP5TransferLog)
nep5transfers := make(map[util.Uint160]map[uint32]*state.TransferLog)
st := newItemCache()
dao := d.GetWrapped()
if cd, ok := dao.(*Cached); ok {
@ -120,8 +120,8 @@ func (cd *Cached) PutNEP5Balances(acc util.Uint160, bs *state.NEP5Balances) erro
return nil
}
// GetNEP5TransferLog retrieves NEP5TransferLog for the acc.
func (cd *Cached) GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.NEP5TransferLog, error) {
// GetNEP5TransferLog retrieves TransferLog for the acc.
func (cd *Cached) GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.TransferLog, error) {
ts := cd.nep5transfers[acc]
if ts != nil && ts[index] != nil {
return ts[index], nil
@ -129,11 +129,11 @@ func (cd *Cached) GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.NEP
return cd.DAO.GetNEP5TransferLog(acc, index)
}
// PutNEP5TransferLog saves NEP5TransferLog for the acc.
func (cd *Cached) PutNEP5TransferLog(acc util.Uint160, index uint32, bs *state.NEP5TransferLog) error {
// PutNEP5TransferLog saves TransferLog for the acc.
func (cd *Cached) PutNEP5TransferLog(acc util.Uint160, index uint32, bs *state.TransferLog) error {
ts := cd.nep5transfers[acc]
if ts == nil {
ts = make(map[uint32]*state.NEP5TransferLog, 2)
ts = make(map[uint32]*state.TransferLog, 2)
cd.nep5transfers[acc] = ts
}
ts[index] = bs

View file

@ -36,7 +36,7 @@ type DAO interface {
GetHeaderHashes() ([]util.Uint256, error)
GetNEP5Balances(acc util.Uint160) (*state.NEP5Balances, error)
GetNEP5Metadata(h util.Uint160) (*state.NEP5Metadata, error)
GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.NEP5TransferLog, error)
GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.TransferLog, error)
GetStateRoot(height uint32) (*state.MPTRootState, error)
PutStateRoot(root *state.MPTRootState) error
GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem
@ -60,7 +60,7 @@ type DAO interface {
PutCurrentHeader(hashAndIndex []byte) error
PutNEP5Balances(acc util.Uint160, bs *state.NEP5Balances) error
PutNEP5Metadata(h util.Uint160, meta *state.NEP5Metadata) error
PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.NEP5TransferLog) error
PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.TransferLog) error
PutStorageItem(scripthash util.Uint160, key []byte, si *state.StorageItem) error
PutUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin) error
PutValidatorState(vs *state.Validator) error
@ -262,7 +262,7 @@ func (dao *Simple) putNEP5Balances(acc util.Uint160, bs *state.NEP5Balances, buf
// -- start transfer log.
const nep5TransferBatchSize = 128
const nep5TransferBatchSize = 128 * state.NEP5TransferSize
func getNEP5TransferLogKey(acc util.Uint160, index uint32) []byte {
key := make([]byte, 1+util.Uint160Size+4)
@ -273,20 +273,20 @@ func getNEP5TransferLogKey(acc util.Uint160, index uint32) []byte {
}
// GetNEP5TransferLog retrieves transfer log from the cache.
func (dao *Simple) GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.NEP5TransferLog, error) {
func (dao *Simple) GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.TransferLog, error) {
key := getNEP5TransferLogKey(acc, index)
value, err := dao.Store.Get(key)
if err != nil {
if err == storage.ErrKeyNotFound {
return new(state.NEP5TransferLog), nil
return new(state.TransferLog), nil
}
return nil, err
}
return &state.NEP5TransferLog{Raw: value}, nil
return &state.TransferLog{Raw: value}, nil
}
// PutNEP5TransferLog saves given transfer log in the cache.
func (dao *Simple) PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.NEP5TransferLog) error {
func (dao *Simple) PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.TransferLog) error {
key := getNEP5TransferLogKey(acc, index)
return dao.Store.Put(key, lg.Raw)
}
@ -299,7 +299,7 @@ func (dao *Simple) AppendNEP5Transfer(acc util.Uint160, index uint32, tr *state.
if err != storage.ErrKeyNotFound {
return false, err
}
lg = new(state.NEP5TransferLog)
lg = new(state.TransferLog)
}
if err := lg.Append(tr); err != nil {
return false, err

View file

@ -14,8 +14,8 @@ type NEP5Tracker struct {
LastUpdatedBlock uint32
}
// NEP5TransferLog is a log of NEP5 token transfers for the specific command.
type NEP5TransferLog struct {
// TransferLog is a log of NEP5 token transfers for the specific command.
type TransferLog struct {
Raw []byte
}
@ -99,7 +99,7 @@ func (bs *NEP5Metadata) EncodeBinary(w *io.BinWriter) {
}
// Append appends single transfer to a log.
func (lg *NEP5TransferLog) Append(tr *NEP5Transfer) error {
func (lg *TransferLog) Append(tr io.Serializable) error {
w := io.NewBufBinWriter()
tr.EncodeBinary(w.BinWriter)
if w.Err != nil {
@ -110,26 +110,25 @@ func (lg *NEP5TransferLog) Append(tr *NEP5Transfer) error {
}
// ForEach iterates over transfer log returning on first error.
func (lg *NEP5TransferLog) ForEach(f func(*NEP5Transfer) error) error {
func (lg *TransferLog) ForEach(size int, tr io.Serializable, f func() error) error {
if lg == nil {
return nil
}
tr := new(NEP5Transfer)
for i := 0; i < len(lg.Raw); i += NEP5TransferSize {
r := io.NewBinReaderFromBuf(lg.Raw[i : i+NEP5TransferSize])
for i := 0; i < len(lg.Raw); i += size {
r := io.NewBinReaderFromBuf(lg.Raw[i : i+size])
tr.DecodeBinary(r)
if r.Err != nil {
return r.Err
} else if err := f(tr); err != nil {
} else if err := f(); err != nil {
return nil
}
}
return nil
}
// Size returns an amount of transfer written in log.
func (lg *NEP5TransferLog) Size() int {
return len(lg.Raw) / NEP5TransferSize
// Size returns an amount of transfer written in log provided size of a single transfer.
func (lg *TransferLog) Size() int {
return len(lg.Raw)
}
// EncodeBinary implements io.Serializable interface.

View file

@ -21,15 +21,16 @@ func TestNEP5TransferLog_Append(t *testing.T) {
randomTransfer(r),
}
lg := new(NEP5TransferLog)
lg := new(TransferLog)
for _, tr := range expected {
require.NoError(t, lg.Append(tr))
}
require.Equal(t, len(expected), lg.Size())
require.Equal(t, len(expected), lg.Size()/NEP5TransferSize)
i := 0
err := lg.ForEach(func(tr *NEP5Transfer) error {
tr := new(NEP5Transfer)
err := lg.ForEach(NEP5TransferSize, tr, func() error {
require.Equal(t, expected[i], tr)
i++
return nil

View file

@ -96,7 +96,7 @@ func (chain testChain) GetAccountState(util.Uint160) *state.Account {
func (chain testChain) GetNEP5Metadata(util.Uint160) (*state.NEP5Metadata, error) {
panic("TODO")
}
func (chain testChain) GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog {
func (chain testChain) GetNEP5TransferLog(util.Uint160) *state.TransferLog {
panic("TODO")
}
func (chain testChain) GetNEP5Balances(util.Uint160) *state.NEP5Balances {

View file

@ -598,7 +598,8 @@ func (s *Server) getNEP5Transfers(ps request.Params) (interface{}, *response.Err
Sent: []result.NEP5Transfer{},
}
lg := s.chain.GetNEP5TransferLog(u)
err = lg.ForEach(func(tr *state.NEP5Transfer) error {
tr := new(state.NEP5Transfer)
err = lg.ForEach(state.NEP5TransferSize, tr, func() error {
transfer := result.NEP5Transfer{
Timestamp: tr.Timestamp,
Asset: tr.Asset,