Merge branch 'master' into wb/message-delay-metrics

This commit is contained in:
William Banfield
2022-01-12 18:47:01 -05:00
committed by GitHub
137 changed files with 1340 additions and 1436 deletions
+3 -3
View File
@@ -24,7 +24,7 @@ jobs:
with:
go-version: "1.17"
- uses: actions/checkout@v2.4.0
- uses: technote-space/get-diff-action@v5
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.go
@@ -45,7 +45,7 @@ jobs:
with:
go-version: "1.17"
- uses: actions/checkout@v2.4.0
- uses: technote-space/get-diff-action@v5
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.go
@@ -67,7 +67,7 @@ jobs:
with:
go-version: "1.17"
- uses: actions/checkout@v2.4.0
- uses: technote-space/get-diff-action@v5
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.go
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
with:
go-version: '1.17'
- uses: actions/checkout@v2.4.0
- uses: technote-space/get-diff-action@v5
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.go
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
timeout-minutes: 8
steps:
- uses: actions/checkout@v2.4.0
- uses: technote-space/get-diff-action@v5
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.go
+2 -2
View File
@@ -20,7 +20,7 @@ jobs:
with:
go-version: "1.17"
- uses: actions/checkout@v2.4.0
- uses: technote-space/get-diff-action@v5
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.go
@@ -42,7 +42,7 @@ jobs:
needs: tests
steps:
- uses: actions/checkout@v2.4.0
- uses: technote-space/get-diff-action@v5
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.go
+1
View File
@@ -51,6 +51,7 @@ Special thanks to external contributors on this release:
- [internal/protoio] \#7325 Optimized `MarshalDelimited` by inlining the common case and using a `sync.Pool` in the worst case. (@odeke-em)
- [pubsub] \#7319 Performance improvements for the event query API (@creachadair)
- [node] \#7521 Define concrete type for seed node implementation (@spacech1mp)
### BUG FIXES
+3 -4
View File
@@ -60,7 +60,7 @@ var RootCmd = &cobra.Command{
}
if logger == nil {
logger = log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false)
logger = log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo)
}
if client == nil {
@@ -575,15 +575,14 @@ func cmdQuery(cmd *cobra.Command, args []string) error {
}
func cmdKVStore(cmd *cobra.Command, args []string) error {
logger := log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false)
logger := log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo)
// Create the application - in memory or persisted to disk
var app types.Application
if flagPersist == "" {
app = kvstore.NewApplication()
} else {
app = kvstore.NewPersistentKVStoreApplication(flagPersist)
app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore"))
app = kvstore.NewPersistentKVStoreApplication(logger, flagPersist)
}
// Start the listener
+9 -3
View File
@@ -76,7 +76,9 @@ func TestPersistentKVStoreKV(t *testing.T) {
if err != nil {
t.Fatal(err)
}
kvstore := NewPersistentKVStoreApplication(dir)
logger := log.NewTestingLogger(t)
kvstore := NewPersistentKVStoreApplication(logger, dir)
key := testKey
value := key
tx := []byte(key)
@@ -92,7 +94,9 @@ func TestPersistentKVStoreInfo(t *testing.T) {
if err != nil {
t.Fatal(err)
}
kvstore := NewPersistentKVStoreApplication(dir)
logger := log.NewTestingLogger(t)
kvstore := NewPersistentKVStoreApplication(logger, dir)
InitKVStore(kvstore)
height := int64(0)
@@ -124,7 +128,9 @@ func TestValUpdates(t *testing.T) {
if err != nil {
t.Fatal(err)
}
kvstore := NewPersistentKVStoreApplication(dir)
logger := log.NewTestingLogger(t)
kvstore := NewPersistentKVStoreApplication(logger, dir)
// init with some validators
total := 10
+2 -6
View File
@@ -35,7 +35,7 @@ type PersistentKVStoreApplication struct {
logger log.Logger
}
func NewPersistentKVStoreApplication(dbDir string) *PersistentKVStoreApplication {
func NewPersistentKVStoreApplication(logger log.Logger, dbDir string) *PersistentKVStoreApplication {
name := "kvstore"
db, err := dbm.NewGoLevelDB(name, dbDir)
if err != nil {
@@ -47,7 +47,7 @@ func NewPersistentKVStoreApplication(dbDir string) *PersistentKVStoreApplication
return &PersistentKVStoreApplication{
app: &Application{state: state},
valAddrToPubKeyMap: make(map[string]cryptoproto.PublicKey),
logger: log.NewNopLogger(),
logger: logger,
}
}
@@ -55,10 +55,6 @@ func (app *PersistentKVStoreApplication) Close() error {
return app.app.state.db.Close()
}
func (app *PersistentKVStoreApplication) SetLogger(l log.Logger) {
app.logger = l
}
func (app *PersistentKVStoreApplication) Info(req types.RequestInfo) types.ResponseInfo {
res := app.app.Info(req)
res.LastBlockHeight = app.app.state.Height
+19 -7
View File
@@ -259,14 +259,26 @@ func (s *SocketServer) handleResponses(
responses <-chan *types.Response,
) {
bw := bufio.NewWriter(conn)
for res := range responses {
if err := types.WriteMessage(res, bw); err != nil {
closeConn <- fmt.Errorf("error writing message: %w", err)
return
}
if err := bw.Flush(); err != nil {
closeConn <- fmt.Errorf("error flushing write buffer: %w", err)
for {
select {
case <-ctx.Done():
return
case res := <-responses:
if err := types.WriteMessage(res, bw); err != nil {
select {
case <-ctx.Done():
case closeConn <- fmt.Errorf("error writing message: %w", err):
}
return
}
if err := bw.Flush(); err != nil {
select {
case <-ctx.Done():
case closeConn <- fmt.Errorf("error flushing write buffer: %w", err):
}
return
}
}
}
}
+5
View File
@@ -4,6 +4,7 @@ import (
"context"
"testing"
"github.com/fortytw2/leaktest"
"github.com/stretchr/testify/assert"
abciclientent "github.com/tendermint/tendermint/abci/client"
@@ -13,6 +14,8 @@ import (
)
func TestClientServerNoAddrPrefix(t *testing.T) {
t.Cleanup(leaktest.Check(t))
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -27,9 +30,11 @@ func TestClientServerNoAddrPrefix(t *testing.T) {
assert.NoError(t, err, "expected no error on NewServer")
err = server.Start(ctx)
assert.NoError(t, err, "expected no error on server.Start")
t.Cleanup(server.Wait)
client, err := abciclientent.NewClient(logger, addr, transport, true)
assert.NoError(t, err, "expected no error on NewClient")
err = client.Start(ctx)
assert.NoError(t, err, "expected no error on client.Start")
t.Cleanup(client.Wait)
}
+1 -2
View File
@@ -46,7 +46,7 @@ func main() {
rootCA = flag.String("rootcafile", "", "absolute path to root CA")
prometheusAddr = flag.String("prometheus-addr", "", "address for prometheus endpoint (host:port)")
logger = log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false).
logger = log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo).
With("module", "priv_val")
)
flag.Parse()
@@ -138,7 +138,6 @@ func main() {
defer opcancel()
go func() {
<-opctx.Done()
logger.Debug("SignerServer: calling Close")
if *prometheusAddr != "" {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
+1 -1
View File
@@ -15,7 +15,7 @@ var (
flagProfAddr = "pprof-laddr"
flagFrequency = "frequency"
logger = log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false)
logger = log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo)
)
// DebugCmd defines the root command containing subcommands that assist in
+1 -1
View File
@@ -102,7 +102,7 @@ func init() {
}
func runProxy(cmd *cobra.Command, args []string) error {
logger, err := log.NewDefaultLogger(logFormat, logLevel, false)
logger, err := log.NewDefaultLogger(logFormat, logLevel)
if err != nil {
return err
}
+4 -1
View File
@@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/cmd/tendermint/commands"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/rpc/client/local"
rpctest "github.com/tendermint/tendermint/rpc/test"
e2e "github.com/tendermint/tendermint/test/e2e/app"
@@ -49,7 +50,9 @@ func TestRollbackIntegration(t *testing.T) {
node2, _, err2 := rpctest.StartTendermint(ctx, cfg, app, rpctest.SuppressStdout)
require.NoError(t, err2)
client, err := local.New(node2.(local.NodeService))
logger := log.NewTestingLogger(t)
client, err := local.New(logger, node2.(local.NodeService))
require.NoError(t, err)
ticker := time.NewTicker(200 * time.Millisecond)
+2 -2
View File
@@ -13,7 +13,7 @@ import (
var (
config = cfg.DefaultConfig()
logger = log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false)
logger = log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo)
ctxTimeout = 4 * time.Second
)
@@ -55,7 +55,7 @@ var RootCmd = &cobra.Command{
return err
}
logger, err = log.NewDefaultLogger(config.LogFormat, config.LogLevel, false)
logger, err = log.NewDefaultLogger(config.LogFormat, config.LogLevel)
if err != nil {
return err
}
-1
View File
@@ -683,7 +683,6 @@ func TestP2PConfig() *P2PConfig {
cfg.ListenAddress = "tcp://127.0.0.1:36656"
cfg.AllowDuplicateIP = true
cfg.FlushThrottleTimeout = 10 * time.Millisecond
return cfg
}
+2
View File
@@ -9,6 +9,7 @@ import (
"text/template"
tmos "github.com/tendermint/tendermint/libs/os"
tmrand "github.com/tendermint/tendermint/libs/rand"
)
// DefaultDirPerm is the default permissions used when creating directories.
@@ -549,6 +550,7 @@ func ResetTestRootWithChainID(testName string, chainID string) (*Config, error)
}
config := TestConfig().SetRoot(rootDir)
config.Instrumentation.Namespace = fmt.Sprintf("%s_%s_%s", testName, chainID, tmrand.Str(16))
return config, nil
}
+1 -1
View File
@@ -3,7 +3,7 @@ module github.com/tendermint/tendermint
go 1.17
require (
github.com/BurntSushi/toml v0.4.1
github.com/BurntSushi/toml v1.0.0
github.com/adlio/schema v1.2.3
github.com/btcsuite/btcd v0.22.0-beta
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
+2 -1
View File
@@ -63,8 +63,9 @@ github.com/Antonboom/nilnil v0.1.0/go.mod h1:PhHLvRPSghY5Y7mX4TW+BHZQYo1A8flE5H2
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
+12 -2
View File
@@ -10,6 +10,7 @@ import (
"time"
"github.com/tendermint/tendermint/internal/consensus"
"github.com/tendermint/tendermint/internal/eventbus"
"github.com/tendermint/tendermint/internal/p2p"
sm "github.com/tendermint/tendermint/internal/state"
"github.com/tendermint/tendermint/internal/store"
@@ -96,7 +97,8 @@ type Reactor struct {
// stopping the p2p Channel(s).
poolWG sync.WaitGroup
metrics *consensus.Metrics
metrics *consensus.Metrics
eventBus *eventbus.EventBus
syncStartTime time.Time
}
@@ -113,6 +115,7 @@ func NewReactor(
peerUpdates *p2p.PeerUpdates,
blockSync bool,
metrics *consensus.Metrics,
eventBus *eventbus.EventBus,
) (*Reactor, error) {
if state.LastBlockHeight != store.Height() {
@@ -146,6 +149,7 @@ func NewReactor(
blockSyncOutBridgeCh: make(chan p2p.Envelope),
peerUpdates: peerUpdates,
metrics: metrics,
eventBus: eventBus,
syncStartTime: time.Time{},
}
@@ -354,7 +358,6 @@ func (r *Reactor) processPeerUpdates(ctx context.Context) {
for {
select {
case <-ctx.Done():
r.logger.Debug("stopped listening on peer updates channel; closing...")
return
case peerUpdate := <-r.peerUpdates.Updates():
r.processPeerUpdate(peerUpdate)
@@ -639,6 +642,13 @@ func (r *Reactor) GetRemainingSyncTime() time.Duration {
return time.Duration(int64(remain * float64(time.Second)))
}
func (r *Reactor) PublishStatus(ctx context.Context, event types.EventDataBlockSyncStatus) error {
if r.eventBus == nil {
return errors.New("event bus is not configured")
}
return r.eventBus.PublishEventBlockSyncStatus(ctx, event)
}
// atomicBool is an atomic Boolean, safe for concurrent use by multiple
// goroutines.
type atomicBool int32
+8 -7
View File
@@ -144,7 +144,6 @@ func (rts *reactorTestSuite) addNode(
time.Now(),
)
require.NoError(t, err)
lastCommit = types.NewCommit(
vote.Height,
vote.Round,
@@ -182,7 +181,9 @@ func (rts *reactorTestSuite) addNode(
chCreator,
rts.peerUpdates[nodeID],
rts.blockSync,
consensus.NopMetrics())
consensus.NopMetrics(),
nil, // eventbus, can be nil
)
require.NoError(t, err)
require.NoError(t, rts.reactors[nodeID].Start(ctx))
@@ -206,7 +207,7 @@ func TestReactor_AbruptDisconnect(t *testing.T) {
require.NoError(t, err)
defer os.RemoveAll(cfg.RootDir)
genDoc, privVals := factory.RandGenesisDoc(ctx, cfg, 1, false, 30)
genDoc, privVals := factory.RandGenesisDoc(ctx, t, cfg, 1, false, 30)
maxBlockHeight := int64(64)
rts := setup(ctx, t, genDoc, privVals[0], []int64{maxBlockHeight, 0}, 0)
@@ -245,7 +246,7 @@ func TestReactor_SyncTime(t *testing.T) {
require.NoError(t, err)
defer os.RemoveAll(cfg.RootDir)
genDoc, privVals := factory.RandGenesisDoc(ctx, cfg, 1, false, 30)
genDoc, privVals := factory.RandGenesisDoc(ctx, t, cfg, 1, false, 30)
maxBlockHeight := int64(101)
rts := setup(ctx, t, genDoc, privVals[0], []int64{maxBlockHeight, 0}, 0)
@@ -273,7 +274,7 @@ func TestReactor_NoBlockResponse(t *testing.T) {
defer os.RemoveAll(cfg.RootDir)
genDoc, privVals := factory.RandGenesisDoc(ctx, cfg, 1, false, 30)
genDoc, privVals := factory.RandGenesisDoc(ctx, t, cfg, 1, false, 30)
maxBlockHeight := int64(65)
rts := setup(ctx, t, genDoc, privVals[0], []int64{maxBlockHeight, 0}, 0)
@@ -325,7 +326,7 @@ func TestReactor_BadBlockStopsPeer(t *testing.T) {
defer os.RemoveAll(cfg.RootDir)
maxBlockHeight := int64(48)
genDoc, privVals := factory.RandGenesisDoc(ctx, cfg, 1, false, 30)
genDoc, privVals := factory.RandGenesisDoc(ctx, t, cfg, 1, false, 30)
rts := setup(ctx, t, genDoc, privVals[0], []int64{maxBlockHeight, 0, 0, 0, 0}, 1000)
@@ -359,7 +360,7 @@ func TestReactor_BadBlockStopsPeer(t *testing.T) {
//
// XXX: This causes a potential race condition.
// See: https://github.com/tendermint/tendermint/issues/6005
otherGenDoc, otherPrivVals := factory.RandGenesisDoc(ctx, cfg, 1, false, 30)
otherGenDoc, otherPrivVals := factory.RandGenesisDoc(ctx, t, cfg, 1, false, 30)
newNode := rts.network.MakeNode(ctx, t, p2ptest.NodeOptions{
MaxPeers: uint16(len(rts.nodes) + 1),
MaxConnected: uint16(len(rts.nodes) + 1),
+2 -8
View File
@@ -41,7 +41,7 @@ func TestByzantinePrevoteEquivocation(t *testing.T) {
tickerFunc := newMockTickerFunc(true)
appFunc := newKVStore
genDoc, privVals := factory.RandGenesisDoc(ctx, config, nValidators, false, 30)
genDoc, privVals := factory.RandGenesisDoc(ctx, t, config, nValidators, false, 30)
states := make([]*State, nValidators)
for i := 0; i < nValidators; i++ {
@@ -59,7 +59,7 @@ func TestByzantinePrevoteEquivocation(t *testing.T) {
defer os.RemoveAll(thisConfig.RootDir)
ensureDir(t, path.Dir(thisConfig.Consensus.WalFile()), 0700) // dir for wal
app := appFunc(t)
app := appFunc(t, logger)
vals := types.TM2PB.ValidatorUpdates(state.Validators)
app.InitChain(abci.RequestInitChain{Validators: vals})
@@ -139,7 +139,6 @@ func TestByzantinePrevoteEquivocation(t *testing.T) {
i := 0
for _, ps := range bzReactor.peers {
if i < len(bzReactor.peers)/2 {
bzNodeState.logger.Info("signed and pushed vote", "vote", prevote1, "peer", ps.peerID)
require.NoError(t, bzReactor.voteCh.Send(ctx,
p2p.Envelope{
To: ps.peerID,
@@ -148,7 +147,6 @@ func TestByzantinePrevoteEquivocation(t *testing.T) {
},
}))
} else {
bzNodeState.logger.Info("signed and pushed vote", "vote", prevote2, "peer", ps.peerID)
require.NoError(t, bzReactor.voteCh.Send(ctx,
p2p.Envelope{
To: ps.peerID,
@@ -161,7 +159,6 @@ func TestByzantinePrevoteEquivocation(t *testing.T) {
i++
}
} else {
bzNodeState.logger.Info("behaving normally")
bzNodeState.defaultDoPrevote(ctx, height, round)
}
}
@@ -173,7 +170,6 @@ func TestByzantinePrevoteEquivocation(t *testing.T) {
lazyNodeState := states[1]
lazyNodeState.decideProposal = func(ctx context.Context, height int64, round int32) {
lazyNodeState.logger.Info("Lazy Proposer proposing condensed commit")
require.NotNil(t, lazyNodeState.privValidator)
var commit *types.Commit
@@ -227,8 +223,6 @@ func TestByzantinePrevoteEquivocation(t *testing.T) {
lazyNodeState.Height, lazyNodeState.Round, part,
}, ""})
}
lazyNodeState.logger.Info("Signed proposal", "height", height, "round", round, "proposal", proposal)
lazyNodeState.logger.Debug(fmt.Sprintf("Signed proposal block: %v", block))
} else if !lazyNodeState.replayMode {
lazyNodeState.logger.Error("enterPropose: Error signing proposal", "height", height, "round", round, "err", err)
}
+12 -13
View File
@@ -6,7 +6,6 @@ import (
"fmt"
"io"
"os"
"path"
"path/filepath"
"sort"
"sync"
@@ -737,11 +736,11 @@ func randConsensusState(
nValidators int,
testName string,
tickerFunc func() TimeoutTicker,
appFunc func(t *testing.T) abci.Application,
appFunc func(t *testing.T, logger log.Logger) abci.Application,
configOpts ...func(*config.Config),
) ([]*State, cleanupFunc) {
genDoc, privVals := factory.RandGenesisDoc(ctx, cfg, nValidators, false, 30)
genDoc, privVals := factory.RandGenesisDoc(ctx, t, cfg, nValidators, false, 30)
css := make([]*State, nValidators)
logger := consensusLogger()
@@ -764,7 +763,7 @@ func randConsensusState(
ensureDir(t, filepath.Dir(thisConfig.Consensus.WalFile()), 0700) // dir for wal
app := appFunc(t)
app := appFunc(t, logger)
if appCloser, ok := app.(io.Closer); ok {
closeFuncs = append(closeFuncs, appCloser.Close)
@@ -797,11 +796,11 @@ func randConsensusNetWithPeers(
nPeers int,
testName string,
tickerFunc func() TimeoutTicker,
appFunc func(string) abci.Application,
appFunc func(log.Logger, string) abci.Application,
) ([]*State, *types.GenesisDoc, *config.Config, cleanupFunc) {
t.Helper()
genDoc, privVals := factory.RandGenesisDoc(ctx, cfg, nValidators, false, testMinPower)
genDoc, privVals := factory.RandGenesisDoc(ctx, t, cfg, nValidators, false, testMinPower)
css := make([]*State, nPeers)
logger := consensusLogger()
@@ -831,7 +830,7 @@ func randConsensusNetWithPeers(
require.NoError(t, err)
}
app := appFunc(path.Join(cfg.DBDir(), fmt.Sprintf("%s_%d", testName, i)))
app := appFunc(logger, filepath.Join(cfg.DBDir(), fmt.Sprintf("%s_%d", testName, i)))
vals := types.TM2PB.ValidatorUpdates(state.Validators)
if _, ok := app.(*kvstore.PersistentKVStoreApplication); ok {
// simulate handshake, receive app version. If don't do this, replay test will fail
@@ -859,7 +858,7 @@ func randGenesisState(
minPower int64,
) (sm.State, []types.PrivValidator) {
genDoc, privValidators := factory.RandGenesisDoc(ctx, cfg, numValidators, randPower, minPower)
genDoc, privValidators := factory.RandGenesisDoc(ctx, t, cfg, numValidators, randPower, minPower)
s0, err := sm.MakeGenesisState(genDoc)
require.NoError(t, err)
return s0, privValidators
@@ -912,21 +911,21 @@ func (m *mockTicker) Chan() <-chan timeoutInfo {
func (*mockTicker) SetLogger(log.Logger) {}
func newPersistentKVStore(t *testing.T) abci.Application {
func newPersistentKVStore(t *testing.T, logger log.Logger) abci.Application {
t.Helper()
dir, err := os.MkdirTemp("", "persistent-kvstore")
require.NoError(t, err)
return kvstore.NewPersistentKVStoreApplication(dir)
return kvstore.NewPersistentKVStoreApplication(logger, dir)
}
func newKVStore(_ *testing.T) abci.Application {
func newKVStore(_ *testing.T, _ log.Logger) abci.Application {
return kvstore.NewApplication()
}
func newPersistentKVStoreWithPath(dbDir string) abci.Application {
return kvstore.NewPersistentKVStoreApplication(dbDir)
func newPersistentKVStoreWithPath(logger log.Logger, dbDir string) abci.Application {
return kvstore.NewPersistentKVStoreApplication(logger, dbDir)
}
func signDataIsEqual(v1 *types.Vote, v2 *tmproto.Vote) bool {
-1
View File
@@ -123,7 +123,6 @@ func invalidDoPrevoteFunc(
cs.mtx.Unlock()
for _, ps := range r.peers {
cs.logger.Info("sending bad vote", "block", blockHash, "peer", ps.peerID)
require.NoError(t, r.voteCh.Send(ctx, p2p.Envelope{
To: ps.peerID,
Message: &tmcons.Vote{
-1
View File
@@ -99,7 +99,6 @@ func TestMempoolProgressInHigherRound(t *testing.T) {
if cs.Height == 2 && cs.Round == 0 {
// dont set the proposal in round 0 so we timeout and
// go to next round
cs.logger.Info("Ignoring set proposal at height 2, round 0")
return nil
}
return cs.defaultSetProposal(proposal)
+2 -2
View File
@@ -23,8 +23,8 @@ var (
// peerStateStats holds internal statistics for a peer.
type peerStateStats struct {
Votes int `json:"votes"`
BlockParts int `json:"block_parts"`
Votes int `json:"votes,string"`
BlockParts int `json:"block_parts,string"`
}
func (pss peerStateStats) String() string {
-1
View File
@@ -1455,7 +1455,6 @@ func (r *Reactor) processPeerUpdates(ctx context.Context) {
for {
select {
case <-ctx.Done():
r.logger.Debug("stopped listening on peer updates channel; closing...")
return
case peerUpdate := <-r.peerUpdates.Updates():
r.processPeerUpdate(ctx, peerUpdate)
+2 -2
View File
@@ -383,7 +383,7 @@ func TestReactorWithEvidence(t *testing.T) {
tickerFunc := newMockTickerFunc(true)
appFunc := newKVStore
genDoc, privVals := factory.RandGenesisDoc(ctx, cfg, n, false, 30)
genDoc, privVals := factory.RandGenesisDoc(ctx, t, cfg, n, false, 30)
states := make([]*State, n)
logger := consensusLogger()
@@ -398,7 +398,7 @@ func TestReactorWithEvidence(t *testing.T) {
defer os.RemoveAll(thisConfig.RootDir)
ensureDir(t, path.Dir(thisConfig.Consensus.WalFile()), 0700) // dir for wal
app := appFunc(t)
app := appFunc(t, logger)
vals := types.TM2PB.ValidatorUpdates(state.Validators)
app.InitChain(abci.RequestInitChain{Validators: vals})
+6 -7
View File
@@ -696,7 +696,6 @@ func TestMockProxyApp(t *testing.T) {
if txRes.Code == abci.CodeTypeOK {
validTxs++
} else {
logger.Debug("Invalid tx", "code", txRes.Code, "log", txRes.Log)
invalidTxs++
}
abciRes.DeliverTxs[txIndex] = txRes
@@ -764,7 +763,7 @@ func testHandshakeReplay(
testConfig, err := ResetConfig(fmt.Sprintf("%s_%v_s", t.Name(), mode))
require.NoError(t, err)
defer func() { _ = os.RemoveAll(testConfig.RootDir) }()
walBody, err := WALWithNBlocks(ctx, t, numBlocks)
walBody, err := WALWithNBlocks(ctx, t, logger, numBlocks)
require.NoError(t, err)
walFile := tempWALWithData(t, walBody)
cfg.Consensus.SetWalFile(walFile)
@@ -806,7 +805,7 @@ func testHandshakeReplay(
latestAppHash := state.AppHash
// make a new client creator
kvstoreApp := kvstore.NewPersistentKVStoreApplication(
kvstoreApp := kvstore.NewPersistentKVStoreApplication(logger,
filepath.Join(cfg.DBDir(), fmt.Sprintf("replay_test_%d_%d_a_r%d", nBlocks, mode, rand.Int())))
t.Cleanup(func() { require.NoError(t, kvstoreApp.Close()) })
@@ -960,7 +959,7 @@ func buildTMStateFromChain(
t.Helper()
// run the whole chain against this client to build up the tendermint state
kvstoreApp := kvstore.NewPersistentKVStoreApplication(
kvstoreApp := kvstore.NewPersistentKVStoreApplication(logger,
filepath.Join(cfg.DBDir(), fmt.Sprintf("replay_test_%d_%d_t", nBlocks, mode)))
defer kvstoreApp.Close()
clientCreator := abciclient.NewLocalCreator(kvstoreApp)
@@ -1023,8 +1022,7 @@ func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) {
genDoc, _ := sm.MakeGenesisDocFromFile(cfg.GenesisFile())
state.LastValidators = state.Validators.Copy()
// mode = 0 for committing all the blocks
blocks, err := sf.MakeBlocks(ctx, 3, &state, privVal)
require.NoError(t, err)
blocks := sf.MakeBlocks(ctx, t, 3, &state, privVal)
store.chain = blocks
@@ -1287,7 +1285,8 @@ func TestHandshakeUpdatesValidators(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
val, _ := factory.RandValidator(ctx, true, 10)
val, _, err := factory.RandValidator(ctx, true, 10)
require.NoError(t, err)
vals := types.NewValidatorSet([]*types.Validator{val})
app := &initChainApp{vals: types.TM2PB.ValidatorUpdates(vals)}
clientCreator := abciclient.NewLocalCreator(app)
+3 -22
View File
@@ -3,6 +3,7 @@ package consensus
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
@@ -18,10 +19,8 @@ import (
"github.com/tendermint/tendermint/crypto"
cstypes "github.com/tendermint/tendermint/internal/consensus/types"
"github.com/tendermint/tendermint/internal/eventbus"
"github.com/tendermint/tendermint/internal/libs/fail"
sm "github.com/tendermint/tendermint/internal/state"
tmevents "github.com/tendermint/tendermint/libs/events"
tmjson "github.com/tendermint/tendermint/libs/json"
"github.com/tendermint/tendermint/libs/log"
tmmath "github.com/tendermint/tendermint/libs/math"
tmos "github.com/tendermint/tendermint/libs/os"
@@ -254,14 +253,14 @@ func (cs *State) GetRoundState() *cstypes.RoundState {
func (cs *State) GetRoundStateJSON() ([]byte, error) {
cs.mtx.RLock()
defer cs.mtx.RUnlock()
return tmjson.Marshal(cs.RoundState)
return json.Marshal(cs.RoundState)
}
// GetRoundStateSimpleJSON returns a json of RoundStateSimple
func (cs *State) GetRoundStateSimpleJSON() ([]byte, error) {
cs.mtx.RLock()
defer cs.mtx.RUnlock()
return tmjson.Marshal(cs.RoundState.RoundStateSimple())
return json.Marshal(cs.RoundState.RoundStateSimple())
}
// GetValidators returns a copy of the current validators.
@@ -867,14 +866,6 @@ func (cs *State) receiveRoutine(ctx context.Context, maxSteps int) {
))
}
if _, ok := mi.Msg.(*VoteMessage); ok {
// we actually want to simulate failing during
// the previous WriteSync, but this isn't easy to do.
// Equivalent would be to fail here and manually remove
// some bytes from the end of the wal.
fail.Fail() // XXX
}
// handles proposals, block parts, votes
cs.handleMsg(ctx, mi)
@@ -1708,8 +1699,6 @@ func (cs *State) finalizeCommit(ctx context.Context, height int64) {
)
logger.Debug(fmt.Sprintf("%v", block))
fail.Fail() // XXX
// Save to blockStore.
if cs.blockStore.Height() < block.Height {
// NOTE: the seenCommit is local justification to commit this block,
@@ -1722,8 +1711,6 @@ func (cs *State) finalizeCommit(ctx context.Context, height int64) {
logger.Debug("calling finalizeCommit on already stored block", "height", block.Height)
}
fail.Fail() // XXX
// Write EndHeightMessage{} for this height, implying that the blockstore
// has saved the block.
//
@@ -1745,8 +1732,6 @@ func (cs *State) finalizeCommit(ctx context.Context, height int64) {
))
}
fail.Fail() // XXX
// Create a copy of the state for staging and an event cache for txs.
stateCopy := cs.state.Copy()
@@ -1765,16 +1750,12 @@ func (cs *State) finalizeCommit(ctx context.Context, height int64) {
return
}
fail.Fail() // XXX
// must be called before we update state
cs.RecordMetrics(height, block)
// NewHeightStep!
cs.updateToState(ctx, stateCopy)
fail.Fail() // XXX
// Private validator might have changed it's key pair => refetch pubkey.
if err := cs.updatePrivValidatorPubKey(ctx); err != nil {
logger.Error("failed to get private validator pubkey", "err", err)
-2
View File
@@ -81,7 +81,6 @@ func (t *timeoutTicker) stopTimer() {
select {
case <-t.timer.C:
default:
t.logger.Debug("Timer already stopped")
}
}
}
@@ -90,7 +89,6 @@ func (t *timeoutTicker) stopTimer() {
// timers are interupted and replaced by new ticks from later steps
// timeouts of 0 on the tickChan will be immediately relayed to the tockChan
func (t *timeoutTicker) timeoutRoutine(ctx context.Context) {
t.logger.Debug("Starting timeout routine")
var ti timeoutInfo
for {
select {
+2 -2
View File
@@ -1,12 +1,12 @@
package types
import (
"encoding/json"
"errors"
"fmt"
"strings"
"sync"
tmjson "github.com/tendermint/tendermint/libs/json"
tmmath "github.com/tendermint/tendermint/libs/math"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/tendermint/tendermint/types"
@@ -237,7 +237,7 @@ func (hvs *HeightVoteSet) StringIndented(indent string) string {
func (hvs *HeightVoteSet) MarshalJSON() ([]byte, error) {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
return tmjson.Marshal(hvs.toAllRoundVotes())
return json.Marshal(hvs.toAllRoundVotes())
}
func (hvs *HeightVoteSet) toAllRoundVotes() []roundVotes {
@@ -33,7 +33,7 @@ func TestPeerCatchupRounds(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
valSet, privVals := factory.RandValidatorSet(ctx, 10, 1)
valSet, privVals := factory.RandValidatorSet(ctx, t, 10, 1)
hvs := NewHeightVoteSet(cfg.ChainID(), 1, valSet)
+3 -3
View File
@@ -13,9 +13,9 @@ import (
// PeerRoundState contains the known state of a peer.
// NOTE: Read-only when returned by PeerState.GetRoundState().
type PeerRoundState struct {
Height int64 `json:"height"` // Height peer is at
Round int32 `json:"round"` // Round peer is at, -1 if unknown.
Step RoundStepType `json:"step"` // Step peer is at
Height int64 `json:"height,string"` // Height peer is at
Round int32 `json:"round"` // Round peer is at, -1 if unknown.
Step RoundStepType `json:"step"` // Step peer is at
// Estimated start of round 0 at this height
StartTime time.Time `json:"start_time"`
+4 -5
View File
@@ -31,13 +31,12 @@ import (
// persistent kvstore application and special consensus wal instance
// (byteBufferWAL) and waits until numBlocks are created.
// If the node fails to produce given numBlocks, it returns an error.
func WALGenerateNBlocks(ctx context.Context, t *testing.T, wr io.Writer, numBlocks int) (err error) {
func WALGenerateNBlocks(ctx context.Context, t *testing.T, logger log.Logger, wr io.Writer, numBlocks int) (err error) {
cfg := getConfig(t)
app := kvstore.NewPersistentKVStoreApplication(filepath.Join(cfg.DBDir(), "wal_generator"))
app := kvstore.NewPersistentKVStoreApplication(logger, filepath.Join(cfg.DBDir(), "wal_generator"))
t.Cleanup(func() { require.NoError(t, app.Close()) })
logger := log.TestingLogger().With("wal_generator", "wal_generator")
logger.Info("generating WAL (last height msg excluded)", "numBlocks", numBlocks)
// COPY PASTE FROM node.go WITH A FEW MODIFICATIONS
@@ -116,11 +115,11 @@ func WALGenerateNBlocks(ctx context.Context, t *testing.T, wr io.Writer, numBloc
}
// WALWithNBlocks returns a WAL content with numBlocks.
func WALWithNBlocks(ctx context.Context, t *testing.T, numBlocks int) (data []byte, err error) {
func WALWithNBlocks(ctx context.Context, t *testing.T, logger log.Logger, numBlocks int) (data []byte, err error) {
var b bytes.Buffer
wr := bufio.NewWriter(&b)
if err := WALGenerateNBlocks(ctx, t, wr, numBlocks); err != nil {
if err := WALGenerateNBlocks(ctx, t, logger, wr, numBlocks); err != nil {
return []byte{}, err
}
+7 -4
View File
@@ -45,7 +45,7 @@ func TestWALTruncate(t *testing.T) {
// 60 block's size nearly 70K, greater than group's headBuf size(4096 * 10),
// when headBuf is full, truncate content will Flush to the file. at this
// time, RotateFile is called, truncate content exist in each file.
err = WALGenerateNBlocks(ctx, t, wal.Group(), 60)
err = WALGenerateNBlocks(ctx, t, logger, wal.Group(), 60)
require.NoError(t, err)
time.Sleep(1 * time.Millisecond) // wait groupCheckDuration, make sure RotateFile run
@@ -136,13 +136,15 @@ func TestWALSearchForEndHeight(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
walBody, err := WALWithNBlocks(ctx, t, 6)
logger := log.NewTestingLogger(t)
walBody, err := WALWithNBlocks(ctx, t, logger, 6)
if err != nil {
t.Fatal(err)
}
walFile := tempWALWithData(t, walBody)
wal, err := NewWAL(log.TestingLogger(), walFile)
wal, err := NewWAL(logger, walFile)
require.NoError(t, err)
h := int64(3)
@@ -171,9 +173,10 @@ func TestWALPeriodicSync(t *testing.T) {
require.NoError(t, err)
wal.SetFlushInterval(walTestFlushInterval)
logger := log.NewTestingLogger(t)
// Generate some data
err = WALGenerateNBlocks(ctx, t, wal.Group(), 5)
err = WALGenerateNBlocks(ctx, t, logger, wal.Group(), 5)
require.NoError(t, err)
// We should have data in the buffer now
+1 -1
View File
@@ -41,7 +41,7 @@ func TestEvidencePoolBasic(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
valSet, privVals := factory.RandValidatorSet(ctx, 1, 10)
valSet, privVals := factory.RandValidatorSet(ctx, t, 1, 10)
blockStore.On("LoadBlockMeta", mock.AnythingOfType("int64")).Return(
&types.BlockMeta{Header: types.Header{Time: defaultEvidenceTime}},
-1
View File
@@ -255,7 +255,6 @@ func (r *Reactor) processPeerUpdates(ctx context.Context) {
case peerUpdate := <-r.peerUpdates.Updates():
r.processPeerUpdate(ctx, peerUpdate)
case <-ctx.Done():
r.logger.Debug("stopped listening on peer updates channel; closing...")
return
}
}
+32 -32
View File
@@ -201,17 +201,16 @@ func TestVerifyLightClientAttack_Equivocation(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
conflictingVals, conflictingPrivVals := factory.RandValidatorSet(ctx, 5, 10)
conflictingVals, conflictingPrivVals := factory.RandValidatorSet(ctx, t, 5, 10)
conflictingHeader, err := factory.MakeHeader(&types.Header{
conflictingHeader := factory.MakeHeader(t, &types.Header{
ChainID: evidenceChainID,
Height: 10,
Time: defaultEvidenceTime,
ValidatorsHash: conflictingVals.Hash(),
})
require.NoError(t, err)
trustedHeader, _ := factory.MakeHeader(&types.Header{
trustedHeader := factory.MakeHeader(t, &types.Header{
ChainID: evidenceChainID,
Height: 10,
Time: defaultEvidenceTime,
@@ -228,6 +227,7 @@ func TestVerifyLightClientAttack_Equivocation(t *testing.T) {
voteSet := types.NewVoteSet(evidenceChainID, 10, 1, tmproto.SignedMsgType(2), conflictingVals)
commit, err := factory.MakeCommit(ctx, blockID, 10, 1, voteSet, conflictingPrivVals[:4], defaultEvidenceTime)
require.NoError(t, err)
ev := &types.LightClientAttackEvidence{
ConflictingBlock: &types.LightBlock{
SignedHeader: &types.SignedHeader{
@@ -247,27 +247,26 @@ func TestVerifyLightClientAttack_Equivocation(t *testing.T) {
trustedCommit, err := factory.MakeCommit(ctx, trustedBlockID, 10, 1,
trustedVoteSet, conflictingPrivVals, defaultEvidenceTime)
require.NoError(t, err)
trustedSignedHeader := &types.SignedHeader{
Header: trustedHeader,
Commit: trustedCommit,
}
// good pass -> no error
err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, conflictingVals,
defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour)
assert.NoError(t, err)
require.NoError(t, evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, conflictingVals,
defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour))
// trusted and conflicting hashes are the same -> an error should be returned
err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, ev.ConflictingBlock.SignedHeader, conflictingVals,
defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour)
assert.Error(t, err)
assert.Error(t, evidence.VerifyLightClientAttack(ev, trustedSignedHeader, ev.ConflictingBlock.SignedHeader, conflictingVals,
defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour))
// conflicting header has different next validators hash which should have been correctly derived from
// the previous round
ev.ConflictingBlock.Header.NextValidatorsHash = crypto.CRandBytes(tmhash.Size)
err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, nil,
defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour)
assert.Error(t, err)
assert.Error(t, evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, nil,
defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour))
// revert next validators hash
ev.ConflictingBlock.Header.NextValidatorsHash = trustedHeader.NextValidatorsHash
@@ -300,17 +299,16 @@ func TestVerifyLightClientAttack_Amnesia(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
conflictingVals, conflictingPrivVals := factory.RandValidatorSet(ctx, 5, 10)
conflictingVals, conflictingPrivVals := factory.RandValidatorSet(ctx, t, 5, 10)
conflictingHeader, err := factory.MakeHeader(&types.Header{
conflictingHeader := factory.MakeHeader(t, &types.Header{
ChainID: evidenceChainID,
Height: height,
Time: defaultEvidenceTime,
ValidatorsHash: conflictingVals.Hash(),
})
require.NoError(t, err)
trustedHeader, _ := factory.MakeHeader(&types.Header{
trustedHeader := factory.MakeHeader(t, &types.Header{
ChainID: evidenceChainID,
Height: height,
Time: defaultEvidenceTime,
@@ -327,6 +325,7 @@ func TestVerifyLightClientAttack_Amnesia(t *testing.T) {
voteSet := types.NewVoteSet(evidenceChainID, height, 0, tmproto.SignedMsgType(2), conflictingVals)
commit, err := factory.MakeCommit(ctx, blockID, height, 0, voteSet, conflictingPrivVals, defaultEvidenceTime)
require.NoError(t, err)
ev := &types.LightClientAttackEvidence{
ConflictingBlock: &types.LightBlock{
SignedHeader: &types.SignedHeader{
@@ -346,20 +345,19 @@ func TestVerifyLightClientAttack_Amnesia(t *testing.T) {
trustedCommit, err := factory.MakeCommit(ctx, trustedBlockID, height, 1,
trustedVoteSet, conflictingPrivVals, defaultEvidenceTime)
require.NoError(t, err)
trustedSignedHeader := &types.SignedHeader{
Header: trustedHeader,
Commit: trustedCommit,
}
// good pass -> no error
err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, conflictingVals,
defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour)
assert.NoError(t, err)
require.NoError(t, evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, conflictingVals,
defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour))
// trusted and conflicting hashes are the same -> an error should be returned
err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, ev.ConflictingBlock.SignedHeader, conflictingVals,
defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour)
assert.Error(t, err)
assert.Error(t, evidence.VerifyLightClientAttack(ev, trustedSignedHeader, ev.ConflictingBlock.SignedHeader, conflictingVals,
defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour))
state := sm.State{
LastBlockTime: defaultEvidenceTime.Add(1 * time.Minute),
@@ -496,14 +494,16 @@ func makeLunaticEvidence(
totalVals, byzVals, phantomVals int,
commonTime, attackTime time.Time,
) (ev *types.LightClientAttackEvidence, trusted *types.LightBlock, common *types.LightBlock) {
commonValSet, commonPrivVals := factory.RandValidatorSet(ctx, totalVals, defaultVotingPower)
t.Helper()
commonValSet, commonPrivVals := factory.RandValidatorSet(ctx, t, totalVals, defaultVotingPower)
require.Greater(t, totalVals, byzVals)
// extract out the subset of byzantine validators in the common validator set
byzValSet, byzPrivVals := commonValSet.Validators[:byzVals], commonPrivVals[:byzVals]
phantomValSet, phantomPrivVals := factory.RandValidatorSet(ctx, phantomVals, defaultVotingPower)
phantomValSet, phantomPrivVals := factory.RandValidatorSet(ctx, t, phantomVals, defaultVotingPower)
conflictingVals := phantomValSet.Copy()
require.NoError(t, conflictingVals.UpdateWithChangeSet(byzValSet))
@@ -511,31 +511,30 @@ func makeLunaticEvidence(
conflictingPrivVals = orderPrivValsByValSet(ctx, t, conflictingVals, conflictingPrivVals)
commonHeader, err := factory.MakeHeader(&types.Header{
commonHeader := factory.MakeHeader(t, &types.Header{
ChainID: evidenceChainID,
Height: commonHeight,
Time: commonTime,
})
require.NoError(t, err)
trustedHeader, err := factory.MakeHeader(&types.Header{
trustedHeader := factory.MakeHeader(t, &types.Header{
ChainID: evidenceChainID,
Height: height,
Time: defaultEvidenceTime,
})
require.NoError(t, err)
conflictingHeader, err := factory.MakeHeader(&types.Header{
conflictingHeader := factory.MakeHeader(t, &types.Header{
ChainID: evidenceChainID,
Height: height,
Time: attackTime,
ValidatorsHash: conflictingVals.Hash(),
})
require.NoError(t, err)
blockID := factory.MakeBlockIDWithHash(conflictingHeader.Hash())
voteSet := types.NewVoteSet(evidenceChainID, height, 1, tmproto.SignedMsgType(2), conflictingVals)
commit, err := factory.MakeCommit(ctx, blockID, height, 1, voteSet, conflictingPrivVals, defaultEvidenceTime)
require.NoError(t, err)
ev = &types.LightClientAttackEvidence{
ConflictingBlock: &types.LightBlock{
SignedHeader: &types.SignedHeader{
@@ -559,10 +558,11 @@ func makeLunaticEvidence(
ValidatorSet: commonValSet,
}
trustedBlockID := factory.MakeBlockIDWithHash(trustedHeader.Hash())
trustedVals, privVals := factory.RandValidatorSet(ctx, totalVals, defaultVotingPower)
trustedVals, privVals := factory.RandValidatorSet(ctx, t, totalVals, defaultVotingPower)
trustedVoteSet := types.NewVoteSet(evidenceChainID, height, 1, tmproto.SignedMsgType(2), trustedVals)
trustedCommit, err := factory.MakeCommit(ctx, trustedBlockID, height, 1, trustedVoteSet, privVals, defaultEvidenceTime)
require.NoError(t, err)
trusted = &types.LightBlock{
SignedHeader: &types.SignedHeader{
Header: trustedHeader,
+16 -30
View File
@@ -8,14 +8,12 @@ import (
"github.com/rs/cors"
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/internal/consensus"
"github.com/tendermint/tendermint/internal/pubsub"
"github.com/tendermint/tendermint/internal/rpc/core"
"github.com/tendermint/tendermint/internal/state"
"github.com/tendermint/tendermint/internal/state/indexer"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/rpc/jsonrpc/server"
"github.com/tendermint/tendermint/types"
)
// Server defines parameters for running an Inspector rpc server.
@@ -33,24 +31,23 @@ type eventBusUnsubscriber interface {
// Routes returns the set of routes used by the Inspector server.
func Routes(cfg config.RPCConfig, s state.Store, bs state.BlockStore, es []indexer.EventSink, logger log.Logger) core.RoutesMap {
env := &core.Environment{
Config: cfg,
EventSinks: es,
StateStore: s,
BlockStore: bs,
ConsensusReactor: waitSyncCheckerImpl{},
Logger: logger,
Config: cfg,
EventSinks: es,
StateStore: s,
BlockStore: bs,
Logger: logger,
}
return core.RoutesMap{
"blockchain": server.NewRPCFunc(env.BlockchainInfo, "minHeight,maxHeight", true),
"consensus_params": server.NewRPCFunc(env.ConsensusParams, "height", true),
"block": server.NewRPCFunc(env.Block, "height", true),
"block_by_hash": server.NewRPCFunc(env.BlockByHash, "hash", true),
"block_results": server.NewRPCFunc(env.BlockResults, "height", true),
"commit": server.NewRPCFunc(env.Commit, "height", true),
"validators": server.NewRPCFunc(env.Validators, "height,page,per_page", true),
"tx": server.NewRPCFunc(env.Tx, "hash,prove", true),
"tx_search": server.NewRPCFunc(env.TxSearch, "query,prove,page,per_page,order_by", false),
"block_search": server.NewRPCFunc(env.BlockSearch, "query,page,per_page,order_by", false),
"blockchain": server.NewRPCFunc(env.BlockchainInfo, "minHeight,maxHeight"),
"consensus_params": server.NewRPCFunc(env.ConsensusParams, "height"),
"block": server.NewRPCFunc(env.Block, "height"),
"block_by_hash": server.NewRPCFunc(env.BlockByHash, "hash"),
"block_results": server.NewRPCFunc(env.BlockResults, "height"),
"commit": server.NewRPCFunc(env.Commit, "height"),
"validators": server.NewRPCFunc(env.Validators, "height,page,per_page"),
"tx": server.NewRPCFunc(env.Tx, "hash,prove"),
"tx_search": server.NewRPCFunc(env.TxSearch, "query,prove,page,per_page,order_by"),
"block_search": server.NewRPCFunc(env.BlockSearch, "query,page,per_page,order_by"),
}
}
@@ -69,10 +66,9 @@ func Handler(rpcConfig *config.RPCConfig, routes core.RoutesMap, logger log.Logg
wmLogger.Error("Failed to unsubscribe addr from events", "addr", remoteAddr, "err", err)
}
}
wm := server.NewWebsocketManager(routes,
wm := server.NewWebsocketManager(logger, routes,
server.OnDisconnect(websocketDisconnectFn),
server.ReadLimit(rpcConfig.MaxBodyBytes))
wm.SetLogger(wmLogger)
mux.HandleFunc("/websocket", wm.WebsocketHandler)
server.RegisterRPCFuncs(mux, routes, logger)
@@ -93,16 +89,6 @@ func addCORSHandler(rpcConfig *config.RPCConfig, h http.Handler) http.Handler {
return h
}
type waitSyncCheckerImpl struct{}
func (waitSyncCheckerImpl) WaitSync() bool {
return false
}
func (waitSyncCheckerImpl) GetPeerState(peerID types.NodeID) (*consensus.PeerState, bool) {
return nil, false
}
// ListenAndServe listens on the address specified in srv.Addr and handles any
// incoming requests over HTTP using the Inspector rpc handler specified on the server.
func (srv *Server) ListenAndServe(ctx context.Context) error {
-40
View File
@@ -1,40 +0,0 @@
package fail
import (
"fmt"
"os"
"strconv"
)
func envSet() int {
callIndexToFailS := os.Getenv("FAIL_TEST_INDEX")
if callIndexToFailS == "" {
return -1
}
var err error
callIndexToFail, err := strconv.Atoi(callIndexToFailS)
if err != nil {
return -1
}
return callIndexToFail
}
// Fail when FAIL_TEST_INDEX == callIndex
var callIndex int // indexes Fail calls
func Fail() {
callIndexToFail := envSet()
if callIndexToFail < 0 {
return
}
if callIndex == callIndexToFail {
fmt.Printf("*** fail-test %d ***\n", callIndex)
os.Exit(1)
}
callIndex++
}
-7
View File
@@ -55,13 +55,6 @@ func (t *ThrottleTimer) Set() {
}
}
func (t *ThrottleTimer) Unset() {
t.mtx.Lock()
defer t.mtx.Unlock()
t.isSet = false
t.timer.Stop()
}
// For ease of .Stop()'ing services before .Start()'ing them,
// we ignore .Stop()'s on nil ThrottleTimers
func (t *ThrottleTimer) Stop() bool {
-1
View File
@@ -281,7 +281,6 @@ func (r *Reactor) processPeerUpdates(ctx context.Context) {
for {
select {
case <-ctx.Done():
r.logger.Debug("stopped listening on peer updates channel; closing...")
return
case peerUpdate := <-r.peerUpdates.Updates():
r.processPeerUpdate(ctx, peerUpdate)
-5
View File
@@ -353,7 +353,6 @@ FOR_LOOP:
channel.updateStats()
}
case <-c.pingTimer.C:
c.logger.Debug("Send Ping")
_n, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPing{}))
if err != nil {
c.logger.Error("Failed to send PacketPing", "err", err)
@@ -370,13 +369,11 @@ FOR_LOOP:
c.flush()
case timeout := <-c.pongTimeoutCh:
if timeout {
c.logger.Debug("Pong timeout")
err = errors.New("pong timeout")
} else {
c.stopPongTimer()
}
case <-c.pong:
c.logger.Debug("Send Pong")
_n, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPong{}))
if err != nil {
c.logger.Error("Failed to send PacketPong", "err", err)
@@ -528,14 +525,12 @@ FOR_LOOP:
case *tmp2p.Packet_PacketPing:
// TODO: prevent abuse, as they cause flush()'s.
// https://github.com/tendermint/tendermint/issues/1190
c.logger.Debug("Receive Ping")
select {
case c.pong <- struct{}{}:
default:
// never block
}
case *tmp2p.Packet_PacketPong:
c.logger.Debug("Receive Pong")
select {
case c.pongTimeoutCh <- false:
default:
-2
View File
@@ -181,7 +181,6 @@ func (r *Reactor) processPexCh(ctx context.Context) {
select {
case <-ctx.Done():
r.logger.Debug("stopped listening on PEX channel; closing...")
return
// outbound requests for new peers
@@ -215,7 +214,6 @@ func (r *Reactor) processPeerUpdates(ctx context.Context) {
for {
select {
case <-ctx.Done():
r.logger.Debug("stopped listening on peer updates channel; closing...")
return
case peerUpdate := <-r.peerUpdates.Updates():
r.processPeerUpdate(peerUpdate)
+1 -12
View File
@@ -487,7 +487,6 @@ func (r *reactorTestSuite) listenFor(
}
func (r *reactorTestSuite) listenForRequest(ctx context.Context, t *testing.T, fromNode, toNode int, waitPeriod time.Duration) {
r.logger.Info("Listening for request", "from", fromNode, "to", toNode)
to, from := r.checkNodePair(t, toNode, fromNode)
conditional := func(msg *p2p.Envelope) bool {
_, ok := msg.Message.(*p2pproto.PexRequest)
@@ -508,7 +507,7 @@ func (r *reactorTestSuite) pingAndlistenForNAddresses(
addresses int,
) {
t.Helper()
r.logger.Info("Listening for addresses", "from", fromNode, "to", toNode)
to, from := r.checkNodePair(t, toNode, fromNode)
conditional := func(msg *p2p.Envelope) bool {
_, ok := msg.Message.(*p2pproto.PexResponse)
@@ -541,11 +540,9 @@ func (r *reactorTestSuite) listenForResponse(
waitPeriod time.Duration,
addresses []p2pproto.PexAddress,
) {
r.logger.Info("Listening for response", "from", fromNode, "to", toNode)
to, from := r.checkNodePair(t, toNode, fromNode)
conditional := func(msg *p2p.Envelope) bool {
_, ok := msg.Message.(*p2pproto.PexResponse)
r.logger.Info("message", msg, "ok", ok)
return ok && msg.From == from
}
assertion := func(t *testing.T, msg *p2p.Envelope) bool {
@@ -658,7 +655,6 @@ func (r *reactorTestSuite) connectN(ctx context.Context, t *testing.T, n int) {
func (r *reactorTestSuite) connectPeers(ctx context.Context, t *testing.T, sourceNode, targetNode int) {
t.Helper()
node1, node2 := r.checkNodePair(t, sourceNode, targetNode)
r.logger.Info("connecting peers", "sourceNode", sourceNode, "targetNode", targetNode)
n1 := r.network.Nodes[node1]
if n1 == nil {
@@ -676,16 +672,12 @@ func (r *reactorTestSuite) connectPeers(ctx context.Context, t *testing.T, sourc
targetSub := n2.PeerManager.Subscribe(ctx)
sourceAddress := n1.NodeAddress
r.logger.Debug("source address", "address", sourceAddress)
targetAddress := n2.NodeAddress
r.logger.Debug("target address", "address", targetAddress)
added, err := n1.PeerManager.Add(targetAddress)
require.NoError(t, err)
if !added {
r.logger.Debug("nodes already know about one another",
"sourceNode", sourceNode, "targetNode", targetNode)
return
}
@@ -695,19 +687,16 @@ func (r *reactorTestSuite) connectPeers(ctx context.Context, t *testing.T, sourc
NodeID: node1,
Status: p2p.PeerStatusUp,
}, peerUpdate)
r.logger.Debug("target connected with source")
case <-time.After(2 * time.Second):
require.Fail(t, "timed out waiting for peer", "%v accepting %v",
targetNode, sourceNode)
}
select {
case peerUpdate := <-sourceSub.Updates():
require.Equal(t, p2p.PeerUpdate{
NodeID: node2,
Status: p2p.PeerStatusUp,
}, peerUpdate)
r.logger.Debug("source connected with target")
case <-time.After(2 * time.Second):
require.Fail(t, "timed out waiting for peer", "%v dialing %v",
sourceNode, targetNode)
-9
View File
@@ -472,8 +472,6 @@ func (r *Router) dialSleep(ctx context.Context) {
// acceptPeers accepts inbound connections from peers on the given transport,
// and spawns goroutines that route messages to/from them.
func (r *Router) acceptPeers(ctx context.Context, transport Transport) {
r.logger.Debug("starting accept routine", "transport", transport)
for {
conn, err := transport.Accept(ctx)
switch err {
@@ -555,8 +553,6 @@ func (r *Router) openConnection(ctx context.Context, conn Connection) {
// dialPeers maintains outbound connections to peers by dialing them.
func (r *Router) dialPeers(ctx context.Context) {
r.logger.Debug("starting dial routine")
addresses := make(chan NodeAddress)
wg := &sync.WaitGroup{}
@@ -587,7 +583,6 @@ LOOP:
address, err := r.peerManager.DialNext(ctx)
switch {
case errors.Is(err, context.Canceled):
r.logger.Debug("stopping dial routine")
break LOOP
case err != nil:
r.logger.Error("failed to find next peer to dial", "err", err)
@@ -917,16 +912,12 @@ func (r *Router) sendPeer(ctx context.Context, peerID types.NodeID, conn Connect
// evictPeers evicts connected peers as requested by the peer manager.
func (r *Router) evictPeers(ctx context.Context) {
r.logger.Debug("starting evict routine")
for {
peerID, err := r.peerManager.EvictNext(ctx)
switch {
case errors.Is(err, context.Canceled):
r.logger.Debug("stopping evict routine")
return
case err != nil:
r.logger.Error("failed to find next peer to evict", "err", err)
return
+1 -1
View File
@@ -21,7 +21,7 @@ func DefaultClientCreator(logger log.Logger, addr, transport, dbDir string) (abc
case "kvstore":
return abciclient.NewLocalCreator(kvstore.NewApplication()), noopCloser{}
case "persistent_kvstore":
app := kvstore.NewPersistentKVStoreApplication(dbDir)
app := kvstore.NewPersistentKVStoreApplication(logger, dbDir)
return abciclient.NewLocalCreator(app), app
case "e2e":
app, err := e2e.NewApplication(e2e.DefaultConfig(dbDir))
+6 -5
View File
@@ -1,23 +1,24 @@
package core
import (
"context"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/internal/proxy"
"github.com/tendermint/tendermint/libs/bytes"
"github.com/tendermint/tendermint/rpc/coretypes"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
)
// ABCIQuery queries the application for some information.
// More: https://docs.tendermint.com/master/rpc/#/ABCI/abci_query
func (env *Environment) ABCIQuery(
ctx *rpctypes.Context,
ctx context.Context,
path string,
data bytes.HexBytes,
height int64,
prove bool,
) (*coretypes.ResultABCIQuery, error) {
resQuery, err := env.ProxyAppQuery.QuerySync(ctx.Context(), abci.RequestQuery{
resQuery, err := env.ProxyAppQuery.QuerySync(ctx, abci.RequestQuery{
Path: path,
Data: data,
Height: height,
@@ -32,8 +33,8 @@ func (env *Environment) ABCIQuery(
// ABCIInfo gets some info about the application.
// More: https://docs.tendermint.com/master/rpc/#/ABCI/abci_info
func (env *Environment) ABCIInfo(ctx *rpctypes.Context) (*coretypes.ResultABCIInfo, error) {
resInfo, err := env.ProxyAppQuery.InfoSync(ctx.Context(), proxy.RequestInfo)
func (env *Environment) ABCIInfo(ctx context.Context) (*coretypes.ResultABCIInfo, error) {
resInfo, err := env.ProxyAppQuery.InfoSync(ctx, proxy.RequestInfo)
if err != nil {
return nil, err
}
+10 -10
View File
@@ -1,6 +1,7 @@
package core
import (
"context"
"fmt"
"sort"
@@ -9,7 +10,6 @@ import (
"github.com/tendermint/tendermint/libs/bytes"
tmmath "github.com/tendermint/tendermint/libs/math"
"github.com/tendermint/tendermint/rpc/coretypes"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
"github.com/tendermint/tendermint/types"
)
@@ -24,7 +24,7 @@ import (
//
// More: https://docs.tendermint.com/master/rpc/#/Info/blockchain
func (env *Environment) BlockchainInfo(
ctx *rpctypes.Context,
ctx context.Context,
minHeight, maxHeight int64) (*coretypes.ResultBlockchainInfo, error) {
const limit int64 = 20
@@ -92,7 +92,7 @@ func filterMinMax(base, height, min, max, limit int64) (int64, int64, error) {
// Block gets block at a given height.
// If no height is provided, it will fetch the latest block.
// More: https://docs.tendermint.com/master/rpc/#/Info/block
func (env *Environment) Block(ctx *rpctypes.Context, heightPtr *int64) (*coretypes.ResultBlock, error) {
func (env *Environment) Block(ctx context.Context, heightPtr *int64) (*coretypes.ResultBlock, error) {
height, err := env.getHeight(env.BlockStore.Height(), heightPtr)
if err != nil {
return nil, err
@@ -109,7 +109,7 @@ func (env *Environment) Block(ctx *rpctypes.Context, heightPtr *int64) (*coretyp
// BlockByHash gets block by hash.
// More: https://docs.tendermint.com/master/rpc/#/Info/block_by_hash
func (env *Environment) BlockByHash(ctx *rpctypes.Context, hash bytes.HexBytes) (*coretypes.ResultBlock, error) {
func (env *Environment) BlockByHash(ctx context.Context, hash bytes.HexBytes) (*coretypes.ResultBlock, error) {
// N.B. The hash parameter is HexBytes so that the reflective parameter
// decoding logic in the HTTP service will correctly translate from JSON.
// See https://github.com/tendermint/tendermint/issues/6802 for context.
@@ -126,7 +126,7 @@ func (env *Environment) BlockByHash(ctx *rpctypes.Context, hash bytes.HexBytes)
// Header gets block header at a given height.
// If no height is provided, it will fetch the latest header.
// More: https://docs.tendermint.com/master/rpc/#/Info/header
func (env *Environment) Header(ctx *rpctypes.Context, heightPtr *int64) (*coretypes.ResultHeader, error) {
func (env *Environment) Header(ctx context.Context, heightPtr *int64) (*coretypes.ResultHeader, error) {
height, err := env.getHeight(env.BlockStore.Height(), heightPtr)
if err != nil {
return nil, err
@@ -142,7 +142,7 @@ func (env *Environment) Header(ctx *rpctypes.Context, heightPtr *int64) (*corety
// HeaderByHash gets header by hash.
// More: https://docs.tendermint.com/master/rpc/#/Info/header_by_hash
func (env *Environment) HeaderByHash(ctx *rpctypes.Context, hash bytes.HexBytes) (*coretypes.ResultHeader, error) {
func (env *Environment) HeaderByHash(ctx context.Context, hash bytes.HexBytes) (*coretypes.ResultHeader, error) {
// N.B. The hash parameter is HexBytes so that the reflective parameter
// decoding logic in the HTTP service will correctly translate from JSON.
// See https://github.com/tendermint/tendermint/issues/6802 for context.
@@ -158,7 +158,7 @@ func (env *Environment) HeaderByHash(ctx *rpctypes.Context, hash bytes.HexBytes)
// Commit gets block commit at a given height.
// If no height is provided, it will fetch the commit for the latest block.
// More: https://docs.tendermint.com/master/rpc/#/Info/commit
func (env *Environment) Commit(ctx *rpctypes.Context, heightPtr *int64) (*coretypes.ResultCommit, error) {
func (env *Environment) Commit(ctx context.Context, heightPtr *int64) (*coretypes.ResultCommit, error) {
height, err := env.getHeight(env.BlockStore.Height(), heightPtr)
if err != nil {
return nil, err
@@ -196,7 +196,7 @@ func (env *Environment) Commit(ctx *rpctypes.Context, heightPtr *int64) (*corety
// Thus response.results.deliver_tx[5] is the results of executing
// getBlock(h).Txs[5]
// More: https://docs.tendermint.com/master/rpc/#/Info/block_results
func (env *Environment) BlockResults(ctx *rpctypes.Context, heightPtr *int64) (*coretypes.ResultBlockResults, error) {
func (env *Environment) BlockResults(ctx context.Context, heightPtr *int64) (*coretypes.ResultBlockResults, error) {
height, err := env.getHeight(env.BlockStore.Height(), heightPtr)
if err != nil {
return nil, err
@@ -226,7 +226,7 @@ func (env *Environment) BlockResults(ctx *rpctypes.Context, heightPtr *int64) (*
// BlockSearch searches for a paginated set of blocks matching BeginBlock and
// EndBlock event search criteria.
func (env *Environment) BlockSearch(
ctx *rpctypes.Context,
ctx context.Context,
query string,
pagePtr, perPagePtr *int,
orderBy string,
@@ -248,7 +248,7 @@ func (env *Environment) BlockSearch(
}
}
results, err := kvsink.SearchBlockEvents(ctx.Context(), q)
results, err := kvsink.SearchBlockEvents(ctx, q)
if err != nil {
return nil, err
}
+3 -2
View File
@@ -1,6 +1,7 @@
package core
import (
"context"
"fmt"
"testing"
@@ -14,7 +15,6 @@ import (
"github.com/tendermint/tendermint/internal/state/mocks"
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
"github.com/tendermint/tendermint/rpc/coretypes"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
)
func TestBlockchainInfo(t *testing.T) {
@@ -108,8 +108,9 @@ func TestBlockResults(t *testing.T) {
}},
}
ctx := context.Background()
for _, tc := range testCases {
res, err := env.BlockResults(&rpctypes.Context{}, &tc.height)
res, err := env.BlockResults(ctx, &tc.height)
if tc.wantErr {
assert.Error(t, err)
} else {
+6 -7
View File
@@ -1,9 +1,10 @@
package core
import (
"context"
tmmath "github.com/tendermint/tendermint/libs/math"
"github.com/tendermint/tendermint/rpc/coretypes"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
)
// Validators gets the validator set at the given block height.
@@ -14,7 +15,7 @@ import (
//
// More: https://docs.tendermint.com/master/rpc/#/Info/validators
func (env *Environment) Validators(
ctx *rpctypes.Context,
ctx context.Context,
heightPtr *int64,
pagePtr, perPagePtr *int) (*coretypes.ResultValidators, error) {
@@ -50,7 +51,7 @@ func (env *Environment) Validators(
// DumpConsensusState dumps consensus state.
// UNSTABLE
// More: https://docs.tendermint.com/master/rpc/#/Info/dump_consensus_state
func (env *Environment) DumpConsensusState(ctx *rpctypes.Context) (*coretypes.ResultDumpConsensusState, error) {
func (env *Environment) DumpConsensusState(ctx context.Context) (*coretypes.ResultDumpConsensusState, error) {
// Get Peer consensus states.
var peerStates []coretypes.PeerStateInfo
@@ -91,7 +92,7 @@ func (env *Environment) DumpConsensusState(ctx *rpctypes.Context) (*coretypes.Re
// ConsensusState returns a concise summary of the consensus state.
// UNSTABLE
// More: https://docs.tendermint.com/master/rpc/#/Info/consensus_state
func (env *Environment) GetConsensusState(ctx *rpctypes.Context) (*coretypes.ResultConsensusState, error) {
func (env *Environment) GetConsensusState(ctx context.Context) (*coretypes.ResultConsensusState, error) {
// Get self round state.
bz, err := env.ConsensusState.GetRoundStateSimpleJSON()
return &coretypes.ResultConsensusState{RoundState: bz}, err
@@ -100,9 +101,7 @@ func (env *Environment) GetConsensusState(ctx *rpctypes.Context) (*coretypes.Res
// ConsensusParams gets the consensus parameters at the given block height.
// If no height is provided, it will fetch the latest consensus params.
// More: https://docs.tendermint.com/master/rpc/#/Info/consensus_params
func (env *Environment) ConsensusParams(
ctx *rpctypes.Context,
heightPtr *int64) (*coretypes.ResultConsensusParams, error) {
func (env *Environment) ConsensusParams(ctx context.Context, heightPtr *int64) (*coretypes.ResultConsensusParams, error) {
// The latest consensus params that we know is the consensus params after the
// last block.
+3 -2
View File
@@ -1,12 +1,13 @@
package core
import (
"context"
"github.com/tendermint/tendermint/rpc/coretypes"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
)
// UnsafeFlushMempool removes all transactions from the mempool.
func (env *Environment) UnsafeFlushMempool(ctx *rpctypes.Context) (*coretypes.ResultUnsafeFlushMempool, error) {
func (env *Environment) UnsafeFlushMempool(ctx context.Context) (*coretypes.ResultUnsafeFlushMempool, error) {
env.Mempool.Flush()
return &coretypes.ResultUnsafeFlushMempool{}, nil
}
+10 -10
View File
@@ -7,6 +7,7 @@ import (
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/internal/blocksync"
"github.com/tendermint/tendermint/internal/consensus"
"github.com/tendermint/tendermint/internal/eventbus"
"github.com/tendermint/tendermint/internal/mempool"
@@ -52,11 +53,6 @@ type transport interface {
NodeInfo() types.NodeInfo
}
type consensusReactor interface {
WaitSync() bool
GetPeerState(peerID types.NodeID) (*consensus.PeerState, bool)
}
type peerManager interface {
Peers() []types.NodeID
Addresses(types.NodeID) []p2p.NodeAddress
@@ -75,7 +71,8 @@ type Environment struct {
BlockStore sm.BlockStore
EvidencePool sm.EvidencePool
ConsensusState consensusState
ConsensusReactor consensusReactor
ConsensusReactor *consensus.Reactor
BlockSyncReactor *blocksync.Reactor
// Legacy p2p stack
P2PTransport transport
@@ -89,7 +86,6 @@ type Environment struct {
EventSinks []indexer.EventSink
EventBus *eventbus.EventBus // thread safe
Mempool mempool.Mempool
BlockSyncReactor consensus.BlockSyncReactor
StateSyncMetricer statesync.Metricer
Logger log.Logger
@@ -199,9 +195,13 @@ func (env *Environment) getHeight(latestHeight int64, heightPtr *int64) (int64,
}
func (env *Environment) latestUncommittedHeight() int64 {
nodeIsSyncing := env.ConsensusReactor.WaitSync()
if nodeIsSyncing {
return env.BlockStore.Height()
if env.ConsensusReactor != nil {
// consensus reactor can be nil in inspect mode.
nodeIsSyncing := env.ConsensusReactor.WaitSync()
if nodeIsSyncing {
return env.BlockStore.Height()
}
}
return env.BlockStore.Height() + 1
}
+13 -12
View File
@@ -23,8 +23,9 @@ const (
// Subscribe for events via WebSocket.
// More: https://docs.tendermint.com/master/rpc/#/Websocket/subscribe
func (env *Environment) Subscribe(ctx *rpctypes.Context, query string) (*coretypes.ResultSubscribe, error) {
addr := ctx.RemoteAddr()
func (env *Environment) Subscribe(ctx context.Context, query string) (*coretypes.ResultSubscribe, error) {
callInfo := rpctypes.GetCallInfo(ctx)
addr := callInfo.RemoteAddr()
if env.EventBus.NumClients() >= env.Config.MaxSubscriptionClients {
return nil, fmt.Errorf("max_subscription_clients %d reached", env.Config.MaxSubscriptionClients)
@@ -41,7 +42,7 @@ func (env *Environment) Subscribe(ctx *rpctypes.Context, query string) (*coretyp
return nil, fmt.Errorf("failed to parse query: %w", err)
}
subCtx, cancel := context.WithTimeout(ctx.Context(), SubscribeTimeout)
subCtx, cancel := context.WithTimeout(ctx, SubscribeTimeout)
defer cancel()
sub, err := env.EventBus.SubscribeWithArgs(subCtx, tmpubsub.SubscribeArgs{
@@ -54,7 +55,7 @@ func (env *Environment) Subscribe(ctx *rpctypes.Context, query string) (*coretyp
}
// Capture the current ID, since it can change in the future.
subscriptionID := ctx.JSONReq.ID
subscriptionID := callInfo.RPCRequest.ID
go func() {
opctx, opcancel := context.WithCancel(context.Background())
defer opcancel()
@@ -67,7 +68,7 @@ func (env *Environment) Subscribe(ctx *rpctypes.Context, query string) (*coretyp
} else if errors.Is(err, tmpubsub.ErrTerminated) {
// The subscription was terminated by the publisher.
resp := rpctypes.RPCServerError(subscriptionID, err)
ok := ctx.WSConn.TryWriteRPCResponse(opctx, resp)
ok := callInfo.WSConn.TryWriteRPCResponse(opctx, resp)
if !ok {
env.Logger.Info("Unable to write response (slow client)",
"to", addr, "subscriptionID", subscriptionID, "err", err)
@@ -82,7 +83,7 @@ func (env *Environment) Subscribe(ctx *rpctypes.Context, query string) (*coretyp
Events: msg.Events(),
})
wctx, cancel := context.WithTimeout(opctx, 10*time.Second)
err = ctx.WSConn.WriteRPCResponse(wctx, resp)
err = callInfo.WSConn.WriteRPCResponse(wctx, resp)
cancel()
if err != nil {
env.Logger.Info("Unable to write response (slow client)",
@@ -96,8 +97,8 @@ func (env *Environment) Subscribe(ctx *rpctypes.Context, query string) (*coretyp
// Unsubscribe from events via WebSocket.
// More: https://docs.tendermint.com/master/rpc/#/Websocket/unsubscribe
func (env *Environment) Unsubscribe(ctx *rpctypes.Context, query string) (*coretypes.ResultUnsubscribe, error) {
args := tmpubsub.UnsubscribeArgs{Subscriber: ctx.RemoteAddr()}
func (env *Environment) Unsubscribe(ctx context.Context, query string) (*coretypes.ResultUnsubscribe, error) {
args := tmpubsub.UnsubscribeArgs{Subscriber: rpctypes.GetCallInfo(ctx).RemoteAddr()}
env.Logger.Info("Unsubscribe from query", "remote", args.Subscriber, "subscription", query)
var err error
@@ -107,7 +108,7 @@ func (env *Environment) Unsubscribe(ctx *rpctypes.Context, query string) (*coret
args.ID = query
}
err = env.EventBus.Unsubscribe(ctx.Context(), args)
err = env.EventBus.Unsubscribe(ctx, args)
if err != nil {
return nil, err
}
@@ -116,10 +117,10 @@ func (env *Environment) Unsubscribe(ctx *rpctypes.Context, query string) (*coret
// UnsubscribeAll from all events via WebSocket.
// More: https://docs.tendermint.com/master/rpc/#/Websocket/unsubscribe_all
func (env *Environment) UnsubscribeAll(ctx *rpctypes.Context) (*coretypes.ResultUnsubscribe, error) {
addr := ctx.RemoteAddr()
func (env *Environment) UnsubscribeAll(ctx context.Context) (*coretypes.ResultUnsubscribe, error) {
addr := rpctypes.GetCallInfo(ctx).RemoteAddr()
env.Logger.Info("Unsubscribe from all", "remote", addr)
err := env.EventBus.UnsubscribeAll(ctx.Context(), addr)
err := env.EventBus.UnsubscribeAll(ctx, addr)
if err != nil {
return nil, err
}
+2 -2
View File
@@ -1,17 +1,17 @@
package core
import (
"context"
"fmt"
"github.com/tendermint/tendermint/rpc/coretypes"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
"github.com/tendermint/tendermint/types"
)
// BroadcastEvidence broadcasts evidence of the misbehavior.
// More: https://docs.tendermint.com/master/rpc/#/Evidence/broadcast_evidence
func (env *Environment) BroadcastEvidence(
ctx *rpctypes.Context,
ctx context.Context,
ev types.Evidence) (*coretypes.ResultBroadcastEvidence, error) {
if ev == nil {
+3 -2
View File
@@ -1,13 +1,14 @@
package core
import (
"context"
"github.com/tendermint/tendermint/rpc/coretypes"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
)
// Health gets node health. Returns empty result (200 OK) on success, no
// response - in case of an error.
// More: https://docs.tendermint.com/master/rpc/#/Info/health
func (env *Environment) Health(ctx *rpctypes.Context) (*coretypes.ResultHealth, error) {
func (env *Environment) Health(ctx context.Context) (*coretypes.ResultHealth, error) {
return &coretypes.ResultHealth{}, nil
}
+13 -13
View File
@@ -1,6 +1,7 @@
package core
import (
"context"
"errors"
"fmt"
"math/rand"
@@ -10,7 +11,6 @@ import (
"github.com/tendermint/tendermint/internal/mempool"
"github.com/tendermint/tendermint/internal/state/indexer"
"github.com/tendermint/tendermint/rpc/coretypes"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
"github.com/tendermint/tendermint/types"
)
@@ -20,8 +20,8 @@ import (
// 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 *rpctypes.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
err := env.Mempool.CheckTx(ctx.Context(), tx, nil, mempool.TxInfo{})
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
}
@@ -32,10 +32,10 @@ func (env *Environment) BroadcastTxAsync(ctx *rpctypes.Context, tx types.Tx) (*c
// 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 *rpctypes.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
func (env *Environment) BroadcastTxSync(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
resCh := make(chan *abci.Response, 1)
err := env.Mempool.CheckTx(
ctx.Context(),
ctx,
tx,
func(res *abci.Response) { resCh <- res },
mempool.TxInfo{},
@@ -59,10 +59,10 @@ func (env *Environment) BroadcastTxSync(ctx *rpctypes.Context, tx types.Tx) (*co
// 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 *rpctypes.Context, tx types.Tx) (*coretypes.ResultBroadcastTxCommit, error) {
func (env *Environment) BroadcastTxCommit(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTxCommit, error) {
resCh := make(chan *abci.Response, 1)
err := env.Mempool.CheckTx(
ctx.Context(),
ctx,
tx,
func(res *abci.Response) { resCh <- res },
mempool.TxInfo{},
@@ -89,7 +89,7 @@ func (env *Environment) BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (*
for {
count++
select {
case <-ctx.Context().Done():
case <-ctx.Done():
env.Logger.Error("error on broadcastTxCommit",
"duration", time.Since(startAt),
"err", err)
@@ -120,7 +120,7 @@ func (env *Environment) BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (*
// UnconfirmedTxs gets unconfirmed transactions (maximum ?limit entries)
// including their number.
// More: https://docs.tendermint.com/master/rpc/#/Info/unconfirmed_txs
func (env *Environment) UnconfirmedTxs(ctx *rpctypes.Context, limitPtr *int) (*coretypes.ResultUnconfirmedTxs, error) {
func (env *Environment) UnconfirmedTxs(ctx context.Context, limitPtr *int) (*coretypes.ResultUnconfirmedTxs, error) {
// reuse per_page validator
limit := env.validatePerPage(limitPtr)
@@ -134,7 +134,7 @@ func (env *Environment) UnconfirmedTxs(ctx *rpctypes.Context, limitPtr *int) (*c
// NumUnconfirmedTxs gets number of unconfirmed transactions.
// More: https://docs.tendermint.com/master/rpc/#/Info/num_unconfirmed_txs
func (env *Environment) NumUnconfirmedTxs(ctx *rpctypes.Context) (*coretypes.ResultUnconfirmedTxs, error) {
func (env *Environment) NumUnconfirmedTxs(ctx context.Context) (*coretypes.ResultUnconfirmedTxs, error) {
return &coretypes.ResultUnconfirmedTxs{
Count: env.Mempool.Size(),
Total: env.Mempool.Size(),
@@ -144,14 +144,14 @@ func (env *Environment) NumUnconfirmedTxs(ctx *rpctypes.Context) (*coretypes.Res
// 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 *rpctypes.Context, tx types.Tx) (*coretypes.ResultCheckTx, error) {
res, err := env.ProxyAppMempool.CheckTxSync(ctx.Context(), abci.RequestCheckTx{Tx: tx})
func (env *Environment) CheckTx(ctx context.Context, tx types.Tx) (*coretypes.ResultCheckTx, error) {
res, err := env.ProxyAppMempool.CheckTxSync(ctx, abci.RequestCheckTx{Tx: tx})
if err != nil {
return nil, err
}
return &coretypes.ResultCheckTx{ResponseCheckTx: *res}, nil
}
func (env *Environment) RemoveTx(ctx *rpctypes.Context, txkey types.TxKey) error {
func (env *Environment) RemoveTx(ctx context.Context, txkey types.TxKey) error {
return env.Mempool.RemoveTxByKey(txkey)
}
+4 -4
View File
@@ -1,16 +1,16 @@
package core
import (
"context"
"errors"
"fmt"
"github.com/tendermint/tendermint/rpc/coretypes"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
)
// NetInfo returns network info.
// More: https://docs.tendermint.com/master/rpc/#/Info/net_info
func (env *Environment) NetInfo(ctx *rpctypes.Context) (*coretypes.ResultNetInfo, error) {
func (env *Environment) NetInfo(ctx context.Context) (*coretypes.ResultNetInfo, error) {
peerList := env.PeerManager.Peers()
peers := make([]coretypes.Peer, 0, len(peerList))
@@ -36,7 +36,7 @@ func (env *Environment) NetInfo(ctx *rpctypes.Context) (*coretypes.ResultNetInfo
// Genesis returns genesis file.
// More: https://docs.tendermint.com/master/rpc/#/Info/genesis
func (env *Environment) Genesis(ctx *rpctypes.Context) (*coretypes.ResultGenesis, error) {
func (env *Environment) Genesis(ctx context.Context) (*coretypes.ResultGenesis, error) {
if len(env.genChunks) > 1 {
return nil, errors.New("genesis response is large, please use the genesis_chunked API instead")
}
@@ -44,7 +44,7 @@ func (env *Environment) Genesis(ctx *rpctypes.Context) (*coretypes.ResultGenesis
return &coretypes.ResultGenesis{Genesis: env.GenDoc}, nil
}
func (env *Environment) GenesisChunked(ctx *rpctypes.Context, chunk uint) (*coretypes.ResultGenesisChunk, error) {
func (env *Environment) GenesisChunked(ctx context.Context, chunk uint) (*coretypes.ResultGenesisChunk, error) {
if env.genChunks == nil {
return nil, fmt.Errorf("service configuration error, genesis chunks are not initialized")
}
+30 -30
View File
@@ -17,46 +17,46 @@ func (env *Environment) GetRoutes() RoutesMap {
"unsubscribe_all": rpc.NewWSRPCFunc(env.UnsubscribeAll, ""),
// info API
"health": rpc.NewRPCFunc(env.Health, "", false),
"status": rpc.NewRPCFunc(env.Status, "", false),
"net_info": rpc.NewRPCFunc(env.NetInfo, "", false),
"blockchain": rpc.NewRPCFunc(env.BlockchainInfo, "minHeight,maxHeight", true),
"genesis": rpc.NewRPCFunc(env.Genesis, "", true),
"genesis_chunked": rpc.NewRPCFunc(env.GenesisChunked, "chunk", true),
"header": rpc.NewRPCFunc(env.Header, "height", true),
"header_by_hash": rpc.NewRPCFunc(env.HeaderByHash, "hash", true),
"block": rpc.NewRPCFunc(env.Block, "height", true),
"block_by_hash": rpc.NewRPCFunc(env.BlockByHash, "hash", true),
"block_results": rpc.NewRPCFunc(env.BlockResults, "height", true),
"commit": rpc.NewRPCFunc(env.Commit, "height", true),
"check_tx": rpc.NewRPCFunc(env.CheckTx, "tx", true),
"remove_tx": rpc.NewRPCFunc(env.RemoveTx, "txkey", false),
"tx": rpc.NewRPCFunc(env.Tx, "hash,prove", true),
"tx_search": rpc.NewRPCFunc(env.TxSearch, "query,prove,page,per_page,order_by", false),
"block_search": rpc.NewRPCFunc(env.BlockSearch, "query,page,per_page,order_by", false),
"validators": rpc.NewRPCFunc(env.Validators, "height,page,per_page", true),
"dump_consensus_state": rpc.NewRPCFunc(env.DumpConsensusState, "", false),
"consensus_state": rpc.NewRPCFunc(env.GetConsensusState, "", false),
"consensus_params": rpc.NewRPCFunc(env.ConsensusParams, "height", true),
"unconfirmed_txs": rpc.NewRPCFunc(env.UnconfirmedTxs, "limit", false),
"num_unconfirmed_txs": rpc.NewRPCFunc(env.NumUnconfirmedTxs, "", false),
"health": rpc.NewRPCFunc(env.Health, ""),
"status": rpc.NewRPCFunc(env.Status, ""),
"net_info": rpc.NewRPCFunc(env.NetInfo, ""),
"blockchain": rpc.NewRPCFunc(env.BlockchainInfo, "minHeight,maxHeight"),
"genesis": rpc.NewRPCFunc(env.Genesis, ""),
"genesis_chunked": rpc.NewRPCFunc(env.GenesisChunked, "chunk"),
"header": rpc.NewRPCFunc(env.Header, "height"),
"header_by_hash": rpc.NewRPCFunc(env.HeaderByHash, "hash"),
"block": rpc.NewRPCFunc(env.Block, "height"),
"block_by_hash": rpc.NewRPCFunc(env.BlockByHash, "hash"),
"block_results": rpc.NewRPCFunc(env.BlockResults, "height"),
"commit": rpc.NewRPCFunc(env.Commit, "height"),
"check_tx": rpc.NewRPCFunc(env.CheckTx, "tx"),
"remove_tx": rpc.NewRPCFunc(env.RemoveTx, "txkey"),
"tx": rpc.NewRPCFunc(env.Tx, "hash,prove"),
"tx_search": rpc.NewRPCFunc(env.TxSearch, "query,prove,page,per_page,order_by"),
"block_search": rpc.NewRPCFunc(env.BlockSearch, "query,page,per_page,order_by"),
"validators": rpc.NewRPCFunc(env.Validators, "height,page,per_page"),
"dump_consensus_state": rpc.NewRPCFunc(env.DumpConsensusState, ""),
"consensus_state": rpc.NewRPCFunc(env.GetConsensusState, ""),
"consensus_params": rpc.NewRPCFunc(env.ConsensusParams, "height"),
"unconfirmed_txs": rpc.NewRPCFunc(env.UnconfirmedTxs, "limit"),
"num_unconfirmed_txs": rpc.NewRPCFunc(env.NumUnconfirmedTxs, ""),
// tx broadcast API
"broadcast_tx_commit": rpc.NewRPCFunc(env.BroadcastTxCommit, "tx", false),
"broadcast_tx_sync": rpc.NewRPCFunc(env.BroadcastTxSync, "tx", false),
"broadcast_tx_async": rpc.NewRPCFunc(env.BroadcastTxAsync, "tx", false),
"broadcast_tx_commit": rpc.NewRPCFunc(env.BroadcastTxCommit, "tx"),
"broadcast_tx_sync": rpc.NewRPCFunc(env.BroadcastTxSync, "tx"),
"broadcast_tx_async": rpc.NewRPCFunc(env.BroadcastTxAsync, "tx"),
// abci API
"abci_query": rpc.NewRPCFunc(env.ABCIQuery, "path,data,height,prove", false),
"abci_info": rpc.NewRPCFunc(env.ABCIInfo, "", true),
"abci_query": rpc.NewRPCFunc(env.ABCIQuery, "path,data,height,prove"),
"abci_info": rpc.NewRPCFunc(env.ABCIInfo, ""),
// evidence API
"broadcast_evidence": rpc.NewRPCFunc(env.BroadcastEvidence, "evidence", false),
"broadcast_evidence": rpc.NewRPCFunc(env.BroadcastEvidence, "evidence"),
}
}
// AddUnsafeRoutes adds unsafe routes.
func (env *Environment) AddUnsafe(routes RoutesMap) {
// control API
routes["unsafe_flush_mempool"] = rpc.NewRPCFunc(env.UnsafeFlushMempool, "", false)
routes["unsafe_flush_mempool"] = rpc.NewRPCFunc(env.UnsafeFlushMempool, "")
}
+2 -2
View File
@@ -2,18 +2,18 @@ package core
import (
"bytes"
"context"
"time"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
"github.com/tendermint/tendermint/rpc/coretypes"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
"github.com/tendermint/tendermint/types"
)
// Status returns Tendermint status including node info, pubkey, latest block
// hash, app hash, block height, current max peer block height, and time.
// More: https://docs.tendermint.com/master/rpc/#/Info/status
func (env *Environment) Status(ctx *rpctypes.Context) (*coretypes.ResultStatus, error) {
func (env *Environment) Status(ctx context.Context) (*coretypes.ResultStatus, error) {
var (
earliestBlockHeight int64
earliestBlockHash tmbytes.HexBytes
+4 -4
View File
@@ -1,6 +1,7 @@
package core
import (
"context"
"errors"
"fmt"
"sort"
@@ -10,7 +11,6 @@ import (
"github.com/tendermint/tendermint/libs/bytes"
tmmath "github.com/tendermint/tendermint/libs/math"
"github.com/tendermint/tendermint/rpc/coretypes"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
"github.com/tendermint/tendermint/types"
)
@@ -18,7 +18,7 @@ import (
// transaction is in the mempool, invalidated, or was not sent in the first
// place.
// More: https://docs.tendermint.com/master/rpc/#/Info/tx
func (env *Environment) Tx(ctx *rpctypes.Context, hash bytes.HexBytes, prove bool) (*coretypes.ResultTx, error) {
func (env *Environment) Tx(ctx context.Context, hash bytes.HexBytes, prove bool) (*coretypes.ResultTx, error) {
// if index is disabled, return error
// N.B. The hash parameter is HexBytes so that the reflective parameter
@@ -63,7 +63,7 @@ func (env *Environment) Tx(ctx *rpctypes.Context, hash bytes.HexBytes, prove boo
// list of transactions (maximum ?per_page entries) and the total count.
// More: https://docs.tendermint.com/master/rpc/#/Info/tx_search
func (env *Environment) TxSearch(
ctx *rpctypes.Context,
ctx context.Context,
query string,
prove bool,
pagePtr, perPagePtr *int,
@@ -83,7 +83,7 @@ func (env *Environment) TxSearch(
for _, sink := range env.EventSinks {
if sink.Type() == indexer.KV {
results, err := sink.SearchTxEvents(ctx.Context(), q)
results, err := sink.SearchTxEvents(ctx, q)
if err != nil {
return nil, err
}
-9
View File
@@ -9,7 +9,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/encoding"
"github.com/tendermint/tendermint/internal/eventbus"
"github.com/tendermint/tendermint/internal/libs/fail"
"github.com/tendermint/tendermint/internal/mempool"
"github.com/tendermint/tendermint/internal/proxy"
"github.com/tendermint/tendermint/libs/log"
@@ -171,15 +170,11 @@ func (blockExec *BlockExecutor) ApplyBlock(
return state, ErrProxyAppConn(err)
}
fail.Fail() // XXX
// Save the results before we commit.
if err := blockExec.store.SaveABCIResponses(block.Height, abciResponses); err != nil {
return state, err
}
fail.Fail() // XXX
// validate the validator updates and convert to tendermint types
abciValUpdates := abciResponses.EndBlock.ValidatorUpdates
err = validateValidatorUpdates(abciValUpdates, state.ConsensusParams.Validator)
@@ -210,16 +205,12 @@ func (blockExec *BlockExecutor) ApplyBlock(
// Update evpool with the latest state.
blockExec.evpool.Update(state, block.Evidence.Evidence)
fail.Fail() // XXX
// Update the app hash and save the state.
state.AppHash = appHash
if err := blockExec.store.Save(state); err != nil {
return state, err
}
fail.Fail() // XXX
// Prune old heights, if requested by ABCI app.
if retainHeight > 0 {
pruned, err := blockExec.pruneBlocks(retainHeight)
+32 -29
View File
@@ -40,6 +40,7 @@ func newTestApp() proxy.AppConns {
func makeAndCommitGoodBlock(
ctx context.Context,
t *testing.T,
state sm.State,
height int64,
lastCommit *types.Commit,
@@ -47,64 +48,59 @@ func makeAndCommitGoodBlock(
blockExec *sm.BlockExecutor,
privVals map[string]types.PrivValidator,
evidence []types.Evidence,
) (sm.State, types.BlockID, *types.Commit, error) {
) (sm.State, types.BlockID, *types.Commit) {
t.Helper()
// A good block passes
state, blockID, err := makeAndApplyGoodBlock(ctx, state, height, lastCommit, proposerAddr, blockExec, evidence)
if err != nil {
return state, types.BlockID{}, nil, err
}
state, blockID := makeAndApplyGoodBlock(ctx, t, state, height, lastCommit, proposerAddr, blockExec, evidence)
// Simulate a lastCommit for this block from all validators for the next height
commit, err := makeValidCommit(ctx, height, blockID, state.Validators, privVals)
if err != nil {
return state, types.BlockID{}, nil, err
}
return state, blockID, commit, nil
commit := makeValidCommit(ctx, t, height, blockID, state.Validators, privVals)
return state, blockID, commit
}
func makeAndApplyGoodBlock(
ctx context.Context,
t *testing.T,
state sm.State,
height int64,
lastCommit *types.Commit,
proposerAddr []byte,
blockExec *sm.BlockExecutor,
evidence []types.Evidence,
) (sm.State, types.BlockID, error) {
) (sm.State, types.BlockID) {
t.Helper()
block, _, err := state.MakeBlock(height, factory.MakeTenTxs(height), lastCommit, evidence, proposerAddr)
if err != nil {
return state, types.BlockID{}, err
}
require.NoError(t, err)
if err := blockExec.ValidateBlock(state, block); err != nil {
return state, types.BlockID{}, err
}
require.NoError(t, blockExec.ValidateBlock(state, block))
blockID := types.BlockID{Hash: block.Hash(),
PartSetHeader: types.PartSetHeader{Total: 3, Hash: tmrand.Bytes(32)}}
state, err = blockExec.ApplyBlock(ctx, state, blockID, block)
if err != nil {
return state, types.BlockID{}, err
}
return state, blockID, nil
require.NoError(t, err)
return state, blockID
}
func makeValidCommit(
ctx context.Context,
t *testing.T,
height int64,
blockID types.BlockID,
vals *types.ValidatorSet,
privVals map[string]types.PrivValidator,
) (*types.Commit, error) {
) *types.Commit {
t.Helper()
sigs := make([]types.CommitSig, 0)
for i := 0; i < vals.Size(); i++ {
_, val := vals.GetByIndex(int32(i))
vote, err := factory.MakeVote(ctx, privVals[val.Address.String()], chainID, int32(i), height, 0, 2, blockID, time.Now())
if err != nil {
return nil, err
}
require.NoError(t, err)
sigs = append(sigs, vote.CommitSig())
}
return types.NewCommit(height, 0, blockID, sigs), nil
return types.NewCommit(height, 0, blockID, sigs)
}
func makeState(t *testing.T, nVals, height int) (sm.State, dbm.DB, map[string]types.PrivValidator) {
@@ -263,9 +259,16 @@ func makeRandomStateFromValidatorSet(
}
}
func makeRandomStateFromConsensusParams(ctx context.Context, consensusParams *types.ConsensusParams,
height, lastHeightConsensusParamsChanged int64) sm.State {
val, _ := factory.RandValidator(ctx, true, 10)
func makeRandomStateFromConsensusParams(
ctx context.Context,
t *testing.T,
consensusParams *types.ConsensusParams,
height,
lastHeightConsensusParamsChanged int64,
) sm.State {
t.Helper()
val, _, err := factory.RandValidator(ctx, true, 10)
require.NoError(t, err)
valSet := types.NewValidatorSet([]*types.Validator{val})
return sm.State{
LastBlockHeight: height - 1,
+1 -1
View File
@@ -113,7 +113,7 @@ func TestRollbackDifferentStateHeight(t *testing.T) {
func setupStateStore(ctx context.Context, t *testing.T, height int64) state.Store {
stateStore := state.NewStore(dbm.NewMemDB())
valSet, _ := factory.RandValidatorSet(ctx, 5, 10)
valSet, _ := factory.RandValidatorSet(ctx, t, 5, 10)
params := types.DefaultConsensusParams()
params.Version.AppVersion = 10
+17 -14
View File
@@ -32,13 +32,15 @@ func TestStoreBootstrap(t *testing.T) {
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB)
val, _ := factory.RandValidator(ctx, true, 10)
val2, _ := factory.RandValidator(ctx, true, 10)
val3, _ := factory.RandValidator(ctx, true, 10)
val, _, err := factory.RandValidator(ctx, true, 10)
require.NoError(t, err)
val2, _, err := factory.RandValidator(ctx, true, 10)
require.NoError(t, err)
val3, _, err := factory.RandValidator(ctx, true, 10)
require.NoError(t, err)
vals := types.NewValidatorSet([]*types.Validator{val, val2, val3})
bootstrapState := makeRandomStateFromValidatorSet(vals, 100, 100)
err := stateStore.Bootstrap(bootstrapState)
require.NoError(t, err)
require.NoError(t, stateStore.Bootstrap(bootstrapState))
// bootstrap should also save the previous validator
_, err = stateStore.LoadValidators(99)
@@ -61,17 +63,18 @@ func TestStoreLoadValidators(t *testing.T) {
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB)
val, _ := factory.RandValidator(ctx, true, 10)
val2, _ := factory.RandValidator(ctx, true, 10)
val3, _ := factory.RandValidator(ctx, true, 10)
val, _, err := factory.RandValidator(ctx, true, 10)
require.NoError(t, err)
val2, _, err := factory.RandValidator(ctx, true, 10)
require.NoError(t, err)
val3, _, err := factory.RandValidator(ctx, true, 10)
require.NoError(t, err)
vals := types.NewValidatorSet([]*types.Validator{val, val2, val3})
// 1) LoadValidators loads validators using a height where they were last changed
// Note that only the next validators at height h + 1 are saved
err := stateStore.Save(makeRandomStateFromValidatorSet(vals, 1, 1))
require.NoError(t, err)
err = stateStore.Save(makeRandomStateFromValidatorSet(vals.CopyIncrementProposerPriority(1), 2, 1))
require.NoError(t, err)
require.NoError(t, stateStore.Save(makeRandomStateFromValidatorSet(vals, 1, 1)))
require.NoError(t, stateStore.Save(makeRandomStateFromValidatorSet(vals.CopyIncrementProposerPriority(1), 2, 1)))
loadedVals, err := stateStore.LoadValidators(3)
require.NoError(t, err)
require.Equal(t, vals.CopyIncrementProposerPriority(3), loadedVals)
@@ -153,7 +156,7 @@ func TestStoreLoadConsensusParams(t *testing.T) {
stateDB := dbm.NewMemDB()
stateStore := sm.NewStore(stateDB)
err := stateStore.Save(makeRandomStateFromConsensusParams(ctx, types.DefaultConsensusParams(), 1, 1))
err := stateStore.Save(makeRandomStateFromConsensusParams(ctx, t, types.DefaultConsensusParams(), 1, 1))
require.NoError(t, err)
params, err := stateStore.LoadConsensusParams(1)
require.NoError(t, err)
@@ -163,7 +166,7 @@ func TestStoreLoadConsensusParams(t *testing.T) {
// it should save a pointer to the params at height 1
differentParams := types.DefaultConsensusParams()
differentParams.Block.MaxBytes = 20000
err = stateStore.Save(makeRandomStateFromConsensusParams(ctx, differentParams, 10, 1))
err = stateStore.Save(makeRandomStateFromConsensusParams(ctx, t, differentParams, 10, 1))
require.NoError(t, err)
res, err := stateStore.LoadConsensusParams(10)
require.NoError(t, err)
+17 -9
View File
@@ -2,14 +2,18 @@ package factory
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/require"
sm "github.com/tendermint/tendermint/internal/state"
"github.com/tendermint/tendermint/internal/test/factory"
"github.com/tendermint/tendermint/types"
)
func MakeBlocks(ctx context.Context, n int, state *sm.State, privVal types.PrivValidator) ([]*types.Block, error) {
func MakeBlocks(ctx context.Context, t *testing.T, n int, state *sm.State, privVal types.PrivValidator) []*types.Block {
t.Helper()
blocks := make([]*types.Block, n)
var (
@@ -21,10 +25,7 @@ func MakeBlocks(ctx context.Context, n int, state *sm.State, privVal types.PrivV
for i := 0; i < n; i++ {
height := int64(i + 1)
block, parts, err := makeBlockAndPartSet(ctx, *state, prevBlock, prevBlockMeta, privVal, height)
if err != nil {
return nil, err
}
block, parts := makeBlockAndPartSet(ctx, t, *state, prevBlock, prevBlockMeta, privVal, height)
blocks[i] = block
@@ -37,7 +38,7 @@ func MakeBlocks(ctx context.Context, n int, state *sm.State, privVal types.PrivV
state.LastBlockHeight = height
}
return blocks, nil
return blocks
}
func MakeBlock(state sm.State, height int64, c *types.Commit) (*types.Block, error) {
@@ -57,24 +58,31 @@ func MakeBlock(state sm.State, height int64, c *types.Commit) (*types.Block, err
func makeBlockAndPartSet(
ctx context.Context,
t *testing.T,
state sm.State,
lastBlock *types.Block,
lastBlockMeta *types.BlockMeta,
privVal types.PrivValidator,
height int64,
) (*types.Block, *types.PartSet, error) {
) (*types.Block, *types.PartSet) {
t.Helper()
lastCommit := types.NewCommit(height-1, 0, types.BlockID{}, nil)
if height > 1 {
vote, _ := factory.MakeVote(
vote, err := factory.MakeVote(
ctx,
privVal,
lastBlock.Header.ChainID,
1, lastBlock.Header.Height, 0, 2,
lastBlockMeta.BlockID,
time.Now())
require.NoError(t, err)
lastCommit = types.NewCommit(vote.Height, vote.Round,
lastBlockMeta.BlockID, []types.CommitSig{vote.CommitSig()})
}
return state.MakeBlock(height, []types.Tx{}, lastCommit, nil, state.Validators.GetProposer().Address)
block, partSet, err := state.MakeBlock(height, []types.Tx{}, lastCommit, nil, state.Validators.GetProposer().Address)
require.NoError(t, err)
return block, partSet
}
+8 -12
View File
@@ -103,10 +103,8 @@ func TestValidateBlockHeader(t *testing.T) {
/*
A good block passes
*/
var err error
state, _, lastCommit, err = makeAndCommitGoodBlock(ctx,
state, _, lastCommit = makeAndCommitGoodBlock(ctx, t,
state, height, lastCommit, state.Validators.GetProposer().Address, blockExec, privVals, nil)
require.NoError(t, err, "height %d", height)
}
nextHeight := validationTestsStopHeight
@@ -158,7 +156,7 @@ func TestValidateBlockCommit(t *testing.T) {
state.LastBlockID,
time.Now(),
)
require.NoError(t, err, "height %d", height)
require.NoError(t, err)
wrongHeightCommit := types.NewCommit(
wrongHeightVote.Height,
wrongHeightVote.Round,
@@ -188,10 +186,10 @@ func TestValidateBlockCommit(t *testing.T) {
/*
A good block passes
*/
var err error
var blockID types.BlockID
state, blockID, lastCommit, err = makeAndCommitGoodBlock(
state, blockID, lastCommit = makeAndCommitGoodBlock(
ctx,
t,
state,
height,
lastCommit,
@@ -200,7 +198,6 @@ func TestValidateBlockCommit(t *testing.T) {
privVals,
nil,
)
require.NoError(t, err, "height %d", height)
/*
wrongSigsCommit is fine except for the extra bad precommit
@@ -216,8 +213,7 @@ func TestValidateBlockCommit(t *testing.T) {
blockID,
time.Now(),
)
require.NoError(t, err, "height %d", height)
require.NoError(t, err)
bpvPubKey, err := badPrivVal.GetPubKey(ctx)
require.NoError(t, err)
@@ -319,9 +315,9 @@ func TestValidateBlockEvidence(t *testing.T) {
evidence = append(evidence, newEv)
}
var err error
state, _, lastCommit, err = makeAndCommitGoodBlock(
state, _, lastCommit = makeAndCommitGoodBlock(
ctx,
t,
state,
height,
lastCommit,
@@ -330,6 +326,6 @@ func TestValidateBlockEvidence(t *testing.T) {
privVals,
evidence,
)
require.NoError(t, err, "height %d", height)
}
}
+1 -1
View File
@@ -294,7 +294,7 @@ loop:
func mockLBResp(ctx context.Context, t *testing.T, peer types.NodeID, height int64, time time.Time) lightBlockResponse {
t.Helper()
vals, pv := factory.RandValidatorSet(ctx, 3, 10)
vals, pv := factory.RandValidatorSet(ctx, t, 3, 10)
_, _, lb := mockLB(ctx, t, height, time, factory.MakeBlockID(), vals, pv)
return lightBlockResponse{
block: lb,
+2 -2
View File
@@ -76,7 +76,7 @@ func TestDispatcherReturnsNoBlock(t *testing.T) {
d := NewDispatcher(ch)
peer := factory.NodeID("a")
peer := factory.NodeID(t, "a")
go func() {
<-chans.Out
@@ -99,7 +99,7 @@ func TestDispatcherTimeOutWaitingOnLightBlock(t *testing.T) {
_, ch := testChannel(100)
d := NewDispatcher(ch)
peer := factory.NodeID("a")
peer := factory.NodeID(t, "a")
ctx, cancelFunc := context.WithTimeout(ctx, 10*time.Millisecond)
defer cancelFunc()
+12 -1
View File
@@ -13,6 +13,7 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/internal/eventbus"
"github.com/tendermint/tendermint/internal/p2p"
"github.com/tendermint/tendermint/internal/proxy"
sm "github.com/tendermint/tendermint/internal/state"
@@ -156,6 +157,7 @@ type Reactor struct {
providers map[types.NodeID]*BlockProvider
stateProvider StateProvider
eventBus *eventbus.EventBus
metrics *Metrics
backfillBlockTotal int64
backfilledBlocks int64
@@ -179,6 +181,7 @@ func NewReactor(
blockStore *store.BlockStore,
tempDir string,
ssMetrics *Metrics,
eventBus *eventbus.EventBus,
) (*Reactor, error) {
chDesc := getChannelDescriptors()
@@ -219,6 +222,7 @@ func NewReactor(
dispatcher: NewDispatcher(blockCh),
providers: make(map[types.NodeID]*BlockProvider),
metrics: ssMetrics,
eventBus: eventBus,
}
r.BaseService = *service.NewBaseService(logger, "StateSync", r)
@@ -248,6 +252,14 @@ func (r *Reactor) OnStop() {
r.dispatcher.Close()
}
func (r *Reactor) PublishStatus(ctx context.Context, event types.EventDataStateSyncStatus) error {
if r.eventBus == nil {
return errors.New("event system is not configured")
}
return r.eventBus.PublishEventStateSyncStatus(ctx, event)
}
// Sync runs a state sync, fetching snapshots and providing chunks to the
// application. At the close of the operation, Sync will bootstrap the state
// store and persist the commit at that height so that either consensus or
@@ -887,7 +899,6 @@ func (r *Reactor) processPeerUpdates(ctx context.Context) {
for {
select {
case <-ctx.Done():
r.logger.Debug("stopped listening on peer updates channel; closing...")
return
case peerUpdate := <-r.peerUpdates.Updates():
r.processPeerUpdate(ctx, peerUpdate)
+21 -15
View File
@@ -161,13 +161,15 @@ func setup(
}
}
logger := log.NewTestingLogger(t)
var err error
rts.reactor, err = NewReactor(
ctx,
factory.DefaultTestChainID,
1,
*cfg,
log.TestingLogger(),
logger.With("component", "reactor"),
conn,
connQuery,
chCreator,
@@ -176,12 +178,13 @@ func setup(
rts.blockStore,
"",
m,
nil, // eventbus can be nil
)
require.NoError(t, err)
rts.syncer = newSyncer(
*cfg,
log.NewNopLogger(),
logger.With("component", "syncer"),
conn,
connQuery,
stateProvider,
@@ -191,13 +194,14 @@ func setup(
rts.reactor.metrics,
)
ctx, cancel := context.WithCancel(ctx)
require.NoError(t, rts.reactor.Start(ctx))
require.True(t, rts.reactor.IsRunning())
t.Cleanup(func() {
rts.reactor.Wait()
require.False(t, rts.reactor.IsRunning())
})
t.Cleanup(cancel)
t.Cleanup(rts.reactor.Wait)
t.Cleanup(leaktest.Check(t))
return rts
}
@@ -233,7 +237,7 @@ func TestReactor_Sync(t *testing.T) {
defer close(closeCh)
go handleLightBlockRequests(ctx, t, chain, rts.blockOutCh,
rts.blockInCh, closeCh, 0)
go graduallyAddPeers(rts.peerUpdateCh, closeCh, 1*time.Second)
go graduallyAddPeers(t, rts.peerUpdateCh, closeCh, 1*time.Second)
go handleSnapshotRequests(t, rts.snapshotOutCh, rts.snapshotInCh, closeCh, []snapshot{
{
Height: uint64(snapshotHeight),
@@ -434,10 +438,11 @@ func TestReactor_LightBlockResponse(t *testing.T) {
rts := setup(ctx, t, nil, nil, nil, 2)
var height int64 = 10
h := factory.MakeRandomHeader()
// generates a random header
h := factory.MakeHeader(t, &types.Header{})
h.Height = height
blockID := factory.MakeBlockIDWithHash(h.Hash())
vals, pv := factory.RandValidatorSet(ctx, 1, 10)
vals, pv := factory.RandValidatorSet(ctx, t, 1, 10)
vote, err := factory.MakeVote(ctx, pv[0], h.ChainID, 0, h.Height, 0, 2,
blockID, factory.DefaultTestTime)
require.NoError(t, err)
@@ -728,7 +733,7 @@ func handleLightBlockRequests(
} else {
switch errorCount % 3 {
case 0: // send a different block
vals, pv := factory.RandValidatorSet(ctx, 3, 10)
vals, pv := factory.RandValidatorSet(ctx, t, 3, 10)
_, _, lb := mockLB(ctx, t, int64(msg.Height), factory.DefaultTestTime, factory.MakeBlockID(), vals, pv)
differntLB, err := lb.ToProto()
require.NoError(t, err)
@@ -797,7 +802,7 @@ func buildLightBlockChain(ctx context.Context, t *testing.T, fromHeight, toHeigh
chain := make(map[int64]*types.LightBlock, toHeight-fromHeight)
lastBlockID := factory.MakeBlockID()
blockTime := startTime.Add(time.Duration(fromHeight-toHeight) * time.Minute)
vals, pv := factory.RandValidatorSet(ctx, 3, 10)
vals, pv := factory.RandValidatorSet(ctx, t, 3, 10)
for height := fromHeight; height < toHeight; height++ {
vals, pv, chain[height] = mockLB(ctx, t, height, blockTime, lastBlockID, vals, pv)
lastBlockID = factory.MakeBlockIDWithHash(chain[height].Header.Hash())
@@ -810,14 +815,14 @@ func mockLB(ctx context.Context, t *testing.T, height int64, time time.Time, las
currentVals *types.ValidatorSet, currentPrivVals []types.PrivValidator,
) (*types.ValidatorSet, []types.PrivValidator, *types.LightBlock) {
t.Helper()
header, err := factory.MakeHeader(&types.Header{
header := factory.MakeHeader(t, &types.Header{
Height: height,
LastBlockID: lastBlockID,
Time: time,
})
header.Version.App = testAppVersion
require.NoError(t, err)
nextVals, nextPrivVals := factory.RandValidatorSet(ctx, 3, 10)
nextVals, nextPrivVals := factory.RandValidatorSet(ctx, t, 3, 10)
header.ValidatorsHash = currentVals.Hash()
header.NextValidatorsHash = nextVals.Hash()
header.ConsensusHash = types.DefaultConsensusParams().HashConsensusParams()
@@ -837,6 +842,7 @@ func mockLB(ctx context.Context, t *testing.T, height int64, time time.Time, las
// graduallyAddPeers delivers a new randomly-generated peer update on peerUpdateCh once
// per interval, until closeCh is closed. Each peer update is assigned a random node ID.
func graduallyAddPeers(
t *testing.T,
peerUpdateCh chan p2p.PeerUpdate,
closeCh chan struct{},
interval time.Duration,
@@ -846,7 +852,7 @@ func graduallyAddPeers(
select {
case <-ticker.C:
peerUpdateCh <- p2p.PeerUpdate{
NodeID: factory.RandomNodeID(),
NodeID: factory.RandomNodeID(t),
Status: p2p.PeerStatusUp,
}
case <-closeCh:
+28 -17
View File
@@ -68,7 +68,7 @@ func TestSyncer_SyncAny(t *testing.T) {
peerAID := types.NodeID("aa")
peerBID := types.NodeID("bb")
peerCID := types.NodeID("cc")
rts := setup(ctx, t, connSnapshot, connQuery, stateProvider, 3)
rts := setup(ctx, t, connSnapshot, connQuery, stateProvider, 4)
rts.reactor.syncer = rts.syncer
@@ -133,27 +133,38 @@ func TestSyncer_SyncAny(t *testing.T) {
chunkRequests := make(map[uint32]int)
chunkRequestsMtx := sync.Mutex{}
var wg sync.WaitGroup
wg.Add(4)
chunkProcessDone := make(chan struct{})
go func() {
for e := range rts.chunkOutCh {
msg, ok := e.Message.(*ssproto.ChunkRequest)
assert.True(t, ok)
defer close(chunkProcessDone)
var seen int
for {
if seen >= 4 {
return
}
assert.EqualValues(t, 1, msg.Height)
assert.EqualValues(t, 1, msg.Format)
assert.LessOrEqual(t, msg.Index, uint32(len(chunks)))
select {
case <-ctx.Done():
t.Logf("sent %d chunks", seen)
return
case e := <-rts.chunkOutCh:
msg, ok := e.Message.(*ssproto.ChunkRequest)
assert.True(t, ok)
added, err := rts.syncer.AddChunk(chunks[msg.Index])
assert.NoError(t, err)
assert.True(t, added)
assert.EqualValues(t, 1, msg.Height)
assert.EqualValues(t, 1, msg.Format)
assert.LessOrEqual(t, msg.Index, uint32(len(chunks)))
chunkRequestsMtx.Lock()
chunkRequests[msg.Index]++
chunkRequestsMtx.Unlock()
added, err := rts.syncer.AddChunk(chunks[msg.Index])
assert.NoError(t, err)
assert.True(t, added)
wg.Done()
chunkRequestsMtx.Lock()
chunkRequests[msg.Index]++
chunkRequestsMtx.Unlock()
seen++
t.Logf("added chunk (%d of 4): %d", seen, msg.Index)
}
}
}()
@@ -186,7 +197,7 @@ func TestSyncer_SyncAny(t *testing.T) {
newState, lastCommit, err := rts.syncer.SyncAny(ctx, 0, func() error { return nil })
require.NoError(t, err)
wg.Wait()
<-chunkProcessDone
chunkRequestsMtx.Lock()
require.Equal(t, map[uint32]int{0: 1, 1: 2, 2: 1}, chunkRequests)
+5 -15
View File
@@ -1,8 +1,10 @@
package factory
import (
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/tmhash"
"github.com/tendermint/tendermint/types"
@@ -17,13 +19,6 @@ var (
DefaultTestTime = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
)
func MakeVersion() version.Consensus {
return version.Consensus{
Block: version.BlockProtocol,
App: 1,
}
}
func RandomAddress() []byte {
return crypto.CRandBytes(crypto.AddressSize)
}
@@ -48,7 +43,8 @@ func MakeBlockIDWithHash(hash []byte) types.BlockID {
// MakeHeader fills the rest of the contents of the header such that it passes
// validate basic
func MakeHeader(h *types.Header) (*types.Header, error) {
func MakeHeader(t *testing.T, h *types.Header) *types.Header {
t.Helper()
if h.Version.Block == 0 {
h.Version.Block = version.BlockProtocol
}
@@ -89,13 +85,7 @@ func MakeHeader(h *types.Header) (*types.Header, error) {
h.ProposerAddress = RandomAddress()
}
return h, h.ValidateBasic()
}
require.NoError(t, h.ValidateBasic())
func MakeRandomHeader() *types.Header {
h, err := MakeHeader(&types.Header{})
if err != nil {
panic(err)
}
return h
}
+8 -15
View File
@@ -2,7 +2,6 @@ package factory
import (
"context"
"fmt"
"time"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
@@ -10,12 +9,11 @@ import (
)
func MakeCommit(ctx context.Context, blockID types.BlockID, height int64, round int32, voteSet *types.VoteSet, validators []types.PrivValidator, now time.Time) (*types.Commit, error) {
// all sign
for i := 0; i < len(validators); i++ {
pubKey, err := validators[i].GetPubKey(ctx)
if err != nil {
return nil, fmt.Errorf("can't get pubkey: %w", err)
return nil, err
}
vote := &types.Vote{
ValidatorAddress: pubKey.Address(),
@@ -27,21 +25,16 @@ func MakeCommit(ctx context.Context, blockID types.BlockID, height int64, round
Timestamp: now,
}
_, err = signAddVote(ctx, validators[i], vote, voteSet)
if err != nil {
v := vote.ToProto()
if err := validators[i].SignVote(ctx, voteSet.ChainID(), v); err != nil {
return nil, err
}
vote.Signature = v.Signature
if _, err := voteSet.AddVote(vote); err != nil {
return nil, err
}
}
return voteSet.MakeCommit(), nil
}
func signAddVote(ctx context.Context, privVal types.PrivValidator, vote *types.Vote, voteSet *types.VoteSet) (signed bool, err error) {
v := vote.ToProto()
err = privVal.SignVote(ctx, voteSet.ChainID(), v)
if err != nil {
return false, err
}
vote.Signature = v.Signature
return voteSet.AddVote(vote)
}
+2 -5
View File
@@ -3,16 +3,13 @@ package factory
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tendermint/tendermint/types"
)
func TestMakeHeader(t *testing.T) {
_, err := MakeHeader(&types.Header{})
assert.NoError(t, err)
MakeHeader(t, &types.Header{})
}
func TestRandomNodeID(t *testing.T) {
assert.NotPanics(t, func() { RandomNodeID() })
RandomNodeID(t)
}
+6 -8
View File
@@ -3,24 +3,22 @@ package factory
import (
"context"
"sort"
"testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/config"
tmtime "github.com/tendermint/tendermint/libs/time"
"github.com/tendermint/tendermint/types"
)
func RandGenesisDoc(
ctx context.Context,
cfg *config.Config,
numValidators int,
randPower bool,
minPower int64,
) (*types.GenesisDoc, []types.PrivValidator) {
func RandGenesisDoc(ctx context.Context, t *testing.T, cfg *config.Config, numValidators int, randPower bool, minPower int64) (*types.GenesisDoc, []types.PrivValidator) {
t.Helper()
validators := make([]types.GenesisValidator, numValidators)
privValidators := make([]types.PrivValidator, numValidators)
for i := 0; i < numValidators; i++ {
val, privVal := RandValidator(ctx, randPower, minPower)
val, privVal, err := RandValidator(ctx, randPower, minPower)
require.NoError(t, err)
validators[i] = types.GenesisValidator{
PubKey: val.PubKey,
Power: val.VotingPower,
+12 -8
View File
@@ -3,25 +3,29 @@ package factory
import (
"encoding/hex"
"strings"
"testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/rand"
"github.com/tendermint/tendermint/types"
)
// NodeID returns a valid NodeID based on an inputted string
func NodeID(str string) types.NodeID {
func NodeID(t *testing.T, str string) types.NodeID {
t.Helper()
id, err := types.NewNodeID(strings.Repeat(str, 2*types.NodeIDByteLength))
if err != nil {
panic(err)
}
require.NoError(t, err)
return id
}
// RandomNodeID returns a randomly generated valid NodeID
func RandomNodeID() types.NodeID {
func RandomNodeID(t *testing.T) types.NodeID {
t.Helper()
id, err := types.NewNodeID(hex.EncodeToString(rand.Bytes(types.NodeIDByteLength)))
if err != nil {
panic(err)
}
require.NoError(t, err)
return id
}
+4 -9
View File
@@ -2,15 +2,10 @@ package factory
import "github.com/tendermint/tendermint/types"
// MakeTxs is a helper function to generate mock transactions by given the block height
// and the transaction numbers.
func MakeTxs(height int64, num int) (txs []types.Tx) {
for i := 0; i < num; i++ {
txs = append(txs, types.Tx([]byte{byte(height), byte(i)}))
func MakeTenTxs(height int64) []types.Tx {
txs := make([]types.Tx, 10)
for i := range txs {
txs[i] = types.Tx([]byte{byte(height), byte(i)})
}
return txs
}
func MakeTenTxs(height int64) (txs []types.Tx) {
return MakeTxs(height, 10)
}
+10 -5
View File
@@ -5,11 +5,13 @@ import (
"fmt"
"math/rand"
"sort"
"testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/types"
)
func RandValidator(ctx context.Context, randPower bool, minPower int64) (*types.Validator, types.PrivValidator) {
func RandValidator(ctx context.Context, randPower bool, minPower int64) (*types.Validator, types.PrivValidator, error) {
privVal := types.NewMockPV()
votePower := minPower
if randPower {
@@ -18,20 +20,23 @@ func RandValidator(ctx context.Context, randPower bool, minPower int64) (*types.
}
pubKey, err := privVal.GetPubKey(ctx)
if err != nil {
panic(fmt.Errorf("could not retrieve pubkey %w", err))
return nil, nil, fmt.Errorf("could not retrieve public key: %w", err)
}
val := types.NewValidator(pubKey, votePower)
return val, privVal
return val, privVal, err
}
func RandValidatorSet(ctx context.Context, numValidators int, votingPower int64) (*types.ValidatorSet, []types.PrivValidator) {
func RandValidatorSet(ctx context.Context, t *testing.T, numValidators int, votingPower int64) (*types.ValidatorSet, []types.PrivValidator) {
var (
valz = make([]*types.Validator, numValidators)
privValidators = make([]types.PrivValidator, numValidators)
)
t.Helper()
for i := 0; i < numValidators; i++ {
val, privValidator := RandValidator(ctx, false, votingPower)
val, privValidator, err := RandValidator(ctx, false, votingPower)
require.NoError(t, err)
valz[i] = val
privValidators[i] = privValidator
}
+4 -3
View File
@@ -23,6 +23,7 @@ func MakeVote(
if err != nil {
return nil, err
}
v := &types.Vote{
ValidatorAddress: pubKey.Address(),
ValidatorIndex: valIndex,
@@ -34,10 +35,10 @@ func MakeVote(
}
vpb := v.ToProto()
err = val.SignVote(ctx, chainID, vpb)
if err != nil {
panic(err)
if err := val.SignVote(ctx, chainID, vpb); err != nil {
return nil, err
}
v.Signature = vpb.Signature
return v, nil
}
+3 -10
View File
@@ -14,8 +14,6 @@ var _ Logger = (*defaultLogger)(nil)
type defaultLogger struct {
zerolog.Logger
trace bool
}
// NewDefaultLogger returns a default logger that can be used within Tendermint
@@ -26,7 +24,7 @@ type defaultLogger struct {
// Since zerolog supports typed structured logging and it is difficult to reflect
// that in a generic interface, all logging methods accept a series of key/value
// pair tuples, where the key must be a string.
func NewDefaultLogger(format, level string, trace bool) (Logger, error) {
func NewDefaultLogger(format, level string) (Logger, error) {
var logWriter io.Writer
switch strings.ToLower(format) {
case LogFormatPlain, LogFormatText:
@@ -59,14 +57,13 @@ func NewDefaultLogger(format, level string, trace bool) (Logger, error) {
return defaultLogger{
Logger: zerolog.New(logWriter).Level(logLevel).With().Timestamp().Logger(),
trace: trace,
}, nil
}
// MustNewDefaultLogger delegates a call NewDefaultLogger where it panics on
// error.
func MustNewDefaultLogger(format, level string, trace bool) Logger {
logger, err := NewDefaultLogger(format, level, trace)
func MustNewDefaultLogger(format, level string) Logger {
logger, err := NewDefaultLogger(format, level)
if err != nil {
panic(err)
}
@@ -80,9 +77,6 @@ func (l defaultLogger) Info(msg string, keyVals ...interface{}) {
func (l defaultLogger) Error(msg string, keyVals ...interface{}) {
e := l.Logger.Error()
if l.trace {
e = e.Stack()
}
e.Fields(getLogFields(keyVals...)).Msg(msg)
}
@@ -94,7 +88,6 @@ func (l defaultLogger) Debug(msg string, keyVals ...interface{}) {
func (l defaultLogger) With(keyVals ...interface{}) Logger {
return defaultLogger{
Logger: l.Logger.With().Fields(getLogFields(keyVals...)).Logger(),
trace: l.trace,
}
}
+2 -2
View File
@@ -34,11 +34,11 @@ func TestNewDefaultLogger(t *testing.T) {
tc := tc
t.Run(name, func(t *testing.T) {
_, err := log.NewDefaultLogger(tc.format, tc.level, false)
_, err := log.NewDefaultLogger(tc.format, tc.level)
if tc.expectErr {
require.Error(t, err)
require.Panics(t, func() {
_ = log.MustNewDefaultLogger(tc.format, tc.level, false)
_ = log.MustNewDefaultLogger(tc.format, tc.level)
})
} else {
require.NoError(t, err)
-1
View File
@@ -7,6 +7,5 @@ import (
func NewNopLogger() Logger {
return defaultLogger{
Logger: zerolog.Nop(),
trace: false,
}
}
+1 -6
View File
@@ -32,7 +32,7 @@ func TestingLogger() Logger {
}
if testing.Verbose() {
testingLogger = MustNewDefaultLogger(LogFormatText, LogLevelDebug, true)
testingLogger = MustNewDefaultLogger(LogFormatText, LogLevelDebug)
} else {
testingLogger = NewNopLogger()
}
@@ -73,13 +73,8 @@ func NewTestingLoggerWithLevel(t testing.TB, level string) Logger {
if err != nil {
t.Fatalf("failed to parse log level (%s): %v", level, err)
}
trace := false
if testing.Verbose() {
trace = true
}
return defaultLogger{
Logger: zerolog.New(newSyncWriter(testingWriter{t})).Level(logLevel),
trace: trace,
}
}
-2
View File
@@ -162,7 +162,6 @@ func (bs *BaseService) Start(ctx context.Context) error {
return nil
}
bs.logger.Debug("not starting service; already started", "service", bs.name, "impl", bs.impl.String())
return ErrAlreadyStarted
}
@@ -183,7 +182,6 @@ func (bs *BaseService) Stop() error {
return nil
}
bs.logger.Debug("not stopping service; already stopped", "service", bs.name, "impl", bs.impl.String())
return ErrAlreadyStopped
}
+2 -2
View File
@@ -114,7 +114,7 @@ func TestClient_SequentialVerification(t *testing.T) {
newKeys := genPrivKeys(4)
newVals := newKeys.ToValidators(10, 1)
differentVals, _ := factory.RandValidatorSet(ctx, 10, 100)
differentVals, _ := factory.RandValidatorSet(ctx, t, 10, 100)
testCases := []struct {
name string
@@ -942,7 +942,7 @@ func TestClient_TrustedValidatorSet(t *testing.T) {
logger := log.NewTestingLogger(t)
differentVals, _ := factory.RandValidatorSet(ctx, 10, 100)
differentVals, _ := factory.RandValidatorSet(ctx, t, 10, 100)
mockBadValSetNode := mockNodeFromHeadersAndVals(
map[int64]*types.SignedHeader{
1: h1,
+1 -1
View File
@@ -26,7 +26,7 @@ func ExampleClient() {
stdlog.Fatal(err)
}
logger, err := log.NewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false)
logger, err := log.NewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo)
if err != nil {
stdlog.Fatal(err)
}
+2 -2
View File
@@ -95,7 +95,7 @@ func (p *Proxy) listen(ctx context.Context) (net.Listener, *http.ServeMux, error
// 2) Allow websocket connections.
wmLogger := p.Logger.With("protocol", "websocket")
wm := rpcserver.NewWebsocketManager(r,
wm := rpcserver.NewWebsocketManager(wmLogger, r,
rpcserver.OnDisconnect(func(remoteAddr string) {
err := p.Client.UnsubscribeAll(context.Background(), remoteAddr)
if err != nil && err != tmpubsub.ErrSubscriptionNotFound {
@@ -104,7 +104,7 @@ func (p *Proxy) listen(ctx context.Context) (net.Listener, *http.ServeMux, error
}),
rpcserver.ReadLimit(p.Config.MaxBodyBytes),
)
wm.SetLogger(wmLogger)
mux.HandleFunc("/websocket", wm.WebsocketHandler)
// 3) Start a client.
+110 -109
View File
@@ -1,12 +1,13 @@
package proxy
import (
"context"
"github.com/tendermint/tendermint/libs/bytes"
lrpc "github.com/tendermint/tendermint/light/rpc"
rpcclient "github.com/tendermint/tendermint/rpc/client"
"github.com/tendermint/tendermint/rpc/coretypes"
rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server"
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
"github.com/tendermint/tendermint/types"
)
@@ -18,149 +19,149 @@ func RPCRoutes(c *lrpc.Client) map[string]*rpcserver.RPCFunc {
"unsubscribe_all": rpcserver.NewWSRPCFunc(c.UnsubscribeAllWS, ""),
// info API
"health": rpcserver.NewRPCFunc(makeHealthFunc(c), "", false),
"status": rpcserver.NewRPCFunc(makeStatusFunc(c), "", false),
"net_info": rpcserver.NewRPCFunc(makeNetInfoFunc(c), "", false),
"blockchain": rpcserver.NewRPCFunc(makeBlockchainInfoFunc(c), "minHeight,maxHeight", true),
"genesis": rpcserver.NewRPCFunc(makeGenesisFunc(c), "", true),
"genesis_chunked": rpcserver.NewRPCFunc(makeGenesisChunkedFunc(c), "", true),
"header": rpcserver.NewRPCFunc(makeHeaderFunc(c), "height", true),
"header_by_hash": rpcserver.NewRPCFunc(makeHeaderByHashFunc(c), "hash", true),
"block": rpcserver.NewRPCFunc(makeBlockFunc(c), "height", true),
"block_by_hash": rpcserver.NewRPCFunc(makeBlockByHashFunc(c), "hash", true),
"block_results": rpcserver.NewRPCFunc(makeBlockResultsFunc(c), "height", true),
"commit": rpcserver.NewRPCFunc(makeCommitFunc(c), "height", true),
"tx": rpcserver.NewRPCFunc(makeTxFunc(c), "hash,prove", true),
"tx_search": rpcserver.NewRPCFunc(makeTxSearchFunc(c), "query,prove,page,per_page,order_by", false),
"block_search": rpcserver.NewRPCFunc(makeBlockSearchFunc(c), "query,page,per_page,order_by", false),
"validators": rpcserver.NewRPCFunc(makeValidatorsFunc(c), "height,page,per_page", true),
"dump_consensus_state": rpcserver.NewRPCFunc(makeDumpConsensusStateFunc(c), "", false),
"consensus_state": rpcserver.NewRPCFunc(makeConsensusStateFunc(c), "", false),
"consensus_params": rpcserver.NewRPCFunc(makeConsensusParamsFunc(c), "height", true),
"unconfirmed_txs": rpcserver.NewRPCFunc(makeUnconfirmedTxsFunc(c), "limit", false),
"num_unconfirmed_txs": rpcserver.NewRPCFunc(makeNumUnconfirmedTxsFunc(c), "", false),
"health": rpcserver.NewRPCFunc(makeHealthFunc(c), ""),
"status": rpcserver.NewRPCFunc(makeStatusFunc(c), ""),
"net_info": rpcserver.NewRPCFunc(makeNetInfoFunc(c), ""),
"blockchain": rpcserver.NewRPCFunc(makeBlockchainInfoFunc(c), "minHeight,maxHeight"),
"genesis": rpcserver.NewRPCFunc(makeGenesisFunc(c), ""),
"genesis_chunked": rpcserver.NewRPCFunc(makeGenesisChunkedFunc(c), ""),
"header": rpcserver.NewRPCFunc(makeHeaderFunc(c), "height"),
"header_by_hash": rpcserver.NewRPCFunc(makeHeaderByHashFunc(c), "hash"),
"block": rpcserver.NewRPCFunc(makeBlockFunc(c), "height"),
"block_by_hash": rpcserver.NewRPCFunc(makeBlockByHashFunc(c), "hash"),
"block_results": rpcserver.NewRPCFunc(makeBlockResultsFunc(c), "height"),
"commit": rpcserver.NewRPCFunc(makeCommitFunc(c), "height"),
"tx": rpcserver.NewRPCFunc(makeTxFunc(c), "hash,prove"),
"tx_search": rpcserver.NewRPCFunc(makeTxSearchFunc(c), "query,prove,page,per_page,order_by"),
"block_search": rpcserver.NewRPCFunc(makeBlockSearchFunc(c), "query,page,per_page,order_by"),
"validators": rpcserver.NewRPCFunc(makeValidatorsFunc(c), "height,page,per_page"),
"dump_consensus_state": rpcserver.NewRPCFunc(makeDumpConsensusStateFunc(c), ""),
"consensus_state": rpcserver.NewRPCFunc(makeConsensusStateFunc(c), ""),
"consensus_params": rpcserver.NewRPCFunc(makeConsensusParamsFunc(c), "height"),
"unconfirmed_txs": rpcserver.NewRPCFunc(makeUnconfirmedTxsFunc(c), "limit"),
"num_unconfirmed_txs": rpcserver.NewRPCFunc(makeNumUnconfirmedTxsFunc(c), ""),
// tx broadcast API
"broadcast_tx_commit": rpcserver.NewRPCFunc(makeBroadcastTxCommitFunc(c), "tx", false),
"broadcast_tx_sync": rpcserver.NewRPCFunc(makeBroadcastTxSyncFunc(c), "tx", false),
"broadcast_tx_async": rpcserver.NewRPCFunc(makeBroadcastTxAsyncFunc(c), "tx", false),
"broadcast_tx_commit": rpcserver.NewRPCFunc(makeBroadcastTxCommitFunc(c), "tx"),
"broadcast_tx_sync": rpcserver.NewRPCFunc(makeBroadcastTxSyncFunc(c), "tx"),
"broadcast_tx_async": rpcserver.NewRPCFunc(makeBroadcastTxAsyncFunc(c), "tx"),
// abci API
"abci_query": rpcserver.NewRPCFunc(makeABCIQueryFunc(c), "path,data,height,prove", false),
"abci_info": rpcserver.NewRPCFunc(makeABCIInfoFunc(c), "", true),
"abci_query": rpcserver.NewRPCFunc(makeABCIQueryFunc(c), "path,data,height,prove"),
"abci_info": rpcserver.NewRPCFunc(makeABCIInfoFunc(c), ""),
// evidence API
"broadcast_evidence": rpcserver.NewRPCFunc(makeBroadcastEvidenceFunc(c), "evidence", false),
"broadcast_evidence": rpcserver.NewRPCFunc(makeBroadcastEvidenceFunc(c), "evidence"),
}
}
type rpcHealthFunc func(ctx *rpctypes.Context) (*coretypes.ResultHealth, error)
type rpcHealthFunc func(ctx context.Context) (*coretypes.ResultHealth, error)
func makeHealthFunc(c *lrpc.Client) rpcHealthFunc {
return func(ctx *rpctypes.Context) (*coretypes.ResultHealth, error) {
return c.Health(ctx.Context())
return func(ctx context.Context) (*coretypes.ResultHealth, error) {
return c.Health(ctx)
}
}
type rpcStatusFunc func(ctx *rpctypes.Context) (*coretypes.ResultStatus, error)
type rpcStatusFunc func(ctx context.Context) (*coretypes.ResultStatus, error)
// nolint: interfacer
func makeStatusFunc(c *lrpc.Client) rpcStatusFunc {
return func(ctx *rpctypes.Context) (*coretypes.ResultStatus, error) {
return c.Status(ctx.Context())
return func(ctx context.Context) (*coretypes.ResultStatus, error) {
return c.Status(ctx)
}
}
type rpcNetInfoFunc func(ctx *rpctypes.Context) (*coretypes.ResultNetInfo, error)
type rpcNetInfoFunc func(ctx context.Context) (*coretypes.ResultNetInfo, error)
func makeNetInfoFunc(c *lrpc.Client) rpcNetInfoFunc {
return func(ctx *rpctypes.Context) (*coretypes.ResultNetInfo, error) {
return c.NetInfo(ctx.Context())
return func(ctx context.Context) (*coretypes.ResultNetInfo, error) {
return c.NetInfo(ctx)
}
}
type rpcBlockchainInfoFunc func(ctx *rpctypes.Context, minHeight, maxHeight int64) (*coretypes.ResultBlockchainInfo, error)
type rpcBlockchainInfoFunc func(ctx context.Context, minHeight, maxHeight int64) (*coretypes.ResultBlockchainInfo, error)
func makeBlockchainInfoFunc(c *lrpc.Client) rpcBlockchainInfoFunc {
return func(ctx *rpctypes.Context, minHeight, maxHeight int64) (*coretypes.ResultBlockchainInfo, error) {
return c.BlockchainInfo(ctx.Context(), minHeight, maxHeight)
return func(ctx context.Context, minHeight, maxHeight int64) (*coretypes.ResultBlockchainInfo, error) {
return c.BlockchainInfo(ctx, minHeight, maxHeight)
}
}
type rpcGenesisFunc func(ctx *rpctypes.Context) (*coretypes.ResultGenesis, error)
type rpcGenesisFunc func(ctx context.Context) (*coretypes.ResultGenesis, error)
func makeGenesisFunc(c *lrpc.Client) rpcGenesisFunc {
return func(ctx *rpctypes.Context) (*coretypes.ResultGenesis, error) {
return c.Genesis(ctx.Context())
return func(ctx context.Context) (*coretypes.ResultGenesis, error) {
return c.Genesis(ctx)
}
}
type rpcGenesisChunkedFunc func(ctx *rpctypes.Context, chunk uint) (*coretypes.ResultGenesisChunk, error)
type rpcGenesisChunkedFunc func(ctx context.Context, chunk uint) (*coretypes.ResultGenesisChunk, error)
func makeGenesisChunkedFunc(c *lrpc.Client) rpcGenesisChunkedFunc {
return func(ctx *rpctypes.Context, chunk uint) (*coretypes.ResultGenesisChunk, error) {
return c.GenesisChunked(ctx.Context(), chunk)
return func(ctx context.Context, chunk uint) (*coretypes.ResultGenesisChunk, error) {
return c.GenesisChunked(ctx, chunk)
}
}
type rpcHeaderFunc func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultHeader, error)
type rpcHeaderFunc func(ctx context.Context, height *int64) (*coretypes.ResultHeader, error)
func makeHeaderFunc(c *lrpc.Client) rpcHeaderFunc {
return func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultHeader, error) {
return c.Header(ctx.Context(), height)
return func(ctx context.Context, height *int64) (*coretypes.ResultHeader, error) {
return c.Header(ctx, height)
}
}
type rpcHeaderByHashFunc func(ctx *rpctypes.Context, hash []byte) (*coretypes.ResultHeader, error)
type rpcHeaderByHashFunc func(ctx context.Context, hash []byte) (*coretypes.ResultHeader, error)
func makeHeaderByHashFunc(c *lrpc.Client) rpcHeaderByHashFunc {
return func(ctx *rpctypes.Context, hash []byte) (*coretypes.ResultHeader, error) {
return c.HeaderByHash(ctx.Context(), hash)
return func(ctx context.Context, hash []byte) (*coretypes.ResultHeader, error) {
return c.HeaderByHash(ctx, hash)
}
}
type rpcBlockFunc func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultBlock, error)
type rpcBlockFunc func(ctx context.Context, height *int64) (*coretypes.ResultBlock, error)
func makeBlockFunc(c *lrpc.Client) rpcBlockFunc {
return func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultBlock, error) {
return c.Block(ctx.Context(), height)
return func(ctx context.Context, height *int64) (*coretypes.ResultBlock, error) {
return c.Block(ctx, height)
}
}
type rpcBlockByHashFunc func(ctx *rpctypes.Context, hash []byte) (*coretypes.ResultBlock, error)
type rpcBlockByHashFunc func(ctx context.Context, hash []byte) (*coretypes.ResultBlock, error)
func makeBlockByHashFunc(c *lrpc.Client) rpcBlockByHashFunc {
return func(ctx *rpctypes.Context, hash []byte) (*coretypes.ResultBlock, error) {
return c.BlockByHash(ctx.Context(), hash)
return func(ctx context.Context, hash []byte) (*coretypes.ResultBlock, error) {
return c.BlockByHash(ctx, hash)
}
}
type rpcBlockResultsFunc func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultBlockResults, error)
type rpcBlockResultsFunc func(ctx context.Context, height *int64) (*coretypes.ResultBlockResults, error)
func makeBlockResultsFunc(c *lrpc.Client) rpcBlockResultsFunc {
return func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultBlockResults, error) {
return c.BlockResults(ctx.Context(), height)
return func(ctx context.Context, height *int64) (*coretypes.ResultBlockResults, error) {
return c.BlockResults(ctx, height)
}
}
type rpcCommitFunc func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultCommit, error)
type rpcCommitFunc func(ctx context.Context, height *int64) (*coretypes.ResultCommit, error)
func makeCommitFunc(c *lrpc.Client) rpcCommitFunc {
return func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultCommit, error) {
return c.Commit(ctx.Context(), height)
return func(ctx context.Context, height *int64) (*coretypes.ResultCommit, error) {
return c.Commit(ctx, height)
}
}
type rpcTxFunc func(ctx *rpctypes.Context, hash []byte, prove bool) (*coretypes.ResultTx, error)
type rpcTxFunc func(ctx context.Context, hash []byte, prove bool) (*coretypes.ResultTx, error)
func makeTxFunc(c *lrpc.Client) rpcTxFunc {
return func(ctx *rpctypes.Context, hash []byte, prove bool) (*coretypes.ResultTx, error) {
return c.Tx(ctx.Context(), hash, prove)
return func(ctx context.Context, hash []byte, prove bool) (*coretypes.ResultTx, error) {
return c.Tx(ctx, hash, prove)
}
}
type rpcTxSearchFunc func(
ctx *rpctypes.Context,
ctx context.Context,
query string,
prove bool,
page, perPage *int,
@@ -169,18 +170,18 @@ type rpcTxSearchFunc func(
func makeTxSearchFunc(c *lrpc.Client) rpcTxSearchFunc {
return func(
ctx *rpctypes.Context,
ctx context.Context,
query string,
prove bool,
page, perPage *int,
orderBy string,
) (*coretypes.ResultTxSearch, error) {
return c.TxSearch(ctx.Context(), query, prove, page, perPage, orderBy)
return c.TxSearch(ctx, query, prove, page, perPage, orderBy)
}
}
type rpcBlockSearchFunc func(
ctx *rpctypes.Context,
ctx context.Context,
query string,
prove bool,
page, perPage *int,
@@ -189,116 +190,116 @@ type rpcBlockSearchFunc func(
func makeBlockSearchFunc(c *lrpc.Client) rpcBlockSearchFunc {
return func(
ctx *rpctypes.Context,
ctx context.Context,
query string,
prove bool,
page, perPage *int,
orderBy string,
) (*coretypes.ResultBlockSearch, error) {
return c.BlockSearch(ctx.Context(), query, page, perPage, orderBy)
return c.BlockSearch(ctx, query, page, perPage, orderBy)
}
}
type rpcValidatorsFunc func(ctx *rpctypes.Context, height *int64,
type rpcValidatorsFunc func(ctx context.Context, height *int64,
page, perPage *int) (*coretypes.ResultValidators, error)
func makeValidatorsFunc(c *lrpc.Client) rpcValidatorsFunc {
return func(ctx *rpctypes.Context, height *int64, page, perPage *int) (*coretypes.ResultValidators, error) {
return c.Validators(ctx.Context(), height, page, perPage)
return func(ctx context.Context, height *int64, page, perPage *int) (*coretypes.ResultValidators, error) {
return c.Validators(ctx, height, page, perPage)
}
}
type rpcDumpConsensusStateFunc func(ctx *rpctypes.Context) (*coretypes.ResultDumpConsensusState, error)
type rpcDumpConsensusStateFunc func(ctx context.Context) (*coretypes.ResultDumpConsensusState, error)
func makeDumpConsensusStateFunc(c *lrpc.Client) rpcDumpConsensusStateFunc {
return func(ctx *rpctypes.Context) (*coretypes.ResultDumpConsensusState, error) {
return c.DumpConsensusState(ctx.Context())
return func(ctx context.Context) (*coretypes.ResultDumpConsensusState, error) {
return c.DumpConsensusState(ctx)
}
}
type rpcConsensusStateFunc func(ctx *rpctypes.Context) (*coretypes.ResultConsensusState, error)
type rpcConsensusStateFunc func(ctx context.Context) (*coretypes.ResultConsensusState, error)
func makeConsensusStateFunc(c *lrpc.Client) rpcConsensusStateFunc {
return func(ctx *rpctypes.Context) (*coretypes.ResultConsensusState, error) {
return c.ConsensusState(ctx.Context())
return func(ctx context.Context) (*coretypes.ResultConsensusState, error) {
return c.ConsensusState(ctx)
}
}
type rpcConsensusParamsFunc func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultConsensusParams, error)
type rpcConsensusParamsFunc func(ctx context.Context, height *int64) (*coretypes.ResultConsensusParams, error)
func makeConsensusParamsFunc(c *lrpc.Client) rpcConsensusParamsFunc {
return func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultConsensusParams, error) {
return c.ConsensusParams(ctx.Context(), height)
return func(ctx context.Context, height *int64) (*coretypes.ResultConsensusParams, error) {
return c.ConsensusParams(ctx, height)
}
}
type rpcUnconfirmedTxsFunc func(ctx *rpctypes.Context, limit *int) (*coretypes.ResultUnconfirmedTxs, error)
type rpcUnconfirmedTxsFunc func(ctx context.Context, limit *int) (*coretypes.ResultUnconfirmedTxs, error)
func makeUnconfirmedTxsFunc(c *lrpc.Client) rpcUnconfirmedTxsFunc {
return func(ctx *rpctypes.Context, limit *int) (*coretypes.ResultUnconfirmedTxs, error) {
return c.UnconfirmedTxs(ctx.Context(), limit)
return func(ctx context.Context, limit *int) (*coretypes.ResultUnconfirmedTxs, error) {
return c.UnconfirmedTxs(ctx, limit)
}
}
type rpcNumUnconfirmedTxsFunc func(ctx *rpctypes.Context) (*coretypes.ResultUnconfirmedTxs, error)
type rpcNumUnconfirmedTxsFunc func(ctx context.Context) (*coretypes.ResultUnconfirmedTxs, error)
func makeNumUnconfirmedTxsFunc(c *lrpc.Client) rpcNumUnconfirmedTxsFunc {
return func(ctx *rpctypes.Context) (*coretypes.ResultUnconfirmedTxs, error) {
return c.NumUnconfirmedTxs(ctx.Context())
return func(ctx context.Context) (*coretypes.ResultUnconfirmedTxs, error) {
return c.NumUnconfirmedTxs(ctx)
}
}
type rpcBroadcastTxCommitFunc func(ctx *rpctypes.Context, tx types.Tx) (*coretypes.ResultBroadcastTxCommit, error)
type rpcBroadcastTxCommitFunc func(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTxCommit, error)
func makeBroadcastTxCommitFunc(c *lrpc.Client) rpcBroadcastTxCommitFunc {
return func(ctx *rpctypes.Context, tx types.Tx) (*coretypes.ResultBroadcastTxCommit, error) {
return c.BroadcastTxCommit(ctx.Context(), tx)
return func(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTxCommit, error) {
return c.BroadcastTxCommit(ctx, tx)
}
}
type rpcBroadcastTxSyncFunc func(ctx *rpctypes.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error)
type rpcBroadcastTxSyncFunc func(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error)
func makeBroadcastTxSyncFunc(c *lrpc.Client) rpcBroadcastTxSyncFunc {
return func(ctx *rpctypes.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
return c.BroadcastTxSync(ctx.Context(), tx)
return func(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
return c.BroadcastTxSync(ctx, tx)
}
}
type rpcBroadcastTxAsyncFunc func(ctx *rpctypes.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error)
type rpcBroadcastTxAsyncFunc func(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error)
func makeBroadcastTxAsyncFunc(c *lrpc.Client) rpcBroadcastTxAsyncFunc {
return func(ctx *rpctypes.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
return c.BroadcastTxAsync(ctx.Context(), tx)
return func(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
return c.BroadcastTxAsync(ctx, tx)
}
}
type rpcABCIQueryFunc func(ctx *rpctypes.Context, path string,
type rpcABCIQueryFunc func(ctx context.Context, path string,
data bytes.HexBytes, height int64, prove bool) (*coretypes.ResultABCIQuery, error)
func makeABCIQueryFunc(c *lrpc.Client) rpcABCIQueryFunc {
return func(ctx *rpctypes.Context, path string, data bytes.HexBytes,
return func(ctx context.Context, path string, data bytes.HexBytes,
height int64, prove bool) (*coretypes.ResultABCIQuery, error) {
return c.ABCIQueryWithOptions(ctx.Context(), path, data, rpcclient.ABCIQueryOptions{
return c.ABCIQueryWithOptions(ctx, path, data, rpcclient.ABCIQueryOptions{
Height: height,
Prove: prove,
})
}
}
type rpcABCIInfoFunc func(ctx *rpctypes.Context) (*coretypes.ResultABCIInfo, error)
type rpcABCIInfoFunc func(ctx context.Context) (*coretypes.ResultABCIInfo, error)
func makeABCIInfoFunc(c *lrpc.Client) rpcABCIInfoFunc {
return func(ctx *rpctypes.Context) (*coretypes.ResultABCIInfo, error) {
return c.ABCIInfo(ctx.Context())
return func(ctx context.Context) (*coretypes.ResultABCIInfo, error) {
return c.ABCIInfo(ctx)
}
}
type rpcBroadcastEvidenceFunc func(ctx *rpctypes.Context, ev types.Evidence) (*coretypes.ResultBroadcastEvidence, error)
type rpcBroadcastEvidenceFunc func(ctx context.Context, ev types.Evidence) (*coretypes.ResultBroadcastEvidence, error)
// nolint: interfacer
func makeBroadcastEvidenceFunc(c *lrpc.Client) rpcBroadcastEvidenceFunc {
return func(ctx *rpctypes.Context, ev types.Evidence) (*coretypes.ResultBroadcastEvidence, error) {
return c.BroadcastEvidence(ctx.Context(), ev)
return func(ctx context.Context, ev types.Evidence) (*coretypes.ResultBroadcastEvidence, error) {
return c.BroadcastEvidence(ctx, ev)
}
}
+9 -8
View File
@@ -615,11 +615,12 @@ func (c *Client) RegisterOpDecoder(typ string, dec merkle.OpDecoder) {
// SubscribeWS subscribes for events using the given query and remote address as
// a subscriber, but does not verify responses (UNSAFE)!
// TODO: verify data
func (c *Client) SubscribeWS(ctx *rpctypes.Context, query string) (*coretypes.ResultSubscribe, error) {
func (c *Client) SubscribeWS(ctx context.Context, query string) (*coretypes.ResultSubscribe, error) {
bctx, bcancel := context.WithCancel(context.Background())
c.closers = append(c.closers, bcancel)
out, err := c.next.Subscribe(bctx, ctx.RemoteAddr(), query)
callInfo := rpctypes.GetCallInfo(ctx)
out, err := c.next.Subscribe(bctx, callInfo.RemoteAddr(), query)
if err != nil {
return nil, err
}
@@ -630,9 +631,9 @@ func (c *Client) SubscribeWS(ctx *rpctypes.Context, query string) (*coretypes.Re
case resultEvent := <-out:
// We should have a switch here that performs a validation
// depending on the event's type.
ctx.WSConn.TryWriteRPCResponse(bctx,
callInfo.WSConn.TryWriteRPCResponse(bctx,
rpctypes.NewRPCSuccessResponse(
rpctypes.JSONRPCStringID(fmt.Sprintf("%v#event", ctx.JSONReq.ID)),
rpctypes.JSONRPCStringID(fmt.Sprintf("%v#event", callInfo.RPCRequest.ID)),
resultEvent,
))
case <-bctx.Done():
@@ -646,8 +647,8 @@ func (c *Client) SubscribeWS(ctx *rpctypes.Context, query string) (*coretypes.Re
// UnsubscribeWS calls original client's Unsubscribe using remote address as a
// subscriber.
func (c *Client) UnsubscribeWS(ctx *rpctypes.Context, query string) (*coretypes.ResultUnsubscribe, error) {
err := c.next.Unsubscribe(context.Background(), ctx.RemoteAddr(), query)
func (c *Client) UnsubscribeWS(ctx context.Context, query string) (*coretypes.ResultUnsubscribe, error) {
err := c.next.Unsubscribe(context.Background(), rpctypes.GetCallInfo(ctx).RemoteAddr(), query)
if err != nil {
return nil, err
}
@@ -656,8 +657,8 @@ func (c *Client) UnsubscribeWS(ctx *rpctypes.Context, query string) (*coretypes.
// UnsubscribeAllWS calls original client's UnsubscribeAll using remote address
// as a subscriber.
func (c *Client) UnsubscribeAllWS(ctx *rpctypes.Context) (*coretypes.ResultUnsubscribe, error) {
err := c.next.UnsubscribeAll(context.Background(), ctx.RemoteAddr())
func (c *Client) UnsubscribeAllWS(ctx context.Context) (*coretypes.ResultUnsubscribe, error) {
err := c.next.UnsubscribeAll(context.Background(), rpctypes.GetCallInfo(ctx).RemoteAddr())
if err != nil {
return nil, err
}
+9 -8
View File
@@ -34,7 +34,7 @@ func TestLast_FirstLightBlockHeight(t *testing.T) {
assert.EqualValues(t, -1, height)
// 1 key
err = dbStore.SaveLightBlock(randLightBlock(ctx, int64(1)))
err = dbStore.SaveLightBlock(randLightBlock(ctx, t, int64(1)))
require.NoError(t, err)
height, err = dbStore.LastLightBlockHeight()
@@ -58,7 +58,7 @@ func Test_SaveLightBlock(t *testing.T) {
assert.Nil(t, h)
// 1 key
err = dbStore.SaveLightBlock(randLightBlock(ctx, 1))
err = dbStore.SaveLightBlock(randLightBlock(ctx, t, 1))
require.NoError(t, err)
size := dbStore.Size()
@@ -90,7 +90,7 @@ func Test_LightBlockBefore(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
err := dbStore.SaveLightBlock(randLightBlock(ctx, int64(2)))
err := dbStore.SaveLightBlock(randLightBlock(ctx, t, int64(2)))
require.NoError(t, err)
h, err := dbStore.LightBlockBefore(3)
@@ -115,7 +115,7 @@ func Test_Prune(t *testing.T) {
require.NoError(t, err)
// One header
err = dbStore.SaveLightBlock(randLightBlock(ctx, 2))
err = dbStore.SaveLightBlock(randLightBlock(ctx, t, 2))
require.NoError(t, err)
assert.EqualValues(t, 1, dbStore.Size())
@@ -130,7 +130,7 @@ func Test_Prune(t *testing.T) {
// Multiple headers
for i := 1; i <= 10; i++ {
err = dbStore.SaveLightBlock(randLightBlock(ctx, int64(i)))
err = dbStore.SaveLightBlock(randLightBlock(ctx, t, int64(i)))
require.NoError(t, err)
}
@@ -155,7 +155,7 @@ func Test_Concurrency(t *testing.T) {
go func(i int64) {
defer wg.Done()
err := dbStore.SaveLightBlock(randLightBlock(ctx, i))
err := dbStore.SaveLightBlock(randLightBlock(ctx, t, i))
require.NoError(t, err)
_, err = dbStore.LightBlock(i)
@@ -198,8 +198,9 @@ func Test_Concurrency(t *testing.T) {
wg.Wait()
}
func randLightBlock(ctx context.Context, height int64) *types.LightBlock {
vals, _ := factory.RandValidatorSet(ctx, 2, 1)
func randLightBlock(ctx context.Context, t *testing.T, height int64) *types.LightBlock {
t.Helper()
vals, _ := factory.RandValidatorSet(ctx, t, 2, 1)
return &types.LightBlock{
SignedHeader: &types.SignedHeader{
Header: &types.Header{
+43 -157
View File
@@ -63,23 +63,17 @@ type nodeImpl struct {
isListening bool
// services
eventBus *eventbus.EventBus // pub/sub for services
eventSinks []indexer.EventSink
stateStore sm.Store
blockStore *store.BlockStore // store the blockchain to disk
bcReactor service.Service // for block-syncing
mempoolReactor service.Service // for gossipping transactions
mempool mempool.Mempool
blockStore *store.BlockStore // store the blockchain to disk
stateSync bool // whether the node should state sync on startup
stateSyncReactor *statesync.Reactor // for hosting and restoring state sync snapshots
consensusReactor *consensus.Reactor // for participating in the consensus
pexReactor service.Service // for exchanging peer addresses
evidenceReactor service.Service
rpcListeners []net.Listener // rpc servers
shutdownOps closer
indexerService service.Service
rpcEnv *rpccore.Environment
prometheusSrv *http.Server
services []service.Service
rpcListeners []net.Listener // rpc servers
shutdownOps closer
rpcEnv *rpccore.Environment
prometheusSrv *http.Server
}
// newDefaultNode returns a Tendermint node with default settings for the
@@ -339,6 +333,7 @@ func makeNode(
peerManager.Subscribe(ctx),
blockSync && !stateSync,
nodeMetrics.consensus,
eventBus,
)
if err != nil {
return nil, combineCloseError(
@@ -372,6 +367,7 @@ func makeNode(
blockStore,
cfg.StateSync.TempDir,
nodeMetrics.statesync,
eventBus,
)
if err != nil {
return nil, combineCloseError(err, makeCloser(closers))
@@ -384,7 +380,6 @@ func makeNode(
return nil, combineCloseError(err, makeCloser(closers))
}
}
node := &nodeImpl{
config: cfg,
logger: logger,
@@ -396,19 +391,22 @@ func makeNode(
nodeInfo: nodeInfo,
nodeKey: nodeKey,
eventSinks: eventSinks,
services: []service.Service{
eventBus,
indexerService,
evReactor,
mpReactor,
csReactor,
bcReactor,
pexReactor,
},
stateStore: stateStore,
blockStore: blockStore,
bcReactor: bcReactor,
mempoolReactor: mpReactor,
mempool: mp,
consensusReactor: csReactor,
stateSyncReactor: stateSyncReactor,
stateSync: stateSync,
pexReactor: pexReactor,
evidenceReactor: evReactor,
indexerService: indexerService,
eventBus: eventBus,
eventSinks: eventSinks,
shutdownOps: makeCloser(closers),
@@ -442,76 +440,6 @@ func makeNode(
return node, nil
}
// makeSeedNode returns a new seed node, containing only p2p, pex reactor
func makeSeedNode(
ctx context.Context,
cfg *config.Config,
dbProvider config.DBProvider,
nodeKey types.NodeKey,
genesisDocProvider genesisDocProvider,
logger log.Logger,
) (service.Service, error) {
if !cfg.P2P.PexReactor {
return nil, errors.New("cannot run seed nodes with PEX disabled")
}
genDoc, err := genesisDocProvider()
if err != nil {
return nil, err
}
state, err := sm.MakeGenesisState(genDoc)
if err != nil {
return nil, err
}
nodeInfo, err := makeSeedNodeInfo(cfg, nodeKey, genDoc, state)
if err != nil {
return nil, err
}
// Setup Transport and Switch.
p2pMetrics := p2p.PrometheusMetrics(cfg.Instrumentation.Namespace, "chain_id", genDoc.ChainID)
peerManager, closer, err := createPeerManager(cfg, dbProvider, nodeKey.ID)
if err != nil {
return nil, combineCloseError(
fmt.Errorf("failed to create peer manager: %w", err),
closer)
}
router, err := createRouter(ctx, logger, p2pMetrics, nodeInfo, nodeKey,
peerManager, cfg, nil)
if err != nil {
return nil, combineCloseError(
fmt.Errorf("failed to create router: %w", err),
closer)
}
pexReactor, err := pex.NewReactor(ctx, logger, peerManager, router.OpenChannel, peerManager.Subscribe(ctx))
if err != nil {
return nil, combineCloseError(err, closer)
}
node := &nodeImpl{
config: cfg,
logger: logger,
genesisDoc: genDoc,
nodeInfo: nodeInfo,
nodeKey: nodeKey,
peerManager: peerManager,
router: router,
shutdownOps: closer,
pexReactor: pexReactor,
}
node.BaseService = *service.NewBaseService(logger, "SeedNode", node)
return node, nil
}
// OnStart starts the Node. It implements service.Service.
func (n *nodeImpl) OnStart(ctx context.Context) error {
if n.config.RPC.PprofListenAddress != "" {
@@ -546,7 +474,7 @@ func (n *nodeImpl) OnStart(ctx context.Context) error {
// Start the RPC server before the P2P server
// so we can eg. receive txs for the first block
if n.config.RPC.ListenAddress != "" && n.config.Mode != config.ModeSeed {
if n.config.RPC.ListenAddress != "" {
listeners, err := n.startRPC(ctx)
if err != nil {
return err
@@ -564,46 +492,25 @@ func (n *nodeImpl) OnStart(ctx context.Context) error {
}
n.isListening = true
if n.config.Mode != config.ModeSeed {
if err := n.bcReactor.Start(ctx); err != nil {
return err
}
for _, reactor := range n.services {
if err := reactor.Start(ctx); err != nil {
if errors.Is(err, service.ErrAlreadyStarted) {
continue
}
// Start the real consensus reactor separately since the switch uses the shim.
if err := n.consensusReactor.Start(ctx); err != nil {
return err
}
// Start the real state sync reactor separately since the switch uses the shim.
if err := n.stateSyncReactor.Start(ctx); err != nil {
return err
}
// Start the real mempool reactor separately since the switch uses the shim.
if err := n.mempoolReactor.Start(ctx); err != nil {
return err
}
// Start the real evidence reactor separately since the switch uses the shim.
if err := n.evidenceReactor.Start(ctx); err != nil {
return err
return fmt.Errorf("problem starting service '%T': %w ", reactor, err)
}
}
if n.config.P2P.PexReactor {
if err := n.pexReactor.Start(ctx); err != nil {
return err
}
if err := n.stateSyncReactor.Start(ctx); err != nil {
return err
}
// Run state sync
// TODO: We shouldn't run state sync if we already have state that has a
// LastBlockHeight that is not InitialHeight
if n.stateSync {
bcR, ok := n.bcReactor.(consensus.BlockSyncReactor)
if !ok {
return fmt.Errorf("this blockchain reactor does not support switching from state sync")
}
bcR := n.rpcEnv.BlockSyncReactor
// we need to get the genesis state to get parameters such as
state, err := sm.MakeGenesisState(n.genesisDoc)
@@ -616,7 +523,7 @@ func (n *nodeImpl) OnStart(ctx context.Context) error {
// At the beginning of the statesync start, we use the initialHeight as the event height
// because of the statesync doesn't have the concreate state height before fetched the snapshot.
d := types.EventDataStateSyncStatus{Complete: false, Height: state.InitialHeight}
if err := n.eventBus.PublishEventStateSyncStatus(ctx, d); err != nil {
if err := n.stateSyncReactor.PublishStatus(ctx, d); err != nil {
n.logger.Error("failed to emit the statesync start event", "err", err)
}
@@ -635,9 +542,9 @@ func (n *nodeImpl) OnStart(ctx context.Context) error {
return err
}
n.consensusReactor.SetStateSyncingMetrics(0)
n.rpcEnv.ConsensusReactor.SetStateSyncingMetrics(0)
if err := n.eventBus.PublishEventStateSyncStatus(ctx,
if err := n.stateSyncReactor.PublishStatus(ctx,
types.EventDataStateSyncStatus{
Complete: true,
Height: ssState.LastBlockHeight,
@@ -650,13 +557,13 @@ func (n *nodeImpl) OnStart(ctx context.Context) error {
// advancing reactors to be able to control which one of the three
// is running
// FIXME Very ugly to have these metrics bleed through here.
n.consensusReactor.SetBlockSyncingMetrics(1)
n.rpcEnv.ConsensusReactor.SetBlockSyncingMetrics(1)
if err := bcR.SwitchToBlockSync(ctx, ssState); err != nil {
n.logger.Error("failed to switch to block sync", "err", err)
return err
}
if err := n.eventBus.PublishEventBlockSyncStatus(ctx,
if err := bcR.PublishStatus(ctx,
types.EventDataBlockSyncStatus{
Complete: false,
Height: ssState.LastBlockHeight,
@@ -673,27 +580,17 @@ func (n *nodeImpl) OnStart(ctx context.Context) error {
func (n *nodeImpl) OnStop() {
n.logger.Info("Stopping Node")
if n.eventBus != nil {
n.eventBus.Wait()
}
if n.indexerService != nil {
n.indexerService.Wait()
}
for _, es := range n.eventSinks {
if err := es.Stop(); err != nil {
n.logger.Error("failed to stop event sink", "err", err)
}
}
if n.config.Mode != config.ModeSeed {
n.bcReactor.Wait()
n.consensusReactor.Wait()
n.stateSyncReactor.Wait()
n.mempoolReactor.Wait()
n.evidenceReactor.Wait()
for _, reactor := range n.services {
reactor.Wait()
}
n.pexReactor.Wait()
n.stateSyncReactor.Wait()
n.router.Wait()
n.isListening = false
@@ -769,16 +666,15 @@ func (n *nodeImpl) startRPC(ctx context.Context) ([]net.Listener, error) {
mux := http.NewServeMux()
rpcLogger := n.logger.With("module", "rpc-server")
wmLogger := rpcLogger.With("protocol", "websocket")
wm := rpcserver.NewWebsocketManager(routes,
wm := rpcserver.NewWebsocketManager(wmLogger, routes,
rpcserver.OnDisconnect(func(remoteAddr string) {
err := n.eventBus.UnsubscribeAll(context.Background(), remoteAddr)
err := n.rpcEnv.EventBus.UnsubscribeAll(context.Background(), remoteAddr)
if err != nil && err != tmpubsub.ErrSubscriptionNotFound {
wmLogger.Error("Failed to unsubscribe addr from events", "addr", remoteAddr, "err", err)
}
}),
rpcserver.ReadLimit(cfg.MaxBodyBytes),
)
wm.SetLogger(wmLogger)
mux.HandleFunc("/websocket", wm.WebsocketHandler)
rpcserver.RegisterRPCFuncs(mux, routes, rpcLogger)
listener, err := rpcserver.Listen(
@@ -866,19 +762,9 @@ func (n *nodeImpl) startPrometheusServer(ctx context.Context, addr string) *http
return srv
}
// ConsensusReactor returns the Node's ConsensusReactor.
func (n *nodeImpl) ConsensusReactor() *consensus.Reactor {
return n.consensusReactor
}
// Mempool returns the Node's mempool.
func (n *nodeImpl) Mempool() mempool.Mempool {
return n.mempool
}
// EventBus returns the Node's EventBus.
func (n *nodeImpl) EventBus() *eventbus.EventBus {
return n.eventBus
return n.rpcEnv.EventBus
}
// PrivValidator returns the Node's PrivValidator.
+2 -2
View File
@@ -556,7 +556,7 @@ func TestNodeNewSeedNode(t *testing.T) {
t.Cleanup(ns.Wait)
require.NoError(t, err)
n, ok := ns.(*nodeImpl)
n, ok := ns.(*seedNodeImpl)
require.True(t, ok)
err = n.Start(ctx)
@@ -717,7 +717,7 @@ func loadStatefromGenesis(ctx context.Context, t *testing.T) sm.State {
require.NoError(t, err)
require.True(t, loadedState.IsEmpty())
genDoc, _ := factory.RandGenesisDoc(ctx, cfg, 0, false, 10)
genDoc, _ := factory.RandGenesisDoc(ctx, t, cfg, 0, false, 10)
state, err := loadStateFromDBOrGenesisDocProvider(
stateStore,
+171
View File
@@ -0,0 +1,171 @@
package node
import (
"context"
"errors"
"fmt"
"net/http"
"time"
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/internal/p2p"
"github.com/tendermint/tendermint/internal/p2p/pex"
sm "github.com/tendermint/tendermint/internal/state"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/libs/service"
"github.com/tendermint/tendermint/libs/strings"
tmtime "github.com/tendermint/tendermint/libs/time"
"github.com/tendermint/tendermint/types"
)
type seedNodeImpl struct {
service.BaseService
logger log.Logger
// config
config *config.Config
genesisDoc *types.GenesisDoc // initial validator set
// network
peerManager *p2p.PeerManager
router *p2p.Router
nodeInfo types.NodeInfo
nodeKey types.NodeKey // our node privkey
isListening bool
// services
pexReactor service.Service // for exchanging peer addresses
shutdownOps closer
}
// makeSeedNode returns a new seed node, containing only p2p, pex reactor
func makeSeedNode(
ctx context.Context,
cfg *config.Config,
dbProvider config.DBProvider,
nodeKey types.NodeKey,
genesisDocProvider genesisDocProvider,
logger log.Logger,
) (service.Service, error) {
if !cfg.P2P.PexReactor {
return nil, errors.New("cannot run seed nodes with PEX disabled")
}
genDoc, err := genesisDocProvider()
if err != nil {
return nil, err
}
state, err := sm.MakeGenesisState(genDoc)
if err != nil {
return nil, err
}
nodeInfo, err := makeSeedNodeInfo(cfg, nodeKey, genDoc, state)
if err != nil {
return nil, err
}
// Setup Transport and Switch.
p2pMetrics := p2p.PrometheusMetrics(cfg.Instrumentation.Namespace, "chain_id", genDoc.ChainID)
peerManager, closer, err := createPeerManager(cfg, dbProvider, nodeKey.ID)
if err != nil {
return nil, combineCloseError(
fmt.Errorf("failed to create peer manager: %w", err),
closer)
}
router, err := createRouter(ctx, logger, p2pMetrics, nodeInfo, nodeKey,
peerManager, cfg, nil)
if err != nil {
return nil, combineCloseError(
fmt.Errorf("failed to create router: %w", err),
closer)
}
pexReactor, err := pex.NewReactor(ctx, logger, peerManager, router.OpenChannel, peerManager.Subscribe(ctx))
if err != nil {
return nil, combineCloseError(err, closer)
}
node := &seedNodeImpl{
config: cfg,
logger: logger,
genesisDoc: genDoc,
nodeInfo: nodeInfo,
nodeKey: nodeKey,
peerManager: peerManager,
router: router,
shutdownOps: closer,
pexReactor: pexReactor,
}
node.BaseService = *service.NewBaseService(logger, "SeedNode", node)
return node, nil
}
// OnStart starts the Seed Node. It implements service.Service.
func (n *seedNodeImpl) OnStart(ctx context.Context) error {
if n.config.RPC.PprofListenAddress != "" {
rpcCtx, rpcCancel := context.WithCancel(ctx)
srv := &http.Server{Addr: n.config.RPC.PprofListenAddress, Handler: nil}
go func() {
select {
case <-ctx.Done():
sctx, scancel := context.WithTimeout(context.Background(), time.Second)
defer scancel()
_ = srv.Shutdown(sctx)
case <-rpcCtx.Done():
}
}()
go func() {
n.logger.Info("Starting pprof server", "laddr", n.config.RPC.PprofListenAddress)
if err := srv.ListenAndServe(); err != nil {
n.logger.Error("pprof server error", "err", err)
rpcCancel()
}
}()
}
now := tmtime.Now()
genTime := n.genesisDoc.GenesisTime
if genTime.After(now) {
n.logger.Info("Genesis time is in the future. Sleeping until then...", "genTime", genTime)
time.Sleep(genTime.Sub(now))
}
// Start the transport.
if err := n.router.Start(ctx); err != nil {
return err
}
n.isListening = true
if n.config.P2P.PexReactor {
if err := n.pexReactor.Start(ctx); err != nil {
return err
}
}
return nil
}
// OnStop stops the Seed Node. It implements service.Service.
func (n *seedNodeImpl) OnStop() {
n.logger.Info("Stopping Node")
n.pexReactor.Wait()
n.router.Wait()
n.isListening = false
if err := n.shutdownOps(); err != nil {
if strings.TrimSpace(err.Error()) != "" {
n.logger.Error("problem shutting down additional services", "err", err)
}
}
}
+4 -3
View File
@@ -3,6 +3,7 @@ package privval
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"os"
@@ -72,7 +73,7 @@ func (pvKey FilePVKey) Save() error {
// FilePVLastSignState stores the mutable part of PrivValidator.
type FilePVLastSignState struct {
Height int64 `json:"height"`
Height int64 `json:"height,string"`
Round int32 `json:"round"`
Step int8 `json:"step"`
Signature []byte `json:"signature,omitempty"`
@@ -128,7 +129,7 @@ func (lss *FilePVLastSignState) Save() error {
if outFile == "" {
return errors.New("cannot save FilePVLastSignState: filePath not set")
}
jsonBytes, err := tmjson.MarshalIndent(lss, "", " ")
jsonBytes, err := json.MarshalIndent(lss, "", " ")
if err != nil {
return err
}
@@ -215,7 +216,7 @@ func loadFilePV(keyFilePath, stateFilePath string, loadState bool) (*FilePV, err
if err != nil {
return nil, err
}
err = tmjson.Unmarshal(stateJSONBytes, &pvState)
err = json.Unmarshal(stateJSONBytes, &pvState)
if err != nil {
return nil, fmt.Errorf("error reading PrivValidator state from %v: %w", stateFilePath, err)
}
+3 -2
View File
@@ -3,6 +3,7 @@ package privval
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"testing"
@@ -105,7 +106,7 @@ func TestUnmarshalValidatorState(t *testing.T) {
}`
val := FilePVLastSignState{}
err := tmjson.Unmarshal([]byte(serialized), &val)
err := json.Unmarshal([]byte(serialized), &val)
require.NoError(t, err)
// make sure the values match
@@ -114,7 +115,7 @@ func TestUnmarshalValidatorState(t *testing.T) {
assert.EqualValues(t, val.Step, 1)
// export it and make sure it is the same
out, err := tmjson.Marshal(val)
out, err := json.Marshal(val)
require.NoError(t, err)
assert.JSONEq(t, serialized, string(out))
}
+4 -4
View File
@@ -34,15 +34,15 @@ func (sc *RetrySignerClient) IsConnected() bool {
return sc.next.IsConnected()
}
func (sc *RetrySignerClient) WaitForConnection(maxWait time.Duration) error {
return sc.next.WaitForConnection(maxWait)
func (sc *RetrySignerClient) WaitForConnection(ctx context.Context, maxWait time.Duration) error {
return sc.next.WaitForConnection(ctx, maxWait)
}
//--------------------------------------------------------
// Implement PrivValidator
func (sc *RetrySignerClient) Ping() error {
return sc.next.Ping()
func (sc *RetrySignerClient) Ping(ctx context.Context) error {
return sc.next.Ping(ctx)
}
func (sc *RetrySignerClient) GetPubKey(ctx context.Context) (crypto.PubKey, error) {
+13 -8
View File
@@ -41,7 +41,12 @@ func NewSignerClient(ctx context.Context, endpoint *SignerListenerEndpoint, chai
// Close closes the underlying connection
func (sc *SignerClient) Close() error {
return sc.endpoint.Close()
err := sc.endpoint.Stop()
cerr := sc.endpoint.Close()
if err != nil {
return err
}
return cerr
}
// IsConnected indicates with the signer is connected to a remote signing service
@@ -50,16 +55,16 @@ func (sc *SignerClient) IsConnected() bool {
}
// WaitForConnection waits maxWait for a connection or returns a timeout error
func (sc *SignerClient) WaitForConnection(maxWait time.Duration) error {
return sc.endpoint.WaitForConnection(maxWait)
func (sc *SignerClient) WaitForConnection(ctx context.Context, maxWait time.Duration) error {
return sc.endpoint.WaitForConnection(ctx, maxWait)
}
//--------------------------------------------------------
// Implement PrivValidator
// Ping sends a ping request to the remote signer
func (sc *SignerClient) Ping() error {
response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.PingRequest{}))
func (sc *SignerClient) Ping(ctx context.Context) error {
response, err := sc.endpoint.SendRequest(ctx, mustWrapMsg(&privvalproto.PingRequest{}))
if err != nil {
sc.logger.Error("SignerClient::Ping", "err", err)
return nil
@@ -76,7 +81,7 @@ func (sc *SignerClient) Ping() error {
// GetPubKey retrieves a public key from a remote signer
// returns an error if client is not able to provide the key
func (sc *SignerClient) GetPubKey(ctx context.Context) (crypto.PubKey, error) {
response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.PubKeyRequest{ChainId: sc.chainID}))
response, err := sc.endpoint.SendRequest(ctx, mustWrapMsg(&privvalproto.PubKeyRequest{ChainId: sc.chainID}))
if err != nil {
return nil, fmt.Errorf("send: %w", err)
}
@@ -99,7 +104,7 @@ func (sc *SignerClient) GetPubKey(ctx context.Context) (crypto.PubKey, error) {
// SignVote requests a remote signer to sign a vote
func (sc *SignerClient) SignVote(ctx context.Context, chainID string, vote *tmproto.Vote) error {
response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.SignVoteRequest{Vote: vote, ChainId: chainID}))
response, err := sc.endpoint.SendRequest(ctx, mustWrapMsg(&privvalproto.SignVoteRequest{Vote: vote, ChainId: chainID}))
if err != nil {
return err
}
@@ -119,7 +124,7 @@ func (sc *SignerClient) SignVote(ctx context.Context, chainID string, vote *tmpr
// SignProposal requests a remote signer to sign a proposal
func (sc *SignerClient) SignProposal(ctx context.Context, chainID string, proposal *tmproto.Proposal) error {
response, err := sc.endpoint.SendRequest(mustWrapMsg(
response, err := sc.endpoint.SendRequest(ctx, mustWrapMsg(
&privvalproto.SignProposalRequest{Proposal: proposal, ChainId: chainID},
))
if err != nil {
+6 -3
View File
@@ -57,6 +57,7 @@ func getSignerTestCases(ctx context.Context, t *testing.T, logger log.Logger) []
signerServer: ss,
})
t.Cleanup(ss.Wait)
t.Cleanup(sc.endpoint.Wait)
}
return testCases
@@ -72,10 +73,14 @@ func TestSignerClose(t *testing.T) {
for _, tc := range getSignerTestCases(bctx, t, logger) {
t.Run(tc.name, func(t *testing.T) {
t.Cleanup(leaktest.Check(t))
defer tc.closer()
assert.NoError(t, tc.signerClient.Close())
assert.NoError(t, tc.signerServer.Stop())
t.Cleanup(tc.signerClient.endpoint.Wait)
t.Cleanup(tc.signerServer.Wait)
})
}
}
@@ -89,7 +94,7 @@ func TestSignerPing(t *testing.T) {
logger := log.NewTestingLogger(t)
for _, tc := range getSignerTestCases(ctx, t, logger) {
err := tc.signerClient.Ping()
err := tc.signerClient.Ping(ctx)
assert.NoError(t, err)
}
}
@@ -298,9 +303,7 @@ func TestSignerVoteKeepAlive(t *testing.T) {
// in this particular case, we use the dialer logger to ensure that
// test messages are properly interleaved in the test logs
tc.signerServer.endpoint.logger.Debug("TEST: Forced Wait -------------------------------------------------")
time.Sleep(testTimeoutReadWrite * 3)
tc.signerServer.endpoint.logger.Debug("TEST: Forced Wait DONE---------------------------------------------")
require.NoError(t, tc.mockPV.SignVote(ctx, tc.chainID, want.ToProto()))
require.NoError(t, tc.signerClient.SignVote(ctx, tc.chainID, have.ToProto()))

Some files were not shown because too many files have changed in this diff Show More