From 584675ec23eb1d8684c65cefe19c88ec0752d609 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 10 Jan 2023 22:37:44 +0300 Subject: [PATCH] state: optimize NEP17Transfer struct We have both from and to here, so technically we can either drop the neg/neg trick from the processTokenTransfer() or drop one field from the structure (the other side is a part of the key). Drop the field since this can make the DB a bit more compact. Change Amount to be a pointer along the way since that's the "native" thing for big.Int, we've used non-pointer field specifically to avoid Neg/Neg problems, but it looks like this is not necessary. This structure is only used by the RPC server and I doubt anyone uses it via the *Blockchain. --- pkg/core/blockchain.go | 33 ++++++++++++------------ pkg/core/state/tokens.go | 18 +++++-------- pkg/core/state/tokens_test.go | 48 ++++++++++++++++------------------- pkg/services/rpcsrv/server.go | 11 +++----- 4 files changed, 49 insertions(+), 61 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 6ac36da8f..c778a136b 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -45,7 +45,7 @@ import ( // Tuning parameters. const ( - version = "0.2.7" + version = "0.2.8" defaultInitialGAS = 52000000_00000000 defaultGCPeriod = 10000 @@ -1765,25 +1765,23 @@ func (bc *Blockchain) processTokenTransfer(cache *dao.Simple, transCache map[uti var isNEP11 = (tokenID != nil) if !isNEP11 { nep17xfer = &state.NEP17Transfer{ - Asset: id, - Amount: *amount, - From: from, - To: to, - Block: b.Index, - Timestamp: b.Timestamp, - Tx: h, + Asset: id, + Amount: amount, + Block: b.Index, + Counterparty: to, + Timestamp: b.Timestamp, + Tx: h, } transfer = nep17xfer } else { nep11xfer := &state.NEP11Transfer{ NEP17Transfer: state.NEP17Transfer{ - Asset: id, - Amount: *amount, - From: from, - To: to, - Block: b.Index, - Timestamp: b.Timestamp, - Tx: h, + Asset: id, + Amount: amount, + Block: b.Index, + Counterparty: to, + Timestamp: b.Timestamp, + Tx: h, }, ID: tokenID, } @@ -1791,14 +1789,15 @@ func (bc *Blockchain) processTokenTransfer(cache *dao.Simple, transCache map[uti nep17xfer = &nep11xfer.NEP17Transfer } if !from.Equals(util.Uint160{}) { - _ = nep17xfer.Amount.Neg(&nep17xfer.Amount) + _ = nep17xfer.Amount.Neg(nep17xfer.Amount) err := appendTokenTransfer(cache, transCache, from, transfer, id, b.Index, b.Timestamp, isNEP11) - _ = nep17xfer.Amount.Neg(&nep17xfer.Amount) + _ = nep17xfer.Amount.Neg(nep17xfer.Amount) if err != nil { return } } if !to.Equals(util.Uint160{}) { + nep17xfer.Counterparty = from _ = appendTokenTransfer(cache, transCache, to, transfer, id, b.Index, b.Timestamp, isNEP11) // Nothing useful we can do. } } diff --git a/pkg/core/state/tokens.go b/pkg/core/state/tokens.go index 8434dc298..06f7d489c 100644 --- a/pkg/core/state/tokens.go +++ b/pkg/core/state/tokens.go @@ -24,13 +24,11 @@ type TokenTransferLog struct { type NEP17Transfer struct { // Asset is a NEP-17 contract ID. Asset int32 - // Address is the address of the sender. - From util.Uint160 - // To is the address of the receiver. - To util.Uint160 + // Counterparty is the address of the sender/receiver (the other side of the transfer). + Counterparty util.Uint160 // Amount is the amount of tokens transferred. // It is negative when tokens are sent and positive if they are received. - Amount big.Int + Amount *big.Int // Block is a number of block when the event occurred. Block uint32 // Timestamp is the timestamp of the block where transfer occurred. @@ -195,11 +193,10 @@ func (t *NEP17Transfer) EncodeBinary(w *io.BinWriter) { w.WriteU32LE(uint32(t.Asset)) w.WriteBytes(t.Tx[:]) - w.WriteBytes(t.From[:]) - w.WriteBytes(t.To[:]) + w.WriteBytes(t.Counterparty[:]) w.WriteU32LE(t.Block) w.WriteU64LE(t.Timestamp) - amount := bigint.ToPreallocatedBytes(&t.Amount, buf[:]) + amount := bigint.ToPreallocatedBytes(t.Amount, buf[:]) w.WriteVarBytes(amount) } @@ -207,12 +204,11 @@ func (t *NEP17Transfer) EncodeBinary(w *io.BinWriter) { func (t *NEP17Transfer) DecodeBinary(r *io.BinReader) { t.Asset = int32(r.ReadU32LE()) r.ReadBytes(t.Tx[:]) - r.ReadBytes(t.From[:]) - r.ReadBytes(t.To[:]) + r.ReadBytes(t.Counterparty[:]) t.Block = r.ReadU32LE() t.Timestamp = r.ReadU64LE() amount := r.ReadVarBytes(bigint.MaxBytesLen) - t.Amount = *bigint.FromBytes(amount) + t.Amount = bigint.FromBytes(amount) } // EncodeBinary implements the io.Serializable interface. diff --git a/pkg/core/state/tokens_test.go b/pkg/core/state/tokens_test.go index 120b5a567..9f8f78671 100644 --- a/pkg/core/state/tokens_test.go +++ b/pkg/core/state/tokens_test.go @@ -86,13 +86,12 @@ func BenchmarkTokenTransferLog_Append(b *testing.B) { func TestNEP17Transfer_DecodeBinary(t *testing.T) { expected := &NEP17Transfer{ - Asset: 123, - From: util.Uint160{5, 6, 7}, - To: util.Uint160{8, 9, 10}, - Amount: *big.NewInt(42), - Block: 12345, - Timestamp: 54321, - Tx: util.Uint256{8, 5, 3}, + Asset: 123, + Counterparty: util.Uint160{5, 6, 7}, + Amount: big.NewInt(42), + Block: 12345, + Timestamp: 54321, + Tx: util.Uint256{8, 5, 3}, } testserdes.EncodeDecodeBinary(t, expected, new(NEP17Transfer)) @@ -101,13 +100,12 @@ func TestNEP17Transfer_DecodeBinary(t *testing.T) { func TestNEP11Transfer_DecodeBinary(t *testing.T) { expected := &NEP11Transfer{ NEP17Transfer: NEP17Transfer{ - Asset: 123, - From: util.Uint160{5, 6, 7}, - To: util.Uint160{8, 9, 10}, - Amount: *big.NewInt(42), - Block: 12345, - Timestamp: 54321, - Tx: util.Uint256{8, 5, 3}, + Asset: 123, + Counterparty: util.Uint160{5, 6, 7}, + Amount: big.NewInt(42), + Block: 12345, + Timestamp: 54321, + Tx: util.Uint256{8, 5, 3}, }, ID: []byte{42, 42, 42}, } @@ -117,24 +115,22 @@ func TestNEP11Transfer_DecodeBinary(t *testing.T) { func random17Transfer(r *rand.Rand) *NEP17Transfer { return &NEP17Transfer{ - Amount: *big.NewInt(int64(r.Uint64())), - Block: r.Uint32(), - Asset: int32(random.Int(10, 10000000)), - From: random.Uint160(), - To: random.Uint160(), - Tx: random.Uint256(), + Amount: big.NewInt(int64(r.Uint64())), + Block: r.Uint32(), + Asset: int32(random.Int(10, 10000000)), + Counterparty: random.Uint160(), + Tx: random.Uint256(), } } func random11Transfer(r *rand.Rand) *NEP11Transfer { return &NEP11Transfer{ NEP17Transfer: NEP17Transfer{ - Amount: *big.NewInt(int64(r.Uint64())), - Block: r.Uint32(), - Asset: int32(random.Int(10, 10000000)), - From: random.Uint160(), - To: random.Uint160(), - Tx: random.Uint256(), + Amount: big.NewInt(int64(r.Uint64())), + Block: r.Uint32(), + Asset: int32(random.Int(10, 10000000)), + Counterparty: random.Uint160(), + Tx: random.Uint256(), }, ID: random.Uint256().BytesBE(), } diff --git a/pkg/services/rpcsrv/server.go b/pkg/services/rpcsrv/server.go index bcd89542a..6258b8ef5 100644 --- a/pkg/services/rpcsrv/server.go +++ b/pkg/services/rpcsrv/server.go @@ -1264,18 +1264,15 @@ func (s *Server) getTokenTransfers(ps params.Params, isNEP11 bool) (interface{}, Index: tr.Block, TxHash: tr.Tx, } + if !tr.Counterparty.Equals(util.Uint160{}) { + transfer.Address = address.Uint160ToString(tr.Counterparty) + } if tr.Amount.Sign() > 0 { // token was received transfer.Amount = tr.Amount.String() - if !tr.From.Equals(util.Uint160{}) { - transfer.Address = address.Uint160ToString(tr.From) - } received = &result.NEP17Transfer{} *received = transfer // Make a copy, transfer is to be modified below. } else { - transfer.Amount = new(big.Int).Neg(&tr.Amount).String() - if !tr.To.Equals(util.Uint160{}) { - transfer.Address = address.Uint160ToString(tr.To) - } + transfer.Amount = new(big.Int).Neg(tr.Amount).String() sent = &result.NEP17Transfer{} *sent = transfer }