Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
c47052a5
Unverified
Commit
c47052a5
authored
Jul 22, 2020
by
Hendrik Hofstadt
Committed by
Péter Szilágyi
Jul 28, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: sort txs at the same gas price by received time
parent
93da0cf8
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
52 additions
and
12 deletions
+52
-12
tx_pool.go
core/tx_pool.go
+1
-0
transaction.go
core/types/transaction.go
+43
-11
transaction_test.go
core/types/transaction_test.go
+8
-1
No files found.
core/tx_pool.go
View file @
c47052a5
...
@@ -568,6 +568,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
...
@@ -568,6 +568,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
// whitelisted, preventing any associated transaction from being dropped out of the pool
// whitelisted, preventing any associated transaction from being dropped out of the pool
// due to pricing constraints.
// due to pricing constraints.
func
(
pool
*
TxPool
)
add
(
tx
*
types
.
Transaction
,
local
bool
)
(
replaced
bool
,
err
error
)
{
func
(
pool
*
TxPool
)
add
(
tx
*
types
.
Transaction
,
local
bool
)
(
replaced
bool
,
err
error
)
{
tx
.
SetReceivedTime
(
time
.
Now
())
// If the transaction is already known, discard it
// If the transaction is already known, discard it
hash
:=
tx
.
Hash
()
hash
:=
tx
.
Hash
()
if
pool
.
all
.
Get
(
hash
)
!=
nil
{
if
pool
.
all
.
Get
(
hash
)
!=
nil
{
...
...
core/types/transaction.go
View file @
c47052a5
...
@@ -22,6 +22,7 @@ import (
...
@@ -22,6 +22,7 @@ import (
"io"
"io"
"math/big"
"math/big"
"sync/atomic"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/hexutil"
...
@@ -37,6 +38,9 @@ var (
...
@@ -37,6 +38,9 @@ var (
type
Transaction
struct
{
type
Transaction
struct
{
data
txdata
data
txdata
// Time when the transaction was added to the txPool
receivedTime
*
time
.
Time
// caches
// caches
hash
atomic
.
Value
hash
atomic
.
Value
size
atomic
.
Value
size
atomic
.
Value
...
@@ -184,6 +188,13 @@ func (tx *Transaction) GasPriceIntCmp(other *big.Int) int {
...
@@ -184,6 +188,13 @@ func (tx *Transaction) GasPriceIntCmp(other *big.Int) int {
func
(
tx
*
Transaction
)
Value
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Set
(
tx
.
data
.
Amount
)
}
func
(
tx
*
Transaction
)
Value
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Set
(
tx
.
data
.
Amount
)
}
func
(
tx
*
Transaction
)
Nonce
()
uint64
{
return
tx
.
data
.
AccountNonce
}
func
(
tx
*
Transaction
)
Nonce
()
uint64
{
return
tx
.
data
.
AccountNonce
}
func
(
tx
*
Transaction
)
CheckNonce
()
bool
{
return
true
}
func
(
tx
*
Transaction
)
CheckNonce
()
bool
{
return
true
}
func
(
tx
*
Transaction
)
ReceivedTime
()
(
time
.
Time
,
bool
)
{
if
tx
.
receivedTime
==
nil
{
return
time
.
Time
{},
false
}
return
*
tx
.
receivedTime
,
true
}
// To returns the recipient address of the transaction.
// To returns the recipient address of the transaction.
// It returns nil if the transaction is a contract creation.
// It returns nil if the transaction is a contract creation.
...
@@ -246,7 +257,7 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e
...
@@ -246,7 +257,7 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
cpy
:=
&
Transaction
{
data
:
tx
.
data
}
cpy
:=
&
Transaction
{
data
:
tx
.
data
,
receivedTime
:
tx
.
receivedTime
}
cpy
.
data
.
R
,
cpy
.
data
.
S
,
cpy
.
data
.
V
=
r
,
s
,
v
cpy
.
data
.
R
,
cpy
.
data
.
S
,
cpy
.
data
.
V
=
r
,
s
,
v
return
cpy
,
nil
return
cpy
,
nil
}
}
...
@@ -264,6 +275,11 @@ func (tx *Transaction) RawSignatureValues() (v, r, s *big.Int) {
...
@@ -264,6 +275,11 @@ func (tx *Transaction) RawSignatureValues() (v, r, s *big.Int) {
return
tx
.
data
.
V
,
tx
.
data
.
R
,
tx
.
data
.
S
return
tx
.
data
.
V
,
tx
.
data
.
R
,
tx
.
data
.
S
}
}
// SetReceivedTime sets the time that this transaction was received at.
func
(
tx
*
Transaction
)
SetReceivedTime
(
time
time
.
Time
)
{
tx
.
receivedTime
=
&
time
}
// Transactions is a Transaction slice type for basic sorting.
// Transactions is a Transaction slice type for basic sorting.
type
Transactions
[]
*
Transaction
type
Transactions
[]
*
Transaction
...
@@ -306,19 +322,35 @@ func (s TxByNonce) Len() int { return len(s) }
...
@@ -306,19 +322,35 @@ func (s TxByNonce) Len() int { return len(s) }
func
(
s
TxByNonce
)
Less
(
i
,
j
int
)
bool
{
return
s
[
i
]
.
data
.
AccountNonce
<
s
[
j
]
.
data
.
AccountNonce
}
func
(
s
TxByNonce
)
Less
(
i
,
j
int
)
bool
{
return
s
[
i
]
.
data
.
AccountNonce
<
s
[
j
]
.
data
.
AccountNonce
}
func
(
s
TxByNonce
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
func
(
s
TxByNonce
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
// TxByPrice implements both the sort and the heap interface, making it useful
// TxByPrice
AndReceiveTime
implements both the sort and the heap interface, making it useful
// for all at once sorting as well as individually adding and removing elements.
// for all at once sorting as well as individually adding and removing elements.
type
TxByPrice
Transactions
type
TxByPriceAndReceiveTime
Transactions
func
(
s
TxByPriceAndReceiveTime
)
Len
()
int
{
return
len
(
s
)
}
func
(
s
TxByPriceAndReceiveTime
)
Less
(
i
,
j
int
)
bool
{
// If the price is equal, use the time the tx was received for deterministic sorting
if
s
[
i
]
.
data
.
Price
.
Cmp
(
s
[
j
]
.
data
.
Price
)
==
0
{
recvI
,
ok
:=
s
[
i
]
.
ReceivedTime
()
if
!
ok
{
return
true
}
func
(
s
TxByPrice
)
Len
()
int
{
return
len
(
s
)
}
recvJ
,
ok
:=
s
[
j
]
.
ReceivedTime
()
func
(
s
TxByPrice
)
Less
(
i
,
j
int
)
bool
{
return
s
[
i
]
.
data
.
Price
.
Cmp
(
s
[
j
]
.
data
.
Price
)
>
0
}
if
!
ok
{
func
(
s
TxByPrice
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
return
true
}
return
recvI
.
UnixNano
()
<
recvJ
.
UnixNano
()
}
return
s
[
i
]
.
data
.
Price
.
Cmp
(
s
[
j
]
.
data
.
Price
)
>
0
}
func
(
s
TxByPriceAndReceiveTime
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
func
(
s
*
TxByPrice
)
Push
(
x
interface
{})
{
func
(
s
*
TxByPrice
AndReceiveTime
)
Push
(
x
interface
{})
{
*
s
=
append
(
*
s
,
x
.
(
*
Transaction
))
*
s
=
append
(
*
s
,
x
.
(
*
Transaction
))
}
}
func
(
s
*
TxByPrice
)
Pop
()
interface
{}
{
func
(
s
*
TxByPrice
AndReceiveTime
)
Pop
()
interface
{}
{
old
:=
*
s
old
:=
*
s
n
:=
len
(
old
)
n
:=
len
(
old
)
x
:=
old
[
n
-
1
]
x
:=
old
[
n
-
1
]
...
@@ -331,7 +363,7 @@ func (s *TxByPrice) Pop() interface{} {
...
@@ -331,7 +363,7 @@ func (s *TxByPrice) Pop() interface{} {
// entire batches of transactions for non-executable accounts.
// entire batches of transactions for non-executable accounts.
type
TransactionsByPriceAndNonce
struct
{
type
TransactionsByPriceAndNonce
struct
{
txs
map
[
common
.
Address
]
Transactions
// Per account nonce-sorted list of transactions
txs
map
[
common
.
Address
]
Transactions
// Per account nonce-sorted list of transactions
heads
TxByPrice
// Next transaction for each unique account (price heap)
heads
TxByPrice
AndReceiveTime
// Next transaction for each unique account (price heap)
signer
Signer
// Signer for the set of transactions
signer
Signer
// Signer for the set of transactions
}
}
...
@@ -341,8 +373,8 @@ type TransactionsByPriceAndNonce struct {
...
@@ -341,8 +373,8 @@ type TransactionsByPriceAndNonce struct {
// Note, the input map is reowned so the caller should not interact any more with
// Note, the input map is reowned so the caller should not interact any more with
// if after providing it to the constructor.
// if after providing it to the constructor.
func
NewTransactionsByPriceAndNonce
(
signer
Signer
,
txs
map
[
common
.
Address
]
Transactions
)
*
TransactionsByPriceAndNonce
{
func
NewTransactionsByPriceAndNonce
(
signer
Signer
,
txs
map
[
common
.
Address
]
Transactions
)
*
TransactionsByPriceAndNonce
{
// Initialize a price based heap with the head transactions
// Initialize a price
and received time
based heap with the head transactions
heads
:=
make
(
TxByPrice
,
0
,
len
(
txs
))
heads
:=
make
(
TxByPrice
AndReceiveTime
,
0
,
len
(
txs
))
for
from
,
accTxs
:=
range
txs
{
for
from
,
accTxs
:=
range
txs
{
heads
=
append
(
heads
,
accTxs
[
0
])
heads
=
append
(
heads
,
accTxs
[
0
])
// Ensure the sender address is from the signer
// Ensure the sender address is from the signer
...
...
core/types/transaction_test.go
View file @
c47052a5
...
@@ -22,6 +22,7 @@ import (
...
@@ -22,6 +22,7 @@ import (
"encoding/json"
"encoding/json"
"math/big"
"math/big"
"testing"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
...
@@ -134,7 +135,8 @@ func TestTransactionPriceNonceSort(t *testing.T) {
...
@@ -134,7 +135,8 @@ func TestTransactionPriceNonceSort(t *testing.T) {
for
start
,
key
:=
range
keys
{
for
start
,
key
:=
range
keys
{
addr
:=
crypto
.
PubkeyToAddress
(
key
.
PublicKey
)
addr
:=
crypto
.
PubkeyToAddress
(
key
.
PublicKey
)
for
i
:=
0
;
i
<
25
;
i
++
{
for
i
:=
0
;
i
<
25
;
i
++
{
tx
,
_
:=
SignTx
(
NewTransaction
(
uint64
(
start
+
i
),
common
.
Address
{},
big
.
NewInt
(
100
),
100
,
big
.
NewInt
(
int64
(
start
+
i
)),
nil
),
signer
,
key
)
tx
,
_
:=
SignTx
(
NewTransaction
(
uint64
(
i
),
common
.
Address
{},
big
.
NewInt
(
100
),
100
,
big
.
NewInt
(
int64
(
25
-
i
)),
nil
),
signer
,
key
)
tx
.
SetReceivedTime
(
time
.
Unix
(
0
,
int64
(
start
)))
groups
[
addr
]
=
append
(
groups
[
addr
],
tx
)
groups
[
addr
]
=
append
(
groups
[
addr
],
tx
)
}
}
}
}
...
@@ -168,6 +170,11 @@ func TestTransactionPriceNonceSort(t *testing.T) {
...
@@ -168,6 +170,11 @@ func TestTransactionPriceNonceSort(t *testing.T) {
if
fromi
!=
fromNext
&&
txi
.
GasPrice
()
.
Cmp
(
next
.
GasPrice
())
<
0
{
if
fromi
!=
fromNext
&&
txi
.
GasPrice
()
.
Cmp
(
next
.
GasPrice
())
<
0
{
t
.
Errorf
(
"invalid gasprice ordering: tx #%d (A=%x P=%v) < tx #%d (A=%x P=%v)"
,
i
,
fromi
[
:
4
],
txi
.
GasPrice
(),
i
+
1
,
fromNext
[
:
4
],
next
.
GasPrice
())
t
.
Errorf
(
"invalid gasprice ordering: tx #%d (A=%x P=%v) < tx #%d (A=%x P=%v)"
,
i
,
fromi
[
:
4
],
txi
.
GasPrice
(),
i
+
1
,
fromNext
[
:
4
],
next
.
GasPrice
())
}
}
// Make sure receivedTime order is ascending if the txs have the same gas price
if
txi
.
GasPrice
()
.
Cmp
(
next
.
GasPrice
())
==
0
&&
fromi
!=
fromNext
&&
txi
.
receivedTime
.
UnixNano
()
>
next
.
receivedTime
.
UnixNano
()
{
t
.
Errorf
(
"invalid received time ordering: tx #%d (A=%x T=%d) > tx #%d (A=%x T=%d)"
,
i
,
fromi
[
:
4
],
txi
.
receivedTime
.
UnixNano
(),
i
+
1
,
fromNext
[
:
4
],
next
.
receivedTime
.
UnixNano
())
}
}
}
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment