Skip to content

Add mempool enpoints #1035

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c7d92bb
add mempool enpoints
YeahNotSewerSide Apr 4, 2025
feee7c6
add metrics for executables
YeahNotSewerSide Apr 4, 2025
dfcf871
lint
YeahNotSewerSide Apr 4, 2025
de6b4f9
modernize
YeahNotSewerSide Apr 4, 2025
25420bf
apply suggestions
YeahNotSewerSide Apr 7, 2025
2a59313
fix: PR suggestions
YeahNotSewerSide Apr 8, 2025
8dc41ca
fix: apply PR suggestions
YeahNotSewerSide Apr 8, 2025
68a44ab
feat: separate logic into functions
YeahNotSewerSide Apr 8, 2025
9a999af
lint
YeahNotSewerSide Apr 8, 2025
16f8c46
Merge branch 'master' into andrew/feat/mempool-enpoints
freemanzMrojo Apr 8, 2025
21ea5a6
Hashes -> IDs
YeahNotSewerSide Apr 9, 2025
696ce89
move StringToAddress function
YeahNotSewerSide Apr 9, 2025
71a545d
remove 'to' filter
YeahNotSewerSide Apr 10, 2025
493b8a2
remove executables from status response
YeahNotSewerSide Apr 10, 2025
5996534
apply PR suggestion
YeahNotSewerSide Apr 14, 2025
546a1f8
add 404 error to docs
YeahNotSewerSide Apr 14, 2025
3913c38
rename flag
YeahNotSewerSide Apr 17, 2025
f43ed9b
add flag to solo
YeahNotSewerSide Apr 17, 2025
fb53d00
Merge branch 'master' into andrew/feat/mempool-enpoints
otherview Apr 17, 2025
b6dd2de
replace GaugeVec with Gauge
YeahNotSewerSide Apr 22, 2025
d4a20f1
move enableTxpool to the structure
YeahNotSewerSide Apr 22, 2025
0ef76d7
Total -> Amount
YeahNotSewerSide Apr 22, 2025
bc6ecb6
move filterTransactions function
YeahNotSewerSide Apr 22, 2025
5b231df
simplify transactions filtering
YeahNotSewerSide Apr 22, 2025
9482dd9
maintain same receiver
YeahNotSewerSide Apr 22, 2025
c1f3390
Update txpool/tx_pool.go
otherview Apr 22, 2025
c7e9c5e
Merge branch 'master' into andrew/feat/mempool-enpoints
otherview Apr 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type Config struct {
AllowedTracers []string
SoloMode bool
EnableDeprecated bool
EnableTxpool bool
}

// New return api router
Expand Down Expand Up @@ -92,7 +93,7 @@ func New(
Mount(router, "/transactions")
debug.New(repo, stater, forkConfig, config.CallGasLimit, config.AllowCustomTracer, bft, config.AllowedTracers, config.SoloMode).
Mount(router, "/debug")
node.New(nw).
node.New(nw, txPool, config.EnableTxpool).
Mount(router, "/node")
subs := subscriptions.New(repo, origins, config.BacktraceLimit, txPool, config.EnableDeprecated)
subs.Mount(router, "/subscriptions")
Expand Down
104 changes: 104 additions & 0 deletions api/doc/thor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,79 @@ paths:
schema:
$ref: '#/components/schemas/GetPeersResponse'

/node/txpool:
get:
tags:
- Node
summary: Retrieve transactions from transactions pool
description: |
Retrieve transactions that are currently in the txpool (pending transactions).
The response can be filtered by sender (origin) addresses.

The transactions can be returned either as a list of transaction IDs or as expanded transaction objects.
parameters:
- name: expanded
in: query
description: |
Whether to return expanded transaction details (true) or just transaction IDs (false).
If omitted, defaults to false.
required: false
schema:
type: boolean
- name: origin
in: query
description: |
Filter transactions by sender address.
required: false
schema:
type: string
pattern: '^0x[0-9a-fA-F]{40}$'
responses:
'200':
description: OK
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/TransactionsIDs'
- $ref: '#/components/schemas/Transactions'
'400':
description: Bad Request
content:
text/plain:
schema:
type: string
example: 'Invalid address'
'404':
description: Endpoint is disabled
content:
text/plain:
schema:
type: string
example: '404 Not Found'

/node/txpool/status:
get:
tags:
- Node
summary: Get txpool status
description: |
Retrieve the current status of the txpool, including the number of pending transactions.
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
'404':
description: Endpoint is disabled
content:
text/plain:
schema:
type: string
example: '404 Not Found'

/subscriptions/block:
get:
tags:
Expand Down Expand Up @@ -2255,6 +2328,37 @@ components:
example: false
nullable: false

Status:
type: object
title: Status
properties:
total:
type: integer
format: uint
description: The total number of transactions currently in the txpool
example: 42
nullable: false

TransactionsIDs:
type: array
title: TransactionsIDs
name: TransactionsIDs
description: Array of transaction IDs currently in the txpool
items:
type: string
format: hex
pattern: '^0x[0-9a-f]{64}$'
example:
- '0x284bba50ef777889ff1a367ed0b38d5e5626714477c40de38d71cedd6f9fa477'
- '0x4de71f2d588aa8a1ea00fe8312d92966da424d9939a511fc0be81e65fad52af8'

Transactions:
type: array
title: Transactions
description: Array of expanded transaction objects currently in the txpool
items:
$ref: '#/components/schemas/Tx'

parameters:
GetAddressInPath:
name: address
Expand Down
113 changes: 111 additions & 2 deletions api/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,28 @@ package node
import (
"net/http"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/gorilla/mux"
"github.com/pkg/errors"
"github.com/vechain/thor/v2/api/transactions"
"github.com/vechain/thor/v2/api/utils"
"github.com/vechain/thor/v2/thor"
"github.com/vechain/thor/v2/tx"
"github.com/vechain/thor/v2/txpool"
)

type Node struct {
nw Network
pool *txpool.TxPool
nw Network
enableTxpool bool
}

func New(nw Network) *Node {
func New(nw Network, pool *txpool.TxPool, enableTxpool bool) *Node {
return &Node{
pool,
nw,
enableTxpool,
}
}

Expand All @@ -30,11 +41,109 @@ func (n *Node) handleNetwork(w http.ResponseWriter, _ *http.Request) error {
return utils.WriteJSON(w, n.PeersStats())
}

func (n *Node) handleGetTransactions(w http.ResponseWriter, req *http.Request) error {
expanded, err := utils.StringToBoolean(req.URL.Query().Get("expanded"), false)
if err != nil {
return utils.BadRequest(errors.WithMessage(err, "expanded"))
}

originString := req.URL.Query().Get("origin")
origin, err := utils.StringToAddress(originString)
if err != nil {
return utils.BadRequest(errors.WithMessage(err, "origin"))
}

filteredTransactions := n.pool.Dump()
if origin != nil {
filteredTransactions, err = filterTransactions(*origin, filteredTransactions)
if err != nil {
return utils.BadRequest(err)
}
}

if expanded {
trxs := make([]transactions.Transaction, len(filteredTransactions))
for index, tx := range filteredTransactions {
origin, _ := tx.Origin()
delegator, _ := tx.Delegator()

txClauses := tx.Clauses()
cls := make(transactions.Clauses, len(txClauses))
for i, c := range txClauses {
cls[i] = transactions.Clause{
To: c.To(),
Value: math.HexOrDecimal256(*c.Value()),
Data: hexutil.Encode(c.Data()),
}
}
br := tx.BlockRef()
trxs[index] = transactions.Transaction{
ChainTag: tx.ChainTag(),
ID: tx.ID(),
Origin: origin,
BlockRef: hexutil.Encode(br[:]),
Expiration: tx.Expiration(),
Nonce: math.HexOrDecimal64(tx.Nonce()),
Size: uint32(tx.Size()),
GasPriceCoef: tx.GasPriceCoef(),
Gas: tx.Gas(),
DependsOn: tx.DependsOn(),
Clauses: cls,
Delegator: delegator,
}
}

return utils.WriteJSON(w, trxs)
}

transactions := make([]thor.Bytes32, len(filteredTransactions))
for index, tx := range filteredTransactions {
transactions[index] = tx.ID()
}

return utils.WriteJSON(w, transactions)
}

func (n *Node) handleGetTxpoolStatus(w http.ResponseWriter, req *http.Request) error {
total := n.pool.Len()
status := Status{
Amount: uint(total),
}
return utils.WriteJSON(w, status)
}

func (n *Node) Mount(root *mux.Router, pathPrefix string) {
sub := root.PathPrefix(pathPrefix).Subrouter()

sub.Path("/network/peers").
Methods(http.MethodGet).
Name("GET /node/network/peers").
HandlerFunc(utils.WrapHandlerFunc(n.handleNetwork))

if n.enableTxpool {
sub.Path("/txpool").
Methods(http.MethodGet).
Name("GET /node/txpool").
HandlerFunc(utils.WrapHandlerFunc(n.handleGetTransactions))
sub.Path("/txpool/status").
Methods(http.MethodGet).
Name("GET /node/txpool/status").
HandlerFunc(utils.WrapHandlerFunc(n.handleGetTxpoolStatus))
}
}

func filterTransactions(origin thor.Address, allTransactions tx.Transactions) (tx.Transactions, error) {
var filtered []*tx.Transaction

for _, tx := range allTransactions {
sender, err := tx.Origin()
if err != nil {
return nil, utils.BadRequest(errors.WithMessage(err, "filtering origin"))
}
if sender == origin {
filtered = append(filtered, tx)
}
}

return filtered, nil
}
Loading
Loading