From 39c54f5f3440058bc93f9a31641b78cae83471db Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Fri, 6 Aug 2021 16:48:50 +0200 Subject: [PATCH] allow exchanging of consensus params --- internal/statesync/dispatcher.go | 1 + internal/statesync/reactor.go | 70 ++++++- internal/statesync/reactor_test.go | 19 +- internal/statesync/stateprovider.go | 231 ++++++++++++++++----- node/node.go | 1 + node/setup.go | 1 + proto/tendermint/statesync/message.go | 7 - proto/tendermint/statesync/message_test.go | 5 +- proto/tendermint/statesync/types.pb.go | 111 +++++----- proto/tendermint/statesync/types.proto | 3 +- test/e2e/networks/simple.toml | 10 +- test/e2e/runner/setup.go | 21 +- 12 files changed, 342 insertions(+), 138 deletions(-) diff --git a/internal/statesync/dispatcher.go b/internal/statesync/dispatcher.go index 584dfa7be..f8197118a 100644 --- a/internal/statesync/dispatcher.go +++ b/internal/statesync/dispatcher.go @@ -181,6 +181,7 @@ func (d *dispatcher) removePeer(peer types.NodeID) { } else { d.availablePeers.Remove(peer) } + delete(d.providers, peer) } // peerCount returns the amount of peers that the dispatcher is connected with diff --git a/internal/statesync/reactor.go b/internal/statesync/reactor.go index 9fd4da586..ea935f3b3 100644 --- a/internal/statesync/reactor.go +++ b/internal/statesync/reactor.go @@ -101,6 +101,10 @@ const ( // return a light block lightBlockResponseTimeout = 30 * time.Second + // consensusParamsResponseTimeout is the time the p2p state provider waits + // before performing a secondary call + consensusParamsResponseTimeout = 5 * time.Second + // maxLightBlockRequestRetries is the amount of retries acceptable before // the backfill process aborts maxLightBlockRequestRetries = 20 @@ -121,6 +125,7 @@ type Reactor struct { snapshotCh *p2p.Channel chunkCh *p2p.Channel blockCh *p2p.Channel + paramsCh *p2p.Channel peerUpdates *p2p.PeerUpdates closeCh chan struct{} @@ -141,7 +146,7 @@ func NewReactor( logger log.Logger, conn proxy.AppConnSnapshot, connQuery proxy.AppConnQuery, - snapshotCh, chunkCh, blockCh *p2p.Channel, + snapshotCh, chunkCh, blockCh, paramsCh *p2p.Channel, peerUpdates *p2p.PeerUpdates, stateStore sm.Store, blockStore *store.BlockStore, @@ -154,10 +159,10 @@ func NewReactor( snapshotCh: snapshotCh, chunkCh: chunkCh, blockCh: blockCh, + paramsCh: paramsCh, peerUpdates: peerUpdates, closeCh: make(chan struct{}), tempDir: tempDir, - dispatcher: newDispatcher(blockCh.Out, lightBlockResponseTimeout), stateStore: stateStore, blockStore: blockStore, } @@ -227,6 +232,8 @@ func (r *Reactor) Sync( return sm.State{}, errors.New("a state sync is already in progress") } + r.dispatcher = newDispatcher(r.blockCh.Out, lightBlockResponseTimeout) + to := light.TrustOptions{ Period: r.cfg.TrustPeriod, Height: r.cfg.TrustHeight, @@ -242,7 +249,7 @@ func (r *Reactor) Sync( // state provider needs at least two connected peers to initialize spLogger.Info("Generating P2P state provider") r.waitForEnoughPeers(ctx, 2) - stateProvider, err = NewP2PStateProvider(ctx, chainID, initialHeight, r.Dispatcher(), to, spLogger) + stateProvider, err = NewP2PStateProvider(ctx, chainID, initialHeight, r.dispatcher, to, r.paramsCh.Out, spLogger) if err != nil { return sm.State{}, err } @@ -476,12 +483,6 @@ func (r *Reactor) backfill( } } -// Dispatcher exposes the dispatcher so that a state provider can use it for -// light client verification -func (r *Reactor) Dispatcher() *dispatcher { //nolint:golint - return r.dispatcher -} - // handleSnapshotMessage handles envelopes sent from peers on the // SnapshotChannel. It returns an error only if the Envelope.Message is unknown // for this channel. This should never be called outside of handleMessage. @@ -677,6 +678,50 @@ func (r *Reactor) handleLightBlockMessage(envelope p2p.Envelope) error { return nil } +func (r *Reactor) handleParamsMessage(envelope p2p.Envelope) error { + switch msg := envelope.Message.(type) { + case *ssproto.ParamsRequest: + r.Logger.Info("received light block request", "height", msg.Height) + cp, err := r.stateStore.LoadConsensusParams(int64(msg.Height)) + if err != nil { + r.Logger.Error("failed to fetch requested consensus params", "err", err, "height", msg.Height) + return nil + } + + cpproto := cp.ToProto() + r.blockCh.Out <- p2p.Envelope{ + To: envelope.From, + Message: &ssproto.ParamsResponse{ + Height: msg.Height, + ConsensusParams: cpproto, + }, + } + + case *ssproto.ParamsResponse: + r.mtx.RLock() + defer r.mtx.RUnlock() + + if r.syncer == nil { + r.Logger.Debug("received unexpected params response; no state sync in progress", "peer", envelope.From) + return nil + } + + cp := types.ConsensusParamsFromProto(msg.ConsensusParams) + + if sp, ok := r.syncer.stateProvider.(*stateProviderP2P); ok { + select { + case sp.paramsRecvCh <- cp: + default: + } + } + + default: + return fmt.Errorf("received unknown message: %T", msg) + } + + return nil +} + // handleMessage handles an Envelope sent from a peer on a specific p2p Channel. // It will handle errors and any possible panics gracefully. A caller can handle // any error returned by sending a PeerError on the respective channel. @@ -704,6 +749,9 @@ func (r *Reactor) handleMessage(chID p2p.ChannelID, envelope p2p.Envelope) (err case LightBlockChannel: err = r.handleLightBlockMessage(envelope) + case ParamsChannel: + err = r.handleParamsMessage(envelope) + default: err = fmt.Errorf("unknown channel ID (%d) for envelope (%v)", chID, envelope) } @@ -729,6 +777,10 @@ func (r *Reactor) processBlockCh() { r.processCh(r.blockCh, "light block") } +func (r *Reactor) processParamsCh() { + r.processCh(r.paramsCh, "consensus params") +} + // processCh routes state sync messages to their respective handlers. Any error // encountered during message execution will result in a PeerError being sent on // the respective channel. When the reactor is stopped, we will catch the signal diff --git a/internal/statesync/reactor_test.go b/internal/statesync/reactor_test.go index dad391ce9..cdc7b5491 100644 --- a/internal/statesync/reactor_test.go +++ b/internal/statesync/reactor_test.go @@ -51,6 +51,11 @@ type reactorTestSuite struct { blockOutCh chan p2p.Envelope blockPeerErrCh chan p2p.PeerError + paramsChannel *p2p.Channel + paramsInCh chan p2p.Envelope + paramsOutCh chan p2p.Envelope + paramsPeerErrCh chan p2p.PeerError + peerUpdateCh chan p2p.PeerUpdate peerUpdates *p2p.PeerUpdates @@ -119,6 +124,14 @@ func setup( rts.blockPeerErrCh, ) + rts.paramsChannel = p2p.NewChannel( + ParamsChannel, + new(ssproto.Message), + rts.paramsInCh, + rts.paramsOutCh, + rts.paramsPeerErrCh, + ) + rts.stateStore = &smmocks.Store{} rts.blockStore = store.NewBlockStore(dbm.NewMemDB()) @@ -132,6 +145,7 @@ func setup( rts.snapshotChannel, rts.chunkChannel, rts.blockChannel, + rts.paramsChannel, rts.peerUpdates, rts.stateStore, rts.blockStore, @@ -388,7 +402,7 @@ func TestReactor_Dispatcher(t *testing.T) { chain := buildLightBlockChain(t, 1, 10, time.Now()) go handleLightBlockRequests(t, chain, rts.blockOutCh, rts.blockInCh, closeCh, 0) - dispatcher := rts.reactor.Dispatcher() + dispatcher := rts.reactor.dispatcher providers := dispatcher.Providers(factory.DefaultTestChainID) require.Len(t, providers, 2) require.Equal(t, 2, dispatcher.peerCount()) @@ -438,7 +452,8 @@ func TestReactor_Dispatcher(t *testing.T) { Hash: lb.Hash(), } - p2pStateProvider, err := NewP2PStateProvider(ctx, "testchain", 1, rts.reactor.Dispatcher(), to, log.TestingLogger()) + // TODO: move into a separate test + p2pStateProvider, err := NewP2PStateProvider(ctx, "testchain", 1, rts.reactor.dispatcher, to, rts.paramsOutCh, log.TestingLogger()) require.NoError(t, err) appHash, err := p2pStateProvider.AppHash(ctx, 5) diff --git a/internal/statesync/stateprovider.go b/internal/statesync/stateprovider.go index 749321fbd..b6a8d8b4c 100644 --- a/internal/statesync/stateprovider.go +++ b/internal/statesync/stateprovider.go @@ -1,7 +1,9 @@ package statesync import ( + "bytes" "context" + "errors" "fmt" "strings" "time" @@ -9,12 +11,14 @@ import ( dbm "github.com/tendermint/tm-db" tmsync "github.com/tendermint/tendermint/internal/libs/sync" + "github.com/tendermint/tendermint/internal/p2p" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/light" lightprovider "github.com/tendermint/tendermint/light/provider" lighthttp "github.com/tendermint/tendermint/light/provider/http" lightrpc "github.com/tendermint/tendermint/light/rpc" lightdb "github.com/tendermint/tendermint/light/store/db" + ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync" rpchttp "github.com/tendermint/tendermint/rpc/client/http" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" @@ -24,7 +28,8 @@ import ( //go:generate ../../scripts/mockery_generate.sh StateProvider // StateProvider is a provider of trusted state data for bootstrapping a node. This refers -// to the state.State object, not the state machine. +// to the state.State object, not the state machine. There are two implementations. One +// uses the P2P layer and the other uses the RPC layer. Both use light client verification. type StateProvider interface { // AppHash returns the app hash after the given height has been committed. AppHash(ctx context.Context, height uint64) ([]byte, error) @@ -34,11 +39,7 @@ type StateProvider interface { State(ctx context.Context, height uint64) (sm.State, error) } -// stateProvider implements the above interface using a light client to fetch and -// verify the AppHash, Commit, and Tendermint State from trusted data in order -// to bootstrap a node. The stateProvider can either be initated using RPC or -// P2P Providers. -type stateProvider struct { +type stateProviderRPC struct { tmsync.Mutex // light.Client is not concurrency-safe lc *light.Client initialHeight int64 @@ -77,48 +78,15 @@ func NewRPCStateProvider( if err != nil { return nil, err } - return &stateProvider{ + return &stateProviderRPC{ lc: lc, initialHeight: initialHeight, providers: providerRemotes, }, nil } -// NewP2PStateProvider creates a light client state -// provider but uses a dispatcher connected to the P2P layer -func NewP2PStateProvider( - ctx context.Context, - chainID string, - initialHeight int64, - dispatcher *dispatcher, - trustOptions light.TrustOptions, - logger log.Logger, -) (StateProvider, error) { - providers := dispatcher.Providers(chainID) - if len(providers) < 2 { - return nil, fmt.Errorf("at least 2 peers are required, got %d", len(providers)) - } - - providersMap := make(map[lightprovider.Provider]string) - for _, p := range providers { - providersMap[p] = p.(*blockProvider).String() - } - - lc, err := light.NewClient(ctx, chainID, trustOptions, providers[0], providers[1:], - lightdb.New(dbm.NewMemDB()), light.Logger(logger)) - if err != nil { - return nil, err - } - - return &stateProvider{ - lc: lc, - initialHeight: initialHeight, - providers: providersMap, - }, nil -} - // AppHash implements StateProvider. -func (s *stateProvider) AppHash(ctx context.Context, height uint64) ([]byte, error) { +func (s *stateProviderRPC) AppHash(ctx context.Context, height uint64) ([]byte, error) { s.Lock() defer s.Unlock() @@ -127,14 +95,10 @@ func (s *stateProvider) AppHash(ctx context.Context, height uint64) ([]byte, err if err != nil { return nil, err } + // We also try to fetch the blocks at H+2, since we need these // when building the state while restoring the snapshot. This avoids the race // condition where we try to restore a snapshot before H+2 exists. - // - // FIXME This is a hack, since we can't add new methods to the interface without - // breaking it. We should instead have a Has(ctx, height) method which checks - // that the state provider has access to the necessary data for the height. - // We piggyback on AppHash() since it's called when adding snapshots to the pool. _, err = s.lc.VerifyLightBlockAtHeight(ctx, int64(height+2), time.Now()) if err != nil { return nil, err @@ -143,7 +107,7 @@ func (s *stateProvider) AppHash(ctx context.Context, height uint64) ([]byte, err } // Commit implements StateProvider. -func (s *stateProvider) Commit(ctx context.Context, height uint64) (*types.Commit, error) { +func (s *stateProviderRPC) Commit(ctx context.Context, height uint64) (*types.Commit, error) { s.Lock() defer s.Unlock() header, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height), time.Now()) @@ -154,7 +118,7 @@ func (s *stateProvider) Commit(ctx context.Context, height uint64) (*types.Commi } // State implements StateProvider. -func (s *stateProvider) State(ctx context.Context, height uint64) (sm.State, error) { +func (s *stateProviderRPC) State(ctx context.Context, height uint64) (sm.State, error) { s.Lock() defer s.Unlock() @@ -233,3 +197,174 @@ func rpcClient(server string) (*rpchttp.HTTP, error) { } return c, nil } + +type stateProviderP2P struct { + tmsync.Mutex // light.Client is not concurrency-safe + lc *light.Client + dispatcher *dispatcher + initialHeight int64 + paramsSendCh chan<- p2p.Envelope + paramsRecvCh chan types.ConsensusParams +} + +// NewP2PStateProvider creates a light client state +// provider but uses a dispatcher connected to the P2P layer +func NewP2PStateProvider( + ctx context.Context, + chainID string, + initialHeight int64, + dispatcher *dispatcher, + trustOptions light.TrustOptions, + paramsSendCh chan<- p2p.Envelope, + logger log.Logger, +) (StateProvider, error) { + providers := dispatcher.Providers(chainID) + if len(providers) < 2 { + return nil, fmt.Errorf("at least 2 peers are required, got %d", len(providers)) + } + + lc, err := light.NewClient(ctx, chainID, trustOptions, providers[0], providers[1:], + lightdb.New(dbm.NewMemDB()), light.Logger(logger)) + if err != nil { + return nil, err + } + + return &stateProviderP2P{ + lc: lc, + initialHeight: initialHeight, + dispatcher: dispatcher, + paramsSendCh: paramsSendCh, + paramsRecvCh: make(chan types.ConsensusParams), + }, nil +} + +// AppHash implements StateProvider. +func (s *stateProviderP2P) AppHash(ctx context.Context, height uint64) ([]byte, error) { + s.Lock() + defer s.Unlock() + + // We have to fetch the next height, which contains the app hash for the previous height. + header, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+1), time.Now()) + if err != nil { + return nil, err + } + + // We also try to fetch the blocks at H+2, since we need these + // when building the state while restoring the snapshot. This avoids the race + // condition where we try to restore a snapshot before H+2 exists. + _, err = s.lc.VerifyLightBlockAtHeight(ctx, int64(height+2), time.Now()) + if err != nil { + return nil, err + } + return header.AppHash, nil +} + +// Commit implements StateProvider. +func (s *stateProviderP2P) Commit(ctx context.Context, height uint64) (*types.Commit, error) { + s.Lock() + defer s.Unlock() + header, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height), time.Now()) + if err != nil { + return nil, err + } + return header.Commit, nil +} + +// State implements StateProvider. +func (s *stateProviderP2P) State(ctx context.Context, height uint64) (sm.State, error) { + s.Lock() + defer s.Unlock() + + state := sm.State{ + ChainID: s.lc.ChainID(), + InitialHeight: s.initialHeight, + } + if state.InitialHeight == 0 { + state.InitialHeight = 1 + } + + // The snapshot height maps onto the state heights as follows: + // + // height: last block, i.e. the snapshotted height + // height+1: current block, i.e. the first block we'll process after the snapshot + // height+2: next block, i.e. the second block after the snapshot + // + // We need to fetch the NextValidators from height+2 because if the application changed + // the validator set at the snapshot height then this only takes effect at height+2. + lastLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height), time.Now()) + if err != nil { + return sm.State{}, err + } + currentLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+1), time.Now()) + if err != nil { + return sm.State{}, err + } + nextLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+2), time.Now()) + if err != nil { + return sm.State{}, err + } + + state.Version = sm.Version{ + Consensus: currentLightBlock.Version, + Software: version.TMVersion, + } + state.LastBlockHeight = lastLightBlock.Height + state.LastBlockTime = lastLightBlock.Time + state.LastBlockID = lastLightBlock.Commit.BlockID + state.AppHash = currentLightBlock.AppHash + state.LastResultsHash = currentLightBlock.LastResultsHash + state.LastValidators = lastLightBlock.ValidatorSet + state.Validators = currentLightBlock.ValidatorSet + state.NextValidators = nextLightBlock.ValidatorSet + state.LastHeightValidatorsChanged = nextLightBlock.Height + + // We'll also need to fetch consensus params via P2P. + state.ConsensusParams, err = s.consensusParams(ctx, currentLightBlock.Height) + if err != nil { + return sm.State{}, err + } + // validate the consensus params + if !bytes.Equal(nextLightBlock.ConsensusHash, state.ConsensusParams.HashConsensusParams()) { + return sm.State{}, fmt.Errorf("consensus params hash mismatch at height %d. Expected %v, got %v", + currentLightBlock.Height, nextLightBlock.ConsensusHash, state.ConsensusParams.HashConsensusParams()) + } + // set the last height changed to the current height + state.LastHeightConsensusParamsChanged = currentLightBlock.Height + + return state, nil +} + +func (s *stateProviderP2P) addPeer(peer types.NodeID) { + provider := s.dispatcher.CreateProvider(peer, s.lc.ChainID()) + if len(s.lc.Witnesses()) < 6 { + s.lc.AddProvider(provider) + } +} + +func (s *stateProviderP2P) consensusParams(ctx context.Context, height int64) (types.ConsensusParams, error) { + providers := s.lc.Witnesses() + for _, provider := range providers { + p, ok := provider.(*blockProvider) + if !ok { + panic("expected p2p state provider to use p2p block providers") + } + peer, err := types.NewNodeID(p.String()) + if err != nil { + return types.ConsensusParams{}, fmt.Errorf("invalid provider node id: %w", err) + } + s.paramsSendCh <- p2p.Envelope{ + To: peer, + Message: &ssproto.ParamsRequest{ + Height: uint64(height), + }, + } + select { + // if we get no response from this provider we move on to the next one + case <-time.After(consensusParamsResponseTimeout): + continue + case params := <-s.paramsRecvCh: + return params, nil + } + } + return types.ConsensusParams{}, errors.New("unable to fetch consensus params from connected providers") +} diff --git a/node/node.go b/node/node.go index c377d7e9f..53bb38bf0 100644 --- a/node/node.go +++ b/node/node.go @@ -340,6 +340,7 @@ func makeNode(config *cfg.Config, channels[statesync.SnapshotChannel], channels[statesync.ChunkChannel], channels[statesync.LightBlockChannel], + channels[statesync.ParamsChannel], peerUpdates, stateStore, blockStore, diff --git a/node/setup.go b/node/setup.go index af48fb382..a128568ce 100644 --- a/node/setup.go +++ b/node/setup.go @@ -756,6 +756,7 @@ func makeNodeInfo( byte(statesync.SnapshotChannel), byte(statesync.ChunkChannel), byte(statesync.LightBlockChannel), + byte(statesync.ParamsChannel), }, Moniker: config.Moniker, Other: types.NodeInfoOther{ diff --git a/proto/tendermint/statesync/message.go b/proto/tendermint/statesync/message.go index a60e63090..992cd7525 100644 --- a/proto/tendermint/statesync/message.go +++ b/proto/tendermint/statesync/message.go @@ -5,8 +5,6 @@ import ( fmt "fmt" proto "github.com/gogo/protobuf/proto" - - "github.com/tendermint/tendermint/types" ) // Wrap implements the p2p Wrapper interface and wraps a state sync proto message. @@ -131,11 +129,6 @@ func (m *Message) Validate() error { return errors.New("height cannot be 0") } - if resp.ConsensusParams != nil { - cp := types.ConsensusParamsFromProto(*resp.ConsensusParams) - return cp.ValidateConsensusParams() - } - default: return fmt.Errorf("unknown message type: %T", msg) } diff --git a/proto/tendermint/statesync/message_test.go b/proto/tendermint/statesync/message_test.go index 50f315c5a..40428ec07 100644 --- a/proto/tendermint/statesync/message_test.go +++ b/proto/tendermint/statesync/message_test.go @@ -9,6 +9,7 @@ import ( ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/tendermint/tendermint/types" ) func TestValidateMsg(t *testing.T) { @@ -186,9 +187,9 @@ func TestStateSyncVectors(t *testing.T) { "ParamsResponse", &ssproto.ParamsResponse{ Height: 9001, - ConsensusParams: &tmproto.ConsensusParams{}, + ConsensusParams: types.DefaultConsensusParams().ToProto(), }, - "420508a9461200", + "423408a946122f0a10088080c00a10ffffffffffffffffff01120e08a08d0612040880c60a188080401a090a07656432353531392200", }, } diff --git a/proto/tendermint/statesync/types.pb.go b/proto/tendermint/statesync/types.pb.go index cdb40eb86..5541c2803 100644 --- a/proto/tendermint/statesync/types.pb.go +++ b/proto/tendermint/statesync/types.pb.go @@ -5,6 +5,7 @@ package statesync import ( fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" types "github.com/tendermint/tendermint/proto/tendermint/types" io "io" @@ -567,8 +568,8 @@ func (m *ParamsRequest) GetHeight() uint64 { } type ParamsResponse struct { - Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - ConsensusParams *types.ConsensusParams `protobuf:"bytes,2,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + ConsensusParams types.ConsensusParams `protobuf:"bytes,2,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` } func (m *ParamsResponse) Reset() { *m = ParamsResponse{} } @@ -611,11 +612,11 @@ func (m *ParamsResponse) GetHeight() uint64 { return 0 } -func (m *ParamsResponse) GetConsensusParams() *types.ConsensusParams { +func (m *ParamsResponse) GetConsensusParams() types.ConsensusParams { if m != nil { return m.ConsensusParams } - return nil + return types.ConsensusParams{} } func init() { @@ -633,43 +634,44 @@ func init() { func init() { proto.RegisterFile("tendermint/statesync/types.proto", fileDescriptor_a1c2869546ca7914) } var fileDescriptor_a1c2869546ca7914 = []byte{ - // 573 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0x4f, 0x8b, 0xd3, 0x5e, - 0x14, 0x6d, 0x7e, 0xd3, 0x7f, 0xdc, 0x69, 0x3a, 0xed, 0xfb, 0x15, 0x29, 0x65, 0x0c, 0x63, 0x14, - 0x67, 0x40, 0x68, 0x41, 0x97, 0xe2, 0xa6, 0xb3, 0x19, 0xa1, 0xa2, 0x64, 0x1c, 0x50, 0x11, 0xca, - 0x6b, 0xfa, 0x6c, 0x82, 0xcd, 0x1f, 0x7b, 0x5f, 0xc4, 0xf9, 0x00, 0xae, 0xdc, 0xf8, 0x59, 0xfc, - 0x14, 0x2e, 0x67, 0xe9, 0x52, 0xda, 0x2f, 0x22, 0x79, 0x79, 0x4d, 0x5e, 0x9a, 0xb6, 0x83, 0xe0, - 0x2e, 0xf7, 0xbc, 0x73, 0x4f, 0xce, 0x7d, 0x39, 0xdc, 0xc0, 0x09, 0x67, 0xfe, 0x94, 0x2d, 0x3c, - 0xd7, 0xe7, 0x03, 0xe4, 0x94, 0x33, 0xbc, 0xf6, 0xed, 0x01, 0xbf, 0x0e, 0x19, 0xf6, 0xc3, 0x45, - 0xc0, 0x03, 0xd2, 0xc9, 0x18, 0xfd, 0x94, 0xd1, 0x3b, 0x56, 0xfa, 0x04, 0x5b, 0xed, 0xe9, 0xdd, - 0x2d, 0x9c, 0x86, 0x74, 0x41, 0x3d, 0x79, 0x6c, 0xfe, 0xa8, 0x40, 0xed, 0x05, 0x43, 0xa4, 0x33, - 0x46, 0xae, 0xa0, 0x8d, 0x3e, 0x0d, 0xd1, 0x09, 0x38, 0x8e, 0x17, 0xec, 0x53, 0xc4, 0x90, 0x77, - 0xb5, 0x13, 0xed, 0xec, 0xf0, 0xf1, 0xc3, 0xfe, 0xb6, 0x57, 0xf7, 0x2f, 0xd7, 0x74, 0x2b, 0x61, - 0x5f, 0x94, 0xac, 0x16, 0x6e, 0x60, 0xe4, 0x0d, 0x10, 0x55, 0x16, 0xc3, 0xc0, 0x47, 0xd6, 0xfd, - 0x4f, 0xe8, 0x9e, 0xde, 0xaa, 0x9b, 0xd0, 0x2f, 0x4a, 0x56, 0x1b, 0x37, 0x41, 0xf2, 0x1c, 0x74, - 0xdb, 0x89, 0xfc, 0x8f, 0xa9, 0xd9, 0x03, 0x21, 0x6a, 0x6e, 0x17, 0x3d, 0x8f, 0xa9, 0x99, 0xd1, - 0x86, 0xad, 0xd4, 0x64, 0x04, 0xcd, 0xb5, 0x94, 0x34, 0x58, 0x16, 0x5a, 0xf7, 0xf7, 0x6a, 0xa5, - 0xe6, 0x74, 0x5b, 0x05, 0xc8, 0x5b, 0xf8, 0x7f, 0xee, 0xce, 0x1c, 0x3e, 0x9e, 0xcc, 0x03, 0x3b, - 0xb3, 0x57, 0xd9, 0x37, 0xf3, 0x28, 0x6e, 0x18, 0xc6, 0xfc, 0xcc, 0x63, 0x7b, 0xbe, 0x09, 0x92, - 0xf7, 0xd0, 0xc9, 0x4b, 0x4b, 0xbb, 0x55, 0xa1, 0x7d, 0x76, 0xbb, 0x76, 0xea, 0x99, 0xcc, 0x0b, - 0x68, 0x7c, 0x0d, 0x49, 0x3c, 0x52, 0xcf, 0xb5, 0x7d, 0xd7, 0xf0, 0x4a, 0x70, 0x33, 0xbf, 0x7a, - 0xa8, 0x02, 0xe4, 0x25, 0x1c, 0xa5, 0x6a, 0xd2, 0x66, 0x5d, 0xc8, 0x3d, 0xd8, 0x2f, 0x97, 0x5a, - 0x6c, 0x86, 0x39, 0x64, 0x58, 0x81, 0x03, 0x8c, 0x3c, 0x93, 0x40, 0x6b, 0x33, 0x79, 0xe6, 0x37, - 0x0d, 0xda, 0x85, 0xd8, 0x90, 0x3b, 0x50, 0x75, 0x58, 0x3c, 0xa6, 0xc8, 0x71, 0xd9, 0x92, 0x55, - 0x8c, 0x7f, 0x08, 0x16, 0x1e, 0xe5, 0x22, 0x87, 0xba, 0x25, 0xab, 0x18, 0x17, 0x5f, 0x12, 0x45, - 0x94, 0x74, 0x4b, 0x56, 0x84, 0x40, 0xd9, 0xa1, 0xe8, 0x88, 0x50, 0x34, 0x2c, 0xf1, 0x4c, 0x7a, - 0x50, 0xf7, 0x18, 0xa7, 0x53, 0xca, 0xa9, 0xf8, 0xb2, 0x0d, 0x2b, 0xad, 0xcd, 0xd7, 0xd0, 0x50, - 0xe3, 0xf6, 0xd7, 0x3e, 0x3a, 0x50, 0x71, 0xfd, 0x29, 0xfb, 0x22, 0x6d, 0x24, 0x85, 0xf9, 0x55, - 0x03, 0x3d, 0x97, 0xbc, 0x7f, 0xa3, 0x1b, 0xa3, 0x62, 0x4e, 0x39, 0x5e, 0x52, 0x90, 0x2e, 0xd4, - 0x3c, 0x17, 0xd1, 0xf5, 0x67, 0x62, 0xbc, 0xba, 0xb5, 0x2e, 0xcd, 0x47, 0xd0, 0x2e, 0xa4, 0x75, - 0x97, 0x15, 0xf3, 0x12, 0x48, 0x31, 0x7e, 0xe4, 0x19, 0x1c, 0x2a, 0x31, 0x96, 0x5b, 0xe6, 0x58, - 0x8d, 0x45, 0xb2, 0xc4, 0x94, 0x56, 0xc8, 0xf2, 0x6a, 0x9e, 0x82, 0x9e, 0xcb, 0xde, 0xce, 0xb7, - 0x7f, 0x86, 0x66, 0x3e, 0x55, 0x3b, 0xaf, 0x6c, 0x04, 0x2d, 0x3b, 0x26, 0xf8, 0x18, 0xe1, 0x38, - 0xc9, 0x9d, 0x5c, 0x52, 0xf7, 0x8a, 0xb6, 0xce, 0xd7, 0x4c, 0x29, 0x7e, 0x64, 0xe7, 0x81, 0xe1, - 0xd5, 0xcf, 0xa5, 0xa1, 0xdd, 0x2c, 0x0d, 0xed, 0xf7, 0xd2, 0xd0, 0xbe, 0xaf, 0x8c, 0xd2, 0xcd, - 0xca, 0x28, 0xfd, 0x5a, 0x19, 0xa5, 0x77, 0x4f, 0x67, 0x2e, 0x77, 0xa2, 0x49, 0xdf, 0x0e, 0xbc, - 0x81, 0xba, 0x9b, 0xb3, 0x47, 0xb1, 0x99, 0x07, 0xdb, 0xfe, 0x06, 0x93, 0xaa, 0x38, 0x7b, 0xf2, - 0x27, 0x00, 0x00, 0xff, 0xff, 0x4d, 0xf6, 0x0e, 0xb3, 0x2c, 0x06, 0x00, 0x00, + // 589 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0x4f, 0x8b, 0xd3, 0x40, + 0x18, 0xc6, 0x13, 0xb7, 0xdd, 0x96, 0x77, 0x9b, 0x6e, 0x3b, 0x16, 0x29, 0x65, 0x8d, 0x6b, 0x14, + 0x77, 0x41, 0x68, 0x41, 0x8f, 0xe2, 0xa5, 0x7b, 0x59, 0x61, 0x45, 0x99, 0x75, 0x41, 0x45, 0x28, + 0x69, 0x3a, 0x26, 0xc1, 0xe6, 0x8f, 0x7d, 0xa7, 0xe0, 0x82, 0x57, 0x4f, 0x5e, 0xfc, 0x2c, 0x7e, + 0x8a, 0x3d, 0xee, 0xd1, 0x93, 0x48, 0xfb, 0x45, 0x24, 0x93, 0x69, 0x32, 0x6d, 0xda, 0x2e, 0x82, + 0xb7, 0xbc, 0xcf, 0x3c, 0xf9, 0xf5, 0x99, 0xc9, 0xc3, 0x14, 0x0e, 0x39, 0x0b, 0x47, 0x6c, 0x12, + 0xf8, 0x21, 0xef, 0x21, 0xb7, 0x39, 0xc3, 0xcb, 0xd0, 0xe9, 0xf1, 0xcb, 0x98, 0x61, 0x37, 0x9e, + 0x44, 0x3c, 0x22, 0xad, 0xdc, 0xd1, 0xcd, 0x1c, 0x9d, 0x96, 0x1b, 0xb9, 0x91, 0x30, 0xf4, 0x92, + 0xa7, 0xd4, 0xdb, 0x39, 0x50, 0x68, 0x82, 0xa1, 0x92, 0x3a, 0x77, 0x0b, 0xab, 0xb1, 0x3d, 0xb1, + 0x03, 0xb9, 0x6c, 0xfd, 0x2c, 0x43, 0xe5, 0x25, 0x43, 0xb4, 0x5d, 0x46, 0x2e, 0xa0, 0x89, 0xa1, + 0x1d, 0xa3, 0x17, 0x71, 0x1c, 0x4c, 0xd8, 0xe7, 0x29, 0x43, 0xde, 0xd6, 0x0f, 0xf5, 0xe3, 0xbd, + 0x27, 0x8f, 0xba, 0xeb, 0x02, 0x75, 0xcf, 0x17, 0x76, 0x9a, 0xba, 0x4f, 0x35, 0xda, 0xc0, 0x15, + 0x8d, 0xbc, 0x05, 0xa2, 0x62, 0x31, 0x8e, 0x42, 0x64, 0xed, 0x5b, 0x82, 0x7b, 0x74, 0x23, 0x37, + 0xb5, 0x9f, 0x6a, 0xb4, 0x89, 0xab, 0x22, 0x79, 0x01, 0x86, 0xe3, 0x4d, 0xc3, 0x4f, 0x59, 0xd8, + 0x1d, 0x01, 0xb5, 0xd6, 0x43, 0x4f, 0x12, 0x6b, 0x1e, 0xb4, 0xe6, 0x28, 0x33, 0x39, 0x83, 0xfa, + 0x02, 0x25, 0x03, 0x96, 0x04, 0xeb, 0xc1, 0x56, 0x56, 0x16, 0xce, 0x70, 0x54, 0x81, 0xbc, 0x83, + 0xdb, 0x63, 0xdf, 0xf5, 0xf8, 0x60, 0x38, 0x8e, 0x9c, 0x3c, 0x5e, 0x79, 0xdb, 0x9e, 0xcf, 0x92, + 0x17, 0xfa, 0x89, 0x3f, 0xcf, 0xd8, 0x1c, 0xaf, 0x8a, 0xe4, 0x03, 0xb4, 0x96, 0xd1, 0x32, 0xee, + 0xae, 0x60, 0x1f, 0xdf, 0xcc, 0xce, 0x32, 0x93, 0x71, 0x41, 0x4d, 0x8e, 0x21, 0xad, 0x47, 0x96, + 0xb9, 0xb2, 0xed, 0x18, 0x5e, 0x0b, 0x6f, 0x9e, 0xd7, 0x88, 0x55, 0x81, 0xbc, 0x82, 0xfd, 0x8c, + 0x26, 0x63, 0x56, 0x05, 0xee, 0xe1, 0x76, 0x5c, 0x16, 0xb1, 0x1e, 0x2f, 0x29, 0xfd, 0x32, 0xec, + 0xe0, 0x34, 0xb0, 0x08, 0x34, 0x56, 0x9b, 0x67, 0x7d, 0xd7, 0xa1, 0x59, 0xa8, 0x0d, 0xb9, 0x03, + 0xbb, 0x1e, 0x4b, 0xb6, 0x29, 0x7a, 0x5c, 0xa2, 0x72, 0x4a, 0xf4, 0x8f, 0xd1, 0x24, 0xb0, 0xb9, + 0xe8, 0xa1, 0x41, 0xe5, 0x94, 0xe8, 0xe2, 0x4b, 0xa2, 0xa8, 0x92, 0x41, 0xe5, 0x44, 0x08, 0x94, + 0x3c, 0x1b, 0x3d, 0x51, 0x8a, 0x1a, 0x15, 0xcf, 0xa4, 0x03, 0xd5, 0x80, 0x71, 0x7b, 0x64, 0x73, + 0x5b, 0x7c, 0xd9, 0x1a, 0xcd, 0x66, 0xeb, 0x0d, 0xd4, 0xd4, 0xba, 0xfd, 0x73, 0x8e, 0x16, 0x94, + 0xfd, 0x70, 0xc4, 0xbe, 0xc8, 0x18, 0xe9, 0x60, 0x7d, 0xd3, 0xc1, 0x58, 0x6a, 0xde, 0xff, 0xe1, + 0x26, 0xaa, 0xd8, 0xa7, 0xdc, 0x5e, 0x3a, 0x90, 0x36, 0x54, 0x02, 0x1f, 0xd1, 0x0f, 0x5d, 0xb1, + 0xbd, 0x2a, 0x5d, 0x8c, 0xd6, 0x63, 0x68, 0x16, 0xda, 0xba, 0x29, 0x8a, 0x75, 0x0e, 0xa4, 0x58, + 0x3f, 0xf2, 0x1c, 0xf6, 0x94, 0x1a, 0xcb, 0x5b, 0xe6, 0x40, 0xad, 0x45, 0x7a, 0x89, 0x29, 0xaf, + 0x42, 0xde, 0x57, 0xeb, 0x08, 0x8c, 0xa5, 0xee, 0x6d, 0xfc, 0xf5, 0xaf, 0x50, 0x5f, 0x6e, 0xd5, + 0xc6, 0x23, 0xa3, 0xd0, 0x70, 0x12, 0x43, 0x88, 0x53, 0x1c, 0xa4, 0xbd, 0x93, 0x97, 0xd4, 0xfd, + 0x62, 0xac, 0x93, 0x85, 0x33, 0x85, 0xf7, 0x4b, 0x57, 0xbf, 0xef, 0x69, 0x74, 0xdf, 0x59, 0x91, + 0x2f, 0xae, 0x66, 0xa6, 0x7e, 0x3d, 0x33, 0xf5, 0x3f, 0x33, 0x53, 0xff, 0x31, 0x37, 0xb5, 0xeb, + 0xb9, 0xa9, 0xfd, 0x9a, 0x9b, 0xda, 0xfb, 0x67, 0xae, 0xcf, 0xbd, 0xe9, 0xb0, 0xeb, 0x44, 0x41, + 0x4f, 0xbd, 0xa1, 0xf3, 0xc7, 0xf4, 0x9e, 0x5f, 0xf7, 0x4f, 0x31, 0xdc, 0x15, 0x6b, 0x4f, 0xff, + 0x06, 0x00, 0x00, 0xff, 0xff, 0xa1, 0xb2, 0xfd, 0x65, 0x48, 0x06, 0x00, 0x00, } func (m *Message) Marshal() (dAtA []byte, err error) { @@ -1151,18 +1153,16 @@ func (m *ParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.ConsensusParams != nil { - { - size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } - i-- - dAtA[i] = 0x12 + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) } + i-- + dAtA[i] = 0x12 if m.Height != 0 { i = encodeVarintTypes(dAtA, i, uint64(m.Height)) i-- @@ -1414,10 +1414,8 @@ func (m *ParamsResponse) Size() (n int) { if m.Height != 0 { n += 1 + sovTypes(uint64(m.Height)) } - if m.ConsensusParams != nil { - l = m.ConsensusParams.Size() - n += 1 + l + sovTypes(uint64(l)) - } + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) return n } @@ -2551,9 +2549,6 @@ func (m *ParamsResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.ConsensusParams == nil { - m.ConsensusParams = &types.ConsensusParams{} - } if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } diff --git a/proto/tendermint/statesync/types.proto b/proto/tendermint/statesync/types.proto index 94e52a250..fcfd05f68 100644 --- a/proto/tendermint/statesync/types.proto +++ b/proto/tendermint/statesync/types.proto @@ -1,6 +1,7 @@ syntax = "proto3"; package tendermint.statesync; +import "gogoproto/gogo.proto"; import "tendermint/types/types.proto"; import "tendermint/types/params.proto"; @@ -57,5 +58,5 @@ message ParamsRequest { message ParamsResponse { uint64 height = 1; - tendermint.types.ConsensusParams consensus_params = 2; + tendermint.types.ConsensusParams consensus_params = 2 [(gogoproto.nullable) = false]; } \ No newline at end of file diff --git a/test/e2e/networks/simple.toml b/test/e2e/networks/simple.toml index f96d48011..b47775b2b 100644 --- a/test/e2e/networks/simple.toml +++ b/test/e2e/networks/simple.toml @@ -1,4 +1,12 @@ [node.validator01] +snapshot_interval = 2 [node.validator02] +snapshot_interval = 3 [node.validator03] -[node.validator04] \ No newline at end of file +snapshot_interval = 3 +[node.validator04] +state_sync = true +start_at = 5 +persistent_peers = ["validator01"] +[node.validator05] +snapshot_interval =3 \ No newline at end of file diff --git a/test/e2e/runner/setup.go b/test/e2e/runner/setup.go index c968ef306..0604109e7 100644 --- a/test/e2e/runner/setup.go +++ b/test/e2e/runner/setup.go @@ -304,18 +304,19 @@ func MakeConfig(node *e2e.Node) (*config.Config, error) { if node.StateSync { cfg.StateSync.Enable = true - cfg.StateSync.RPCServers = []string{} + cfg.StateSync.UseP2P = true + // cfg.StateSync.RPCServers = []string{} - for _, peer := range node.Testnet.ArchiveNodes() { - if peer.Name == node.Name { - continue - } - cfg.StateSync.RPCServers = append(cfg.StateSync.RPCServers, peer.AddressRPC()) - } + // for _, peer := range node.Testnet.ArchiveNodes() { + // if peer.Name == node.Name { + // continue + // } + // cfg.StateSync.RPCServers = append(cfg.StateSync.RPCServers, peer.AddressRPC()) + // } - if len(cfg.StateSync.RPCServers) < 2 { - return nil, errors.New("unable to find 2 suitable state sync RPC servers") - } + // if len(cfg.StateSync.RPCServers) < 2 { + // return nil, errors.New("unable to find 2 suitable state sync RPC servers") + // } } cfg.P2P.Seeds = ""