mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 14:21:14 +00:00
This change has two main effects: 1. Remove most of the Async methods from the abci.Client interface. Remaining are FlushAsync, CommitTxAsync, and DeliverTxAsync. 2. Rename the synchronous methods to remove the "Sync" suffix. The rest of the change is updating the implementations, subsets, and mocks of the interface, along with the call sites that point to them. * Fix stringly-typed mock stubs. * Rename helper method.
166 lines
5.0 KiB
Go
166 lines
5.0 KiB
Go
package core
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"math/rand"
|
|
"time"
|
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
"github.com/tendermint/tendermint/internal/mempool"
|
|
"github.com/tendermint/tendermint/internal/state/indexer"
|
|
tmmath "github.com/tendermint/tendermint/libs/math"
|
|
"github.com/tendermint/tendermint/rpc/coretypes"
|
|
"github.com/tendermint/tendermint/types"
|
|
)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// NOTE: tx should be signed, but this is only checked at the app level (not by Tendermint!)
|
|
|
|
// BroadcastTxAsync returns right away, with no response. Does not wait for
|
|
// CheckTx nor DeliverTx results.
|
|
// More: https://docs.tendermint.com/master/rpc/#/Tx/broadcast_tx_async
|
|
func (env *Environment) BroadcastTxAsync(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
|
|
err := env.Mempool.CheckTx(ctx, tx, nil, mempool.TxInfo{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &coretypes.ResultBroadcastTx{Hash: tx.Hash()}, nil
|
|
}
|
|
|
|
// BroadcastTxSync returns with the response from CheckTx. Does not wait for
|
|
// DeliverTx result.
|
|
// More: https://docs.tendermint.com/master/rpc/#/Tx/broadcast_tx_sync
|
|
func (env *Environment) BroadcastTxSync(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
|
|
resCh := make(chan *abci.Response, 1)
|
|
err := env.Mempool.CheckTx(
|
|
ctx,
|
|
tx,
|
|
func(res *abci.Response) { resCh <- res },
|
|
mempool.TxInfo{},
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
res := <-resCh
|
|
r := res.GetCheckTx()
|
|
|
|
return &coretypes.ResultBroadcastTx{
|
|
Code: r.Code,
|
|
Data: r.Data,
|
|
Log: r.Log,
|
|
Codespace: r.Codespace,
|
|
MempoolError: r.MempoolError,
|
|
Hash: tx.Hash(),
|
|
}, nil
|
|
}
|
|
|
|
// BroadcastTxCommit returns with the responses from CheckTx and DeliverTx.
|
|
// More: https://docs.tendermint.com/master/rpc/#/Tx/broadcast_tx_commit
|
|
func (env *Environment) BroadcastTxCommit(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTxCommit, error) {
|
|
resCh := make(chan *abci.Response, 1)
|
|
err := env.Mempool.CheckTx(
|
|
ctx,
|
|
tx,
|
|
func(res *abci.Response) { resCh <- res },
|
|
mempool.TxInfo{},
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
r := (<-resCh).GetCheckTx()
|
|
|
|
if !indexer.KVSinkEnabled(env.EventSinks) {
|
|
return &coretypes.ResultBroadcastTxCommit{
|
|
CheckTx: *r,
|
|
Hash: tx.Hash(),
|
|
},
|
|
errors.New("cannot confirm transaction because kvEventSink is not enabled")
|
|
}
|
|
|
|
startAt := time.Now()
|
|
timer := time.NewTimer(0)
|
|
defer timer.Stop()
|
|
|
|
count := 0
|
|
for {
|
|
count++
|
|
select {
|
|
case <-ctx.Done():
|
|
env.Logger.Error("error on broadcastTxCommit",
|
|
"duration", time.Since(startAt),
|
|
"err", err)
|
|
return &coretypes.ResultBroadcastTxCommit{
|
|
CheckTx: *r,
|
|
Hash: tx.Hash(),
|
|
}, fmt.Errorf("timeout waiting for commit of tx %s (%s)",
|
|
tx.Hash(), time.Since(startAt))
|
|
case <-timer.C:
|
|
txres, err := env.Tx(ctx, tx.Hash(), false)
|
|
if err != nil {
|
|
jitter := 100*time.Millisecond + time.Duration(rand.Int63n(int64(time.Second))) // nolint: gosec
|
|
backoff := 100 * time.Duration(count) * time.Millisecond
|
|
timer.Reset(jitter + backoff)
|
|
continue
|
|
}
|
|
|
|
return &coretypes.ResultBroadcastTxCommit{
|
|
CheckTx: *r,
|
|
DeliverTx: txres.TxResult,
|
|
Hash: tx.Hash(),
|
|
Height: txres.Height,
|
|
}, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
// UnconfirmedTxs gets unconfirmed transactions from the mempool in order of priority
|
|
// More: https://docs.tendermint.com/master/rpc/#/Info/unconfirmed_txs
|
|
func (env *Environment) UnconfirmedTxs(ctx context.Context, pagePtr, perPagePtr *int) (*coretypes.ResultUnconfirmedTxs, error) {
|
|
totalCount := env.Mempool.Size()
|
|
perPage := env.validatePerPage(perPagePtr)
|
|
page, err := validatePage(pagePtr, perPage, totalCount)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
skipCount := validateSkipCount(page, perPage)
|
|
|
|
txs := env.Mempool.ReapMaxTxs(skipCount + tmmath.MinInt(perPage, totalCount-skipCount))
|
|
result := txs[skipCount:]
|
|
|
|
return &coretypes.ResultUnconfirmedTxs{
|
|
Count: len(result),
|
|
Total: totalCount,
|
|
TotalBytes: env.Mempool.SizeBytes(),
|
|
Txs: result}, nil
|
|
}
|
|
|
|
// NumUnconfirmedTxs gets number of unconfirmed transactions.
|
|
// More: https://docs.tendermint.com/master/rpc/#/Info/num_unconfirmed_txs
|
|
func (env *Environment) NumUnconfirmedTxs(ctx context.Context) (*coretypes.ResultUnconfirmedTxs, error) {
|
|
return &coretypes.ResultUnconfirmedTxs{
|
|
Count: env.Mempool.Size(),
|
|
Total: env.Mempool.Size(),
|
|
TotalBytes: env.Mempool.SizeBytes()}, nil
|
|
}
|
|
|
|
// CheckTx checks the transaction without executing it. The transaction won't
|
|
// be added to the mempool either.
|
|
// More: https://docs.tendermint.com/master/rpc/#/Tx/check_tx
|
|
func (env *Environment) CheckTx(ctx context.Context, tx types.Tx) (*coretypes.ResultCheckTx, error) {
|
|
res, err := env.ProxyAppMempool.CheckTx(ctx, abci.RequestCheckTx{Tx: tx})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &coretypes.ResultCheckTx{ResponseCheckTx: *res}, nil
|
|
}
|
|
|
|
func (env *Environment) RemoveTx(ctx context.Context, txkey types.TxKey) error {
|
|
return env.Mempool.RemoveTxByKey(txkey)
|
|
}
|