Skip to content

Commit 5932fc4

Browse files
committed
New mempool impl
Signed-off-by: Alessandro Sorniotti <aso@zurich.ibm.com>
1 parent 8a13cba commit 5932fc4

5 files changed

Lines changed: 458 additions & 52 deletions

File tree

gateway/core/api.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,32 @@ type Submitter interface {
3636
Close() error
3737
}
3838

39+
// TxQueueInterface defines the interface that transaction queue implementations must satisfy.
40+
// This allows switching between different queue implementations (e.g., TxQueue and TxQueueV2).
41+
type TxQueueInterface interface {
42+
// Enqueue adds a transaction to the queue
43+
Enqueue(tx *types.Transaction)
44+
45+
// Dequeue removes and returns a transaction from the queue
46+
// Returns (transaction, true) if successful, or (nil, false) if queue is closed
47+
Dequeue() (*types.Transaction, bool)
48+
49+
// IsPending checks if a transaction is currently in the queue or being processed
50+
IsPending(txHash common.Hash) *types.Transaction
51+
52+
// Complete marks a transaction as completed
53+
Complete(hash common.Hash)
54+
55+
// Close signals shutdown of the queue
56+
Close()
57+
58+
// Handle processes block notifications from the synchronizer
59+
Handle(ctx context.Context, block *domain.Block) error
60+
61+
// Stats returns statistics about processed transactions (total, invalid)
62+
Stats() (total int, invalid int)
63+
}
64+
3965
var logger = flogging.MustGetLogger("gateway.core")
4066

4167
// Gateway is the component that bridges Fabric-x and the EVM. Its API is the
@@ -49,7 +75,7 @@ type Gateway struct {
4975
chainID *big.Int
5076
ChainConfig *params.ChainConfig
5177
Signer types.Signer
52-
TxQueue *TxQueue
78+
TxQueue TxQueueInterface
5379
workerCount int
5480
wg sync.WaitGroup
5581
stopOnce sync.Once
@@ -84,7 +110,7 @@ func New(ec *EndorsementClient, submitter Submitter, store Store, chainID int64,
84110
chainID: cid,
85111
ChainConfig: cmn.BuildChainConfig(chainID),
86112
Signer: types.LatestSignerForChainID(cid),
87-
TxQueue: NewTxQueue(),
113+
TxQueue: NewTxQueueV2(),
88114
workerCount: workerCount,
89115
}, nil
90116
}
@@ -346,7 +372,10 @@ func (g *Gateway) Stop() error {
346372
err = g.submitter.Close()
347373
})
348374

349-
fmt.Println("gw stats:", g.TxQueue.total, g.TxQueue.invalid, float64(g.TxQueue.invalid)/float64(g.TxQueue.total))
375+
total, invalid := g.TxQueue.Stats()
376+
if total > 0 {
377+
fmt.Println("gw stats:", total, invalid, float64(invalid)/float64(total))
378+
}
350379

351380
return err
352381
}

gateway/core/txqueue.go

Lines changed: 6 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -222,55 +222,12 @@ func (q *TxQueue) Complete(hash common.Hash) {
222222
}
223223
}
224224

225-
func participantsForTx(tx *types.Transaction) []common.Address {
226-
participants := make([]common.Address, 0, 2)
227-
228-
if sender, ok := senderForTx(tx); ok {
229-
participants = append(participants, sender)
230-
}
231-
232-
if recipient, ok := recipientForTx(tx); ok && !containsAddress(participants, recipient) {
233-
participants = append(participants, recipient)
234-
}
235-
236-
return participants
237-
}
238-
239-
func senderForTx(tx *types.Transaction) (common.Address, bool) {
240-
if !tx.Protected() && tx.Type() == types.LegacyTxType {
241-
return common.Address{}, false
242-
}
243-
244-
signer := types.LatestSignerForChainID(tx.ChainId())
245-
sender, err := types.Sender(signer, tx)
246-
if err != nil {
247-
return common.Address{}, false
248-
}
249-
250-
return sender, true
251-
}
252-
253-
func recipientForTx(tx *types.Transaction) (common.Address, bool) {
254-
if tx.To() == nil {
255-
return common.Address{}, false
256-
}
257-
258-
data := tx.Data()
259-
if len(data) < 4+32+32 {
260-
return common.Address{}, false
261-
}
262-
263-
recipientOffset := 4 + 12
264-
return common.BytesToAddress(data[recipientOffset : recipientOffset+20]), true
265-
}
266-
267-
func containsAddress(addresses []common.Address, target common.Address) bool {
268-
for _, address := range addresses {
269-
if address == target {
270-
return true
271-
}
272-
}
273-
return false
225+
// Stats returns statistics about processed transactions.
226+
// Returns (total transactions processed, invalid transactions).
227+
func (q *TxQueue) Stats() (int, int) {
228+
q.mu.RLock()
229+
defer q.mu.RUnlock()
230+
return q.total, q.invalid
274231
}
275232

276233
// Handle processes block notifications from the synchronizer and marks transactions as complete.

gateway/core/txqueue_helpers.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: LGPL-3.0-or-later
5+
*/
6+
7+
package core
8+
9+
import (
10+
"github.com/ethereum/go-ethereum/common"
11+
"github.com/ethereum/go-ethereum/core/types"
12+
)
13+
14+
// participantsForTx extracts the sender and recipient addresses from a transaction.
15+
// Returns a slice containing unique participant addresses (1 or 2 elements).
16+
func participantsForTx(tx *types.Transaction) []common.Address {
17+
participants := make([]common.Address, 0, 2)
18+
19+
if sender, ok := senderForTx(tx); ok {
20+
participants = append(participants, sender)
21+
}
22+
23+
if recipient, ok := recipientForTx(tx); ok && !containsAddress(participants, recipient) {
24+
participants = append(participants, recipient)
25+
}
26+
27+
return participants
28+
}
29+
30+
// senderForTx extracts the sender address from a transaction.
31+
// Returns (address, true) if successful, (zero address, false) otherwise.
32+
func senderForTx(tx *types.Transaction) (common.Address, bool) {
33+
if !tx.Protected() && tx.Type() == types.LegacyTxType {
34+
return common.Address{}, false
35+
}
36+
37+
signer := types.LatestSignerForChainID(tx.ChainId())
38+
sender, err := types.Sender(signer, tx)
39+
if err != nil {
40+
return common.Address{}, false
41+
}
42+
43+
return sender, true
44+
}
45+
46+
// recipientForTx extracts the recipient address from a transaction.
47+
// For ERC20 transfers, it extracts the recipient from the calldata.
48+
// Returns (address, true) if successful, (zero address, false) otherwise.
49+
func recipientForTx(tx *types.Transaction) (common.Address, bool) {
50+
if tx.To() == nil {
51+
return common.Address{}, false
52+
}
53+
54+
data := tx.Data()
55+
if len(data) < 4+32+32 {
56+
return common.Address{}, false
57+
}
58+
59+
// Extract recipient from ERC20 transfer calldata (offset 4 + 12 bytes)
60+
recipientOffset := 4 + 12
61+
return common.BytesToAddress(data[recipientOffset : recipientOffset+20]), true
62+
}
63+
64+
// containsAddress checks if a slice of addresses contains the target address.
65+
func containsAddress(addresses []common.Address, target common.Address) bool {
66+
for _, address := range addresses {
67+
if address == target {
68+
return true
69+
}
70+
}
71+
return false
72+
}
73+
74+
// Made with Bob

0 commit comments

Comments
 (0)