Skip to content

Commit 5d6f580

Browse files
authored
Merge pull request #25 from kuba-4chain/feat/get-txs-batching
feat!: improve performance of HandleTransactionGet, by requesting all transactions from InvMsg at once
2 parents f57e79b + 684dd18 commit 5d6f580

File tree

6 files changed

+99
-89
lines changed

6 files changed

+99
-89
lines changed

examples/simple/handler.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package main
22

33
import (
44
"fmt"
5-
65
"log/slog"
76

87
"github.com/libsv/go-p2p"
@@ -15,10 +14,10 @@ type SimplePeerHandler struct {
1514
logger *slog.Logger
1615
}
1716

18-
func (s *SimplePeerHandler) HandleTransactionGet(msg *wire.InvVect, peer p2p.PeerI) ([]byte, error) {
19-
s.logger.Info("Peer requested transaction", slog.String("hash", msg.Hash.String()), slog.String("peer", peer.String()))
20-
// You should implement a store and return the transaction bytes here.
21-
return nil, fmt.Errorf("transaction not found")
17+
func (s *SimplePeerHandler) HandleTransactionsGet(msgs []*wire.InvVect, peer p2p.PeerI) ([][]byte, error) {
18+
s.logger.Info("Peer requested transactions", slog.Int("count", len(msgs)), slog.String("peer", peer.String()))
19+
// You should implement a store and return the transactions bytes here.
20+
return nil, fmt.Errorf("transactions not found")
2221
}
2322

2423
func (s *SimplePeerHandler) HandleTransactionSent(msg *wire.MsgTx, peer p2p.PeerI) error {

interface.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ import (
77
"github.com/libsv/go-p2p/wire"
88
)
99

10-
var (
11-
ErrPeerNetworkMismatch = fmt.Errorf("peer network mismatch")
12-
)
10+
var ErrPeerNetworkMismatch = fmt.Errorf("peer network mismatch")
1311

1412
type PeerManagerI interface {
1513
AnnounceTransaction(txHash *chainhash.Hash, peers []PeerI) []PeerI
@@ -36,7 +34,7 @@ type PeerI interface {
3634
}
3735

3836
type PeerHandlerI interface {
39-
HandleTransactionGet(msg *wire.InvVect, peer PeerI) ([]byte, error)
37+
HandleTransactionsGet(msgs []*wire.InvVect, peer PeerI) ([][]byte, error)
4038
HandleTransactionSent(msg *wire.MsgTx, peer PeerI) error
4139
HandleTransactionAnnouncement(msg *wire.InvVect, peer PeerI) error
4240
HandleTransactionRejection(rejMsg *wire.MsgReject, peer PeerI) error

peer.go

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -550,36 +550,43 @@ func (p *Peer) startReadHandler(ctx context.Context) {
550550
}
551551

552552
func (p *Peer) handleGetDataMsg(dataMsg *wire.MsgGetData, logger *slog.Logger) {
553+
txRequests := make([]*wire.InvVect, 0)
554+
553555
for _, invVect := range dataMsg.InvList {
554556
switch invVect.Type {
555557
case wire.InvTypeTx:
556558
logger.Debug("Request for TX", slog.String(hashKey, invVect.Hash.String()))
557-
558-
txBytes, err := p.peerHandler.HandleTransactionGet(invVect, p)
559-
if err != nil {
560-
logger.Warn("Unable to fetch tx from store", slog.String(hashKey, invVect.Hash.String()), slog.String(typeKey, invVect.Type.String()), slog.String(errKey, err.Error()))
561-
continue
562-
}
563-
564-
if txBytes == nil {
565-
logger.Warn("tx does not exist", slog.String(hashKey, invVect.Hash.String()), slog.String(typeKey, invVect.Type.String()))
566-
continue
567-
}
568-
569-
tx, err := bsvutil.NewTxFromBytes(txBytes)
570-
if err != nil {
571-
logger.Error("failed to parse tx", slog.String(hashKey, invVect.Hash.String()), slog.String(typeKey, invVect.Type.String()), slog.String("rawHex", hex.EncodeToString(txBytes)), slog.String(errKey, err.Error()))
572-
continue
573-
}
574-
575-
p.writeChan <- tx.MsgTx()
559+
txRequests = append(txRequests, invVect)
576560

577561
case wire.InvTypeBlock:
578562
logger.Info("Request for block", slog.String(hashKey, invVect.Hash.String()), slog.String(typeKey, invVect.Type.String()))
563+
continue
579564

580565
default:
581566
logger.Warn("Unknown type", slog.String(hashKey, invVect.Hash.String()), slog.String(typeKey, invVect.Type.String()))
567+
continue
568+
}
569+
}
570+
571+
rawTxs, err := p.peerHandler.HandleTransactionsGet(txRequests, p)
572+
if err != nil {
573+
logger.Warn("Unable to fetch txs from store", slog.Int("count", len(txRequests)), slog.String(errKey, err.Error()))
574+
return
575+
}
576+
577+
for _, txBytes := range rawTxs {
578+
if txBytes == nil {
579+
logger.Warn("tx does not exist")
580+
continue
581+
}
582+
583+
tx, err := bsvutil.NewTxFromBytes(txBytes)
584+
if err != nil {
585+
logger.Error("failed to parse tx", slog.String("rawHex", hex.EncodeToString(txBytes)), slog.String(errKey, err.Error()))
586+
continue
582587
}
588+
589+
p.writeChan <- tx.MsgTx()
583590
}
584591
}
585592

peer_handler_gen_mock.go

Lines changed: 50 additions & 50 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

peer_handler_mock.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,23 @@ func NewMockPeerHandler() *MockPeerHandler {
2727
}
2828
}
2929

30-
func (m *MockPeerHandler) HandleTransactionGet(msg *wire.InvVect, _ PeerI) ([]byte, error) {
30+
func (m *MockPeerHandler) HandleTransactionsGet(msgs []*wire.InvVect, _ PeerI) ([][]byte, error) {
3131
m.mu.Lock()
3232
defer m.mu.Unlock()
3333

34-
m.transactionGet = append(m.transactionGet, *msg)
34+
rawTxs := make([][]byte, 0)
3535

36-
bytes, ok := m.transactionGetBytes[msg.Hash.String()]
37-
if !ok {
38-
return nil, fmt.Errorf("no bytes for transaction %s", msg.Hash.String())
36+
for _, msg := range msgs {
37+
m.transactionGet = append(m.transactionGet, *msg)
38+
bytes, ok := m.transactionGetBytes[msg.Hash.String()]
39+
if !ok {
40+
return nil, fmt.Errorf("no bytes for transaction %s", msg.Hash.String())
41+
}
42+
43+
rawTxs = append(rawTxs, bytes)
3944
}
40-
return bytes, nil
45+
46+
return rawTxs, nil
4147
}
4248

4349
func (m *MockPeerHandler) GetTransactionGet() []wire.InvVect {

test/peer_integration_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ package test
22

33
import (
44
"fmt"
5-
"github.com/libsv/go-p2p"
65
"log"
76
"log/slog"
87
"os"
98
"testing"
109
"time"
1110

11+
"github.com/libsv/go-p2p"
12+
1213
"github.com/libsv/go-p2p/wire"
1314
"github.com/ory/dockertest/v3"
1415
"github.com/ory/dockertest/v3/docker"
@@ -19,7 +20,7 @@ const (
1920
p2pPortBinding = "18335"
2021
)
2122

22-
//go:generate moq -out ./peer_handler_gen_mock.go . PeerHandlerI
23+
//go:generate moq -out ../peer_handler_gen_mock.go ../ PeerHandlerI
2324

2425
var (
2526
pool *dockertest.Pool
@@ -148,15 +149,14 @@ func TestNewPeer(t *testing.T) {
148149
})
149150

150151
t.Run("announce transaction", func(t *testing.T) {
151-
152152
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug}))
153153

154154
pm := p2p.NewPeerManager(logger, wire.TestNet)
155155
require.NotNil(t, pm)
156156

157157
peerHandler := &p2p.PeerHandlerIMock{
158-
HandleTransactionGetFunc: func(msg *wire.InvVect, peer p2p.PeerI) ([]byte, error) {
159-
return TX1RawBytes, nil
158+
HandleTransactionsGetFunc: func(msgs []*wire.InvVect, peer p2p.PeerI) ([][]byte, error) {
159+
return [][]byte{TX1RawBytes}, nil
160160
},
161161
}
162162

0 commit comments

Comments
 (0)