allow exchanging of consensus params

This commit is contained in:
Callum Waters
2021-08-06 16:48:50 +02:00
parent 2bde896c13
commit 39c54f5f34
12 changed files with 342 additions and 138 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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")
}

View File

@@ -340,6 +340,7 @@ func makeNode(config *cfg.Config,
channels[statesync.SnapshotChannel],
channels[statesync.ChunkChannel],
channels[statesync.LightBlockChannel],
channels[statesync.ParamsChannel],
peerUpdates,
stateStore,
blockStore,

View File

@@ -756,6 +756,7 @@ func makeNodeInfo(
byte(statesync.SnapshotChannel),
byte(statesync.ChunkChannel),
byte(statesync.LightBlockChannel),
byte(statesync.ParamsChannel),
},
Moniker: config.Moniker,
Other: types.NodeInfoOther{

View File

@@ -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)
}

View File

@@ -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",
},
}

View File

@@ -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
}

View File

@@ -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];
}

View File

@@ -1,4 +1,12 @@
[node.validator01]
snapshot_interval = 2
[node.validator02]
snapshot_interval = 3
[node.validator03]
[node.validator04]
snapshot_interval = 3
[node.validator04]
state_sync = true
start_at = 5
persistent_peers = ["validator01"]
[node.validator05]
snapshot_interval =3

View File

@@ -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 = ""