From 3097dc60e56bb2e3d7fa5a33ffcbabc2f3a1604b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 3 Jul 2020 17:37:01 +0300 Subject: [PATCH 1/3] transaction: cache feePerByte --- pkg/core/transaction/transaction.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index 9785276c6..9bb6825d4 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -64,6 +64,9 @@ type Transaction struct { // for correct signing/verification. Network netmode.Magic + // feePerByte is the ratio of NetworkFee and tx size, used for calculating tx priority. + feePerByte int64 + // Hash of the transaction (double SHA256). hash util.Uint256 @@ -278,7 +281,11 @@ func NewTransactionFromBytes(network netmode.Magic, b []byte) (*Transaction, err // FeePerByte returns NetworkFee of the transaction divided by // its size func (t *Transaction) FeePerByte() int64 { - return t.NetworkFee / int64(io.GetVarSize(t)) + if t.feePerByte != 0 { + return t.feePerByte + } + t.feePerByte = t.NetworkFee / int64(io.GetVarSize(t)) + return t.feePerByte } // transactionJSON is a wrapper for Transaction and From 27b3054df48cfab91312a75eb5da5c16216225c3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 3 Jul 2020 17:40:03 +0300 Subject: [PATCH 2/3] transaction: set feePerByte on tx construction --- pkg/core/transaction/transaction.go | 1 + pkg/rpc/client/rpc_test.go | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index 9bb6825d4..657300fe9 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -275,6 +275,7 @@ func NewTransactionFromBytes(network netmode.Magic, b []byte) (*Transaction, err if r.Err != nil { return nil, r.Err } + tx.feePerByte = tx.NetworkFee / int64(len(b)) return tx, nil } diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index 93741e7b0..71b1ae334 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -498,7 +498,12 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ if err != nil { panic(err) } - return c.GetRawTransactionVerbose(hash) + out, err := c.GetRawTransactionVerbose(hash) + if err != nil { + return nil, err + } + out.Transaction.FeePerByte() // set fee per byte + return out, nil }, serverResponse: txMoveNeoVerbose, result: func(c *Client) interface{} { From 5787d7775f66f6c9edbdd09bfdb5baa96ed9b330 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 3 Jul 2020 17:52:44 +0300 Subject: [PATCH 3/3] transaction: fail creating tx if there is additional data present --- pkg/core/transaction/transaction.go | 4 ++++ pkg/core/transaction/transaction_test.go | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index 657300fe9..c4e0fe539 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -275,6 +275,10 @@ func NewTransactionFromBytes(network netmode.Magic, b []byte) (*Transaction, err if r.Err != nil { return nil, r.Err } + _ = r.ReadB() + if r.Err == nil { + return nil, errors.New("additional data after the transaction") + } tx.feePerByte = tx.NetworkFee / int64(len(b)) return tx, nil } diff --git a/pkg/core/transaction/transaction_test.go b/pkg/core/transaction/transaction_test.go index 37cd3771b..fe2d38a55 100644 --- a/pkg/core/transaction/transaction_test.go +++ b/pkg/core/transaction/transaction_test.go @@ -71,6 +71,26 @@ func TestNew(t *testing.T) { testserdes.EncodeDecodeBinary(t, tx, &Transaction{Network: netmode.UnitTestNet}) } +func TestNewTransactionFromBytes(t *testing.T) { + script := []byte{0x51} + tx := New(netmode.UnitTestNet, script, 1) + tx.NetworkFee = 123 + data, err := testserdes.EncodeBinary(tx) + require.NoError(t, err) + + // set cached fields + tx.Hash() + tx.FeePerByte() + + tx1, err := NewTransactionFromBytes(netmode.UnitTestNet, data) + require.NoError(t, err) + require.Equal(t, tx, tx1) + + data = append(data, 42) + _, err = NewTransactionFromBytes(netmode.UnitTestNet, data) + require.Error(t, err) +} + func TestEncodingTXWithNoScript(t *testing.T) { _, err := testserdes.EncodeBinary(new(Transaction)) require.Error(t, err)