TxPool is a standalone transaction pool service built in Go. It provides a peer-to-peer gossip layer using libp2p Gossipsub, and exposes a gRPC API for interaction with application layer logic
This service is designed to be run as a standalone daemon, allowing applications to submit and retrieve transactions via gRPC, while the pool automatically propagates valid transactions to peer nodes in the network.
- Decentralized Gossip: Uses libp2p Gossipsub for efficient, fault tolerant transaction propagation.
- In Memory Mempool: Maintains a deduplicated, FIFO queue of incoming transactions.
- gRPC API: Applications may submit transactions and fetch pending txs for block proposal.
- Validation: Modular framework for transaction validation.
txpool/
├── cmd/ # Main entrypoint
├── internal/
├── pkg/
│ ├── api/ # gRPC server
│ ├── network/ # P2P networking layer
│ ├── pool/ # Transaction pool logic
│ └── types/
├── proto/ # Protobuf definition
├── test/ # Test app and integration tests
├── Dockerfile
├── docker-compose.yaml
└── MakefileA client submits a transaction to any node's public gRPC interface. The node:
- Validates and stores the transaction in its local pool storage.
- Broadcasts a
GossipMessage_Txevent using libp2p gossipsub to inform other peers.
All nodes are subscribed to the txpool topic. Upon receiving a gossiped message:
- The transaction handler parses the message type.
- If it's a
GossipMessage_Tx, the node validates and inserts the transaction into its own local pool storage.
Future optimization: Add conditional rebroadcasting or acknowledgment logic for sparsely connected networks.
When the gRPC Reap method is called (hypothetically by a block proposer):
- The node removes
ntransactions from the head of its local pool. - The node immediately broadcasts a
GossipMessage_Evictmessage with all reaped transaction IDs.
When a node receives a GossipMessage_Evict:
- The handler parses the list of transaction IDs.
- Each included transaction is evicted from local pool storage, ensuring global consistency across nodes.
- Go 1.23+
- Docker
protoc+protoc-gen-go,protoc-gen-go-grpc
Bring up a single node network.
make proto # Generate proto types
make build # Build binary
make run # Run locallyBring up a 3 node testnet.
The beacon node will be listening on :9090, with the remaining nodes listening on :9091 and :9092 respectively.
make up # Start 3 node testnet
make down # Teardown testnetThe network is strongly connected, and its topology is as follows:
A: B, C
B: A
C: A
Future considerations include making the network a fully connected mesh, though this will necessitate an additional peer discovery protocol/module.
In order to interact with the gRPC endpoint make sure to install either grpcurl or grpcui
SubmitTx(PostTx)→ adds and gossips a transactionGetPending(max)→ fetches and removes pending txs from poolPeekPending(max)→ returns a preview of the number of requested pending transactions in the poolSize(max)→ returns the current number of pending transactionsPurge()→ removes all transactions from the mempool
Submit Transactions
grpcurl -plaintext -d '{
"id": "abc123",
"author": "alice",
"body": "hello world"
}' localhost:9090 txpool.TxPool/SubmitTxReap Pending Transactions
grpcurl -plaintext -d '{"max": 10}' localhost:9090 txpool.TxPool/GetPendingPeek Pending Transactions
grpcurl -plaintext -d '{
"max": 10
}' localhost:9090 txpool.TxPool/PeekPendingGet Pool Size
grpcurl -plaintext -d '{}' localhost:9090 txpool.TxPool/GetSizePurge Pool
grpcurl -plaintext -d '{
"max": 5
}' localhost:9090 txpool.TxPool/Purge