From 806b89db76659fdd542d73196e9fa79e9aadff81 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Mon, 21 Sep 2020 21:46:40 +0300 Subject: [PATCH] state: store the length of NEP5TransferLog in the first byte We lose `size` field after serialization/deserialization which can lead to adding more than NEP5TransferBatchSize elements into the NEP5TransferLog. --- pkg/core/dao/cacheddao.go | 2 +- pkg/core/dao/dao.go | 4 +--- pkg/core/state/nep5.go | 20 +++++++++++++++----- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/pkg/core/dao/cacheddao.go b/pkg/core/dao/cacheddao.go index 8c8bf1aa6..9cfa8992e 100644 --- a/pkg/core/dao/cacheddao.go +++ b/pkg/core/dao/cacheddao.go @@ -95,7 +95,7 @@ func (cd *Cached) AppendNEP5Transfer(acc util.Uint160, index uint32, tr *state.N if err := lg.Append(tr); err != nil { return false, err } - return lg.Size() >= nep5TransferBatchSize, cd.PutNEP5TransferLog(acc, index, lg) + return lg.Size() >= state.NEP5TransferBatchSize, cd.PutNEP5TransferLog(acc, index, lg) } // Persist flushes all the changes made into the (supposedly) persistent diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index af746cef4..f4fa5050d 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -208,8 +208,6 @@ func (dao *Simple) putNEP5Balances(acc util.Uint160, bs *state.NEP5Balances, buf // -- start transfer log. -const nep5TransferBatchSize = 128 - func getNEP5TransferLogKey(acc util.Uint160, index uint32) []byte { key := make([]byte, 1+util.Uint160Size+4) key[0] = byte(storage.STNEP5Transfers) @@ -250,7 +248,7 @@ func (dao *Simple) AppendNEP5Transfer(acc util.Uint160, index uint32, tr *state. if err := lg.Append(tr); err != nil { return false, err } - return lg.Size() >= nep5TransferBatchSize, dao.PutNEP5TransferLog(acc, index, lg) + return lg.Size() >= state.NEP5TransferBatchSize, dao.PutNEP5TransferLog(acc, index, lg) } // -- end transfer log. diff --git a/pkg/core/state/nep5.go b/pkg/core/state/nep5.go index b3dc38715..9679ab57e 100644 --- a/pkg/core/state/nep5.go +++ b/pkg/core/state/nep5.go @@ -8,6 +8,9 @@ import ( "github.com/nspcc-dev/neo-go/pkg/util" ) +// NEP5TransferBatchSize is the maximum number of entries for NEP5TransferLog. +const NEP5TransferBatchSize = 128 + // NEP5Tracker contains info about a single account in a NEP5 contract. type NEP5Tracker struct { // Balance is the current balance of the account. @@ -20,8 +23,6 @@ type NEP5Tracker struct { // NEP5TransferLog is a log of NEP5 token transfers for the specific command. type NEP5TransferLog struct { Raw []byte - // size is the number of NEP5Transfers written into Raw - size int } // NEP5Transfer represents a single NEP5 Transfer event. @@ -85,12 +86,18 @@ func (bs *NEP5Balances) EncodeBinary(w *io.BinWriter) { // Append appends single transfer to a log. func (lg *NEP5TransferLog) Append(tr *NEP5Transfer) error { w := io.NewBufBinWriter() + // The first entry, set up counter. + if len(lg.Raw) == 0 { + w.WriteB(1) + } tr.EncodeBinary(w.BinWriter) if w.Err != nil { return w.Err } + if len(lg.Raw) != 0 { + lg.Raw[0]++ + } lg.Raw = append(lg.Raw, w.Bytes()...) - lg.size++ return nil } @@ -101,7 +108,7 @@ func (lg *NEP5TransferLog) ForEach(f func(*NEP5Transfer) error) error { } tr := new(NEP5Transfer) var bytesRead int - for i := 0; i < len(lg.Raw); i += bytesRead { + for i := 1; i < len(lg.Raw); i += bytesRead { r := io.NewBinReaderFromBuf(lg.Raw[i:]) bytesRead = tr.DecodeBinaryReturnCount(r) if r.Err != nil { @@ -115,7 +122,10 @@ func (lg *NEP5TransferLog) ForEach(f func(*NEP5Transfer) error) error { // Size returns an amount of transfer written in log. func (lg *NEP5TransferLog) Size() int { - return lg.size + if len(lg.Raw) == 0 { + return 0 + } + return int(lg.Raw[0]) } // EncodeBinary implements io.Serializable interface.