mempool: use uint256 library for fee tracking
It's very effective in avoiding allocations for big.Int, we don't have a microbenchmark for memppol, but this improves TPS metrics by ~1-2%, so it's noticeable.
This commit is contained in:
parent
ee05f73b6f
commit
748a70569a
4 changed files with 32 additions and 30 deletions
1
go.mod
1
go.mod
|
@ -6,6 +6,7 @@ require (
|
|||
github.com/btcsuite/btcd v0.22.0-beta
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/holiman/uint256 v1.2.0
|
||||
github.com/mr-tron/base58 v1.2.0
|
||||
github.com/nspcc-dev/dbft v0.0.0-20210721160347-1b03241391ac
|
||||
github.com/nspcc-dev/go-ordered-json v0.0.0-20210915112629-e1b6cce73d02
|
||||
|
|
2
go.sum
2
go.sum
|
@ -128,6 +128,8 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
|||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM=
|
||||
github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
|
|
|
@ -3,11 +3,11 @@ package mempool
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"math/bits"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/mempoolevent"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
|
@ -50,8 +50,8 @@ type items []item
|
|||
// utilityBalanceAndFees stores sender's balance and overall fees of
|
||||
// sender's transactions which are currently in mempool.
|
||||
type utilityBalanceAndFees struct {
|
||||
balance *big.Int
|
||||
feeSum *big.Int
|
||||
balance uint256.Int
|
||||
feeSum uint256.Int
|
||||
}
|
||||
|
||||
// Pool stores the unconfirms transactions.
|
||||
|
@ -164,8 +164,7 @@ func (mp *Pool) tryAddSendersFee(tx *transaction.Transaction, feer Feer, needChe
|
|||
payer := tx.Signers[mp.payerIndex].Account
|
||||
senderFee, ok := mp.fees[payer]
|
||||
if !ok {
|
||||
senderFee.balance = feer.GetUtilityTokenBalance(payer)
|
||||
senderFee.feeSum = big.NewInt(0)
|
||||
_ = senderFee.balance.SetFromBig(feer.GetUtilityTokenBalance(payer))
|
||||
mp.fees[payer] = senderFee
|
||||
}
|
||||
if needCheck {
|
||||
|
@ -173,23 +172,26 @@ func (mp *Pool) tryAddSendersFee(tx *transaction.Transaction, feer Feer, needChe
|
|||
if err != nil {
|
||||
return false
|
||||
}
|
||||
senderFee.feeSum.Set(newFeeSum)
|
||||
senderFee.feeSum = newFeeSum
|
||||
} else {
|
||||
senderFee.feeSum.Add(senderFee.feeSum, big.NewInt(tx.SystemFee+tx.NetworkFee))
|
||||
senderFee.feeSum.AddUint64(&senderFee.feeSum, uint64(tx.SystemFee+tx.NetworkFee))
|
||||
}
|
||||
mp.fees[payer] = senderFee
|
||||
return true
|
||||
}
|
||||
|
||||
// checkBalance returns new cumulative fee balance for account or an error in
|
||||
// case sender doesn't have enough GAS to pay for the transaction.
|
||||
func checkBalance(tx *transaction.Transaction, balance utilityBalanceAndFees) (*big.Int, error) {
|
||||
txFee := big.NewInt(tx.SystemFee + tx.NetworkFee)
|
||||
if balance.balance.Cmp(txFee) < 0 {
|
||||
return nil, ErrInsufficientFunds
|
||||
func checkBalance(tx *transaction.Transaction, balance utilityBalanceAndFees) (uint256.Int, error) {
|
||||
var txFee uint256.Int
|
||||
|
||||
txFee.SetUint64(uint64(tx.SystemFee + tx.NetworkFee))
|
||||
if balance.balance.Cmp(&txFee) < 0 {
|
||||
return txFee, ErrInsufficientFunds
|
||||
}
|
||||
txFee.Add(txFee, balance.feeSum)
|
||||
if balance.balance.Cmp(txFee) < 0 {
|
||||
return nil, ErrConflict
|
||||
txFee.Add(&txFee, &balance.feeSum)
|
||||
if balance.balance.Cmp(&txFee) < 0 {
|
||||
return txFee, ErrConflict
|
||||
}
|
||||
return txFee, nil
|
||||
}
|
||||
|
@ -323,7 +325,7 @@ func (mp *Pool) removeInternal(hash util.Uint256, feer Feer) {
|
|||
}
|
||||
payer := itm.txn.Signers[mp.payerIndex].Account
|
||||
senderFee := mp.fees[payer]
|
||||
senderFee.feeSum.Sub(senderFee.feeSum, big.NewInt(tx.SystemFee+tx.NetworkFee))
|
||||
senderFee.feeSum.SubUint64(&senderFee.feeSum, uint64(tx.SystemFee+tx.NetworkFee))
|
||||
mp.fees[payer] = senderFee
|
||||
if feer.P2PSigExtensionsEnabled() {
|
||||
// remove all conflicting hashes from mp.conflicts list
|
||||
|
@ -507,8 +509,7 @@ func (mp *Pool) checkTxConflicts(tx *transaction.Transaction, fee Feer) ([]*tran
|
|||
payer := tx.Signers[mp.payerIndex].Account
|
||||
actualSenderFee, ok := mp.fees[payer]
|
||||
if !ok {
|
||||
actualSenderFee.balance = fee.GetUtilityTokenBalance(payer)
|
||||
actualSenderFee.feeSum = big.NewInt(0)
|
||||
actualSenderFee.balance.SetFromBig(fee.GetUtilityTokenBalance(payer))
|
||||
}
|
||||
|
||||
var expectedSenderFee utilityBalanceAndFees
|
||||
|
@ -541,13 +542,10 @@ func (mp *Pool) checkTxConflicts(tx *transaction.Transaction, fee Feer) ([]*tran
|
|||
conflictsToBeRemoved = append(conflictsToBeRemoved, existingTx)
|
||||
}
|
||||
// Step 3: take into account sender's conflicting transactions before balance check.
|
||||
expectedSenderFee = utilityBalanceAndFees{
|
||||
balance: new(big.Int).Set(actualSenderFee.balance),
|
||||
feeSum: new(big.Int).Set(actualSenderFee.feeSum),
|
||||
}
|
||||
expectedSenderFee = actualSenderFee
|
||||
for _, conflictingTx := range conflictsToBeRemoved {
|
||||
if conflictingTx.Signers[mp.payerIndex].Account.Equals(payer) {
|
||||
expectedSenderFee.feeSum.Sub(expectedSenderFee.feeSum, big.NewInt(conflictingTx.SystemFee+conflictingTx.NetworkFee))
|
||||
expectedSenderFee.feeSum.SubUint64(&expectedSenderFee.feeSum, uint64(conflictingTx.SystemFee+conflictingTx.NetworkFee))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/nspcc-dev/neo-go/internal/random"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/network/payload"
|
||||
|
@ -268,8 +269,8 @@ func TestMemPoolFees(t *testing.T) {
|
|||
require.NoError(t, mp.Add(tx1, fs))
|
||||
require.Equal(t, 1, len(mp.fees))
|
||||
require.Equal(t, utilityBalanceAndFees{
|
||||
balance: big.NewInt(fs.balance),
|
||||
feeSum: big.NewInt(tx1.NetworkFee),
|
||||
balance: *uint256.NewInt(uint64(fs.balance)),
|
||||
feeSum: *uint256.NewInt(uint64(tx1.NetworkFee)),
|
||||
}, mp.fees[sender0])
|
||||
|
||||
// balance shouldn't change after adding one more transaction
|
||||
|
@ -280,8 +281,8 @@ func TestMemPoolFees(t *testing.T) {
|
|||
require.Equal(t, 2, len(mp.verifiedTxes))
|
||||
require.Equal(t, 1, len(mp.fees))
|
||||
require.Equal(t, utilityBalanceAndFees{
|
||||
balance: big.NewInt(fs.balance),
|
||||
feeSum: big.NewInt(fs.balance),
|
||||
balance: *uint256.NewInt(uint64(fs.balance)),
|
||||
feeSum: *uint256.NewInt(uint64(fs.balance)),
|
||||
}, mp.fees[sender0])
|
||||
|
||||
// can't add more transactions as we don't have enough GAS
|
||||
|
@ -292,8 +293,8 @@ func TestMemPoolFees(t *testing.T) {
|
|||
require.Error(t, mp.Add(tx3, fs))
|
||||
require.Equal(t, 1, len(mp.fees))
|
||||
require.Equal(t, utilityBalanceAndFees{
|
||||
balance: big.NewInt(fs.balance),
|
||||
feeSum: big.NewInt(fs.balance),
|
||||
balance: *uint256.NewInt(uint64(fs.balance)),
|
||||
feeSum: *uint256.NewInt(uint64(fs.balance)),
|
||||
}, mp.fees[sender0])
|
||||
|
||||
// check whether sender's fee updates correctly
|
||||
|
@ -302,8 +303,8 @@ func TestMemPoolFees(t *testing.T) {
|
|||
}, fs)
|
||||
require.Equal(t, 1, len(mp.fees))
|
||||
require.Equal(t, utilityBalanceAndFees{
|
||||
balance: big.NewInt(fs.balance),
|
||||
feeSum: big.NewInt(tx2.NetworkFee),
|
||||
balance: *uint256.NewInt(uint64(fs.balance)),
|
||||
feeSum: *uint256.NewInt(uint64(tx2.NetworkFee)),
|
||||
}, mp.fees[sender0])
|
||||
|
||||
// there should be nothing left
|
||||
|
|
Loading…
Reference in a new issue