github.com/okex/exchain@v1.8.0/libs/tendermint/state/test_common.go (about)

     1  package state
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/okex/exchain/libs/iavl"
     9  	"github.com/okex/exchain/libs/tendermint/libs/log"
    10  
    11  	dbm "github.com/okex/exchain/libs/tm-db"
    12  
    13  	abci "github.com/okex/exchain/libs/tendermint/abci/types"
    14  	"github.com/okex/exchain/libs/tendermint/crypto"
    15  	"github.com/okex/exchain/libs/tendermint/crypto/ed25519"
    16  	tmrand "github.com/okex/exchain/libs/tendermint/libs/rand"
    17  	"github.com/okex/exchain/libs/tendermint/proxy"
    18  	"github.com/okex/exchain/libs/tendermint/types"
    19  	tmtime "github.com/okex/exchain/libs/tendermint/types/time"
    20  )
    21  
    22  var (
    23  	chainID      = "execution_chain"
    24  	testPartSize = 65536
    25  	nTxsPerBlock = 10
    26  )
    27  
    28  type paramsChangeTestCase struct {
    29  	height int64
    30  	params types.ConsensusParams
    31  }
    32  
    33  // always returns true if asked if any evidence was already committed.
    34  type mockEvPoolAlwaysCommitted struct{}
    35  
    36  func (m mockEvPoolAlwaysCommitted) PendingEvidence(int64) []types.Evidence { return nil }
    37  func (m mockEvPoolAlwaysCommitted) AddEvidence(types.Evidence) error       { return nil }
    38  func (m mockEvPoolAlwaysCommitted) Update(*types.Block, State)             {}
    39  func (m mockEvPoolAlwaysCommitted) IsCommitted(types.Evidence) bool        { return true }
    40  
    41  func newTestApp() proxy.AppConns {
    42  	app := &testApp{}
    43  	cc := proxy.NewLocalClientCreator(app)
    44  	return proxy.NewAppConns(cc)
    45  }
    46  
    47  func makeAndCommitGoodBlock(
    48  	state State,
    49  	height int64,
    50  	lastCommit *types.Commit,
    51  	proposerAddr []byte,
    52  	blockExec *BlockExecutor,
    53  	privVals map[string]types.PrivValidator,
    54  	evidence []types.Evidence) (State, types.BlockID, *types.Commit, error) {
    55  	// A good block passes
    56  	state, blockID, err := makeAndApplyGoodBlock(state, height, lastCommit, proposerAddr, blockExec, evidence)
    57  	if err != nil {
    58  		return state, types.BlockID{}, nil, err
    59  	}
    60  
    61  	// Simulate a lastCommit for this block from all validators for the next height
    62  	commit, err := makeValidCommit(height, blockID, state.Validators, privVals)
    63  	if err != nil {
    64  		return state, types.BlockID{}, nil, err
    65  	}
    66  	return state, blockID, commit, nil
    67  }
    68  
    69  func makeAndApplyGoodBlock(state State, height int64, lastCommit *types.Commit, proposerAddr []byte,
    70  	blockExec *BlockExecutor, evidence []types.Evidence) (State, types.BlockID, error) {
    71  	block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, evidence, proposerAddr)
    72  	if err := blockExec.ValidateBlock(state, block); err != nil {
    73  		return state, types.BlockID{}, err
    74  	}
    75  	blockID := types.BlockID{Hash: block.Hash(),
    76  		PartsHeader: types.PartSetHeader{Total: 3, Hash: tmrand.Bytes(32)}}
    77  	state, _, err := blockExec.ApplyBlock(state, blockID, block)
    78  	if err != nil {
    79  		return state, types.BlockID{}, err
    80  	}
    81  	return state, blockID, nil
    82  }
    83  
    84  func makeValidCommit(
    85  	height int64,
    86  	blockID types.BlockID,
    87  	vals *types.ValidatorSet,
    88  	privVals map[string]types.PrivValidator,
    89  ) (*types.Commit, error) {
    90  	sigs := make([]types.CommitSig, 0)
    91  	for i := 0; i < vals.Size(); i++ {
    92  		_, val := vals.GetByIndex(i)
    93  		vote, err := types.MakeVote(height, blockID, vals, privVals[val.Address.String()], chainID, time.Now())
    94  		if err != nil {
    95  			return nil, err
    96  		}
    97  		sigs = append(sigs, vote.CommitSig())
    98  	}
    99  	return types.NewCommit(height, 0, blockID, sigs), nil
   100  }
   101  
   102  // make some bogus txs
   103  func makeTxs(height int64) (txs []types.Tx) {
   104  	for i := 0; i < nTxsPerBlock; i++ {
   105  		txs = append(txs, types.Tx([]byte{byte(height), byte(i)}))
   106  	}
   107  	return txs
   108  }
   109  
   110  func makeState(nVals, height int) (State, dbm.DB, map[string]types.PrivValidator) {
   111  	vals := make([]types.GenesisValidator, nVals)
   112  	privVals := make(map[string]types.PrivValidator, nVals)
   113  	for i := 0; i < nVals; i++ {
   114  		secret := []byte(fmt.Sprintf("test%d", i))
   115  		pk := ed25519.GenPrivKeyFromSecret(secret)
   116  		valAddr := pk.PubKey().Address()
   117  		vals[i] = types.GenesisValidator{
   118  			Address: valAddr,
   119  			PubKey:  pk.PubKey(),
   120  			Power:   1000,
   121  			Name:    fmt.Sprintf("test%d", i),
   122  		}
   123  		privVals[valAddr.String()] = types.NewMockPVWithParams(pk, false, false)
   124  	}
   125  	s, _ := MakeGenesisState(&types.GenesisDoc{
   126  		ChainID:    chainID,
   127  		Validators: vals,
   128  		AppHash:    nil,
   129  	})
   130  
   131  	stateDB := dbm.NewMemDB()
   132  	SaveState(stateDB, s)
   133  
   134  	for i := 1; i < height; i++ {
   135  		s.LastBlockHeight++
   136  		s.LastValidators = s.Validators.Copy()
   137  		SaveState(stateDB, s)
   138  	}
   139  	return s, stateDB, privVals
   140  }
   141  
   142  func makeBlock(state State, height int64) *types.Block {
   143  	block, _ := state.MakeBlock(
   144  		height,
   145  		makeTxs(state.LastBlockHeight),
   146  		new(types.Commit),
   147  		nil,
   148  		state.Validators.GetProposer().Address,
   149  	)
   150  	return block
   151  }
   152  
   153  func genValSet(size int) *types.ValidatorSet {
   154  	vals := make([]*types.Validator, size)
   155  	for i := 0; i < size; i++ {
   156  		vals[i] = types.NewValidator(ed25519.GenPrivKey().PubKey(), 10)
   157  	}
   158  	return types.NewValidatorSet(vals)
   159  }
   160  
   161  func makeConsensusParams(
   162  	blockBytes, blockGas int64,
   163  	blockTimeIotaMs int64,
   164  	evidenceAge int64,
   165  ) types.ConsensusParams {
   166  	return types.ConsensusParams{
   167  		Block: types.BlockParams{
   168  			MaxBytes:   blockBytes,
   169  			MaxGas:     blockGas,
   170  			TimeIotaMs: blockTimeIotaMs,
   171  		},
   172  		Evidence: types.EvidenceParams{
   173  			MaxAgeNumBlocks: evidenceAge,
   174  			MaxAgeDuration:  time.Duration(evidenceAge),
   175  		},
   176  	}
   177  }
   178  
   179  func makeHeaderPartsResponsesValPubKeyChange(
   180  	state State,
   181  	pubkey crypto.PubKey,
   182  ) (types.Header, types.BlockID, *ABCIResponses) {
   183  
   184  	block := makeBlock(state, state.LastBlockHeight+1)
   185  	abciResponses := &ABCIResponses{
   186  		EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
   187  	}
   188  
   189  	// If the pubkey is new, remove the old and add the new.
   190  	_, val := state.NextValidators.GetByIndex(0)
   191  	if !bytes.Equal(pubkey.Bytes(), val.PubKey.Bytes()) {
   192  		abciResponses.EndBlock = &abci.ResponseEndBlock{
   193  			ValidatorUpdates: []abci.ValidatorUpdate{
   194  				types.TM2PB.NewValidatorUpdate(val.PubKey, 0),
   195  				types.TM2PB.NewValidatorUpdate(pubkey, 10),
   196  			},
   197  		}
   198  	}
   199  
   200  	return block.Header, types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}}, abciResponses
   201  }
   202  
   203  func makeHeaderPartsResponsesValPowerChange(
   204  	state State,
   205  	power int64,
   206  ) (types.Header, types.BlockID, *ABCIResponses) {
   207  
   208  	block := makeBlock(state, state.LastBlockHeight+1)
   209  	abciResponses := &ABCIResponses{
   210  		EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: nil},
   211  	}
   212  
   213  	// If the pubkey is new, remove the old and add the new.
   214  	_, val := state.NextValidators.GetByIndex(0)
   215  	if val.VotingPower != power {
   216  		abciResponses.EndBlock = &abci.ResponseEndBlock{
   217  			ValidatorUpdates: []abci.ValidatorUpdate{
   218  				types.TM2PB.NewValidatorUpdate(val.PubKey, power),
   219  			},
   220  		}
   221  	}
   222  
   223  	return block.Header, types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}}, abciResponses
   224  }
   225  
   226  func makeHeaderPartsResponsesParams(
   227  	state State,
   228  	params types.ConsensusParams,
   229  ) (types.Header, types.BlockID, *ABCIResponses) {
   230  
   231  	block := makeBlock(state, state.LastBlockHeight+1)
   232  	abciResponses := &ABCIResponses{
   233  		EndBlock: &abci.ResponseEndBlock{ConsensusParamUpdates: types.TM2PB.ConsensusParams(&params)},
   234  	}
   235  	return block.Header, types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}}, abciResponses
   236  }
   237  
   238  func randomGenesisDoc() *types.GenesisDoc {
   239  	pubkey := ed25519.GenPrivKey().PubKey()
   240  	return &types.GenesisDoc{
   241  		GenesisTime: tmtime.Now(),
   242  		ChainID:     "abc",
   243  		Validators: []types.GenesisValidator{
   244  			{
   245  				Address: pubkey.Address(),
   246  				PubKey:  pubkey,
   247  				Power:   10,
   248  				Name:    "myval",
   249  			},
   250  		},
   251  		ConsensusParams: types.DefaultConsensusParams(),
   252  	}
   253  }
   254  
   255  //----------------------------------------------------------------------------
   256  
   257  type testApp struct {
   258  	abci.BaseApplication
   259  
   260  	CommitVotes         []abci.VoteInfo
   261  	ByzantineValidators []abci.Evidence
   262  	ValidatorUpdates    []abci.ValidatorUpdate
   263  }
   264  
   265  var _ abci.Application = (*testApp)(nil)
   266  
   267  func (app *testApp) Info(req abci.RequestInfo) (resInfo abci.ResponseInfo) {
   268  	return abci.ResponseInfo{}
   269  }
   270  
   271  func (app *testApp) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock {
   272  	app.CommitVotes = req.LastCommitInfo.Votes
   273  	app.ByzantineValidators = req.ByzantineValidators
   274  	return abci.ResponseBeginBlock{}
   275  }
   276  
   277  func (app *testApp) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlock {
   278  	return abci.ResponseEndBlock{ValidatorUpdates: app.ValidatorUpdates}
   279  }
   280  
   281  func (app *testApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx {
   282  	return abci.ResponseDeliverTx{Events: []abci.Event{}}
   283  }
   284  
   285  func (app *testApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx {
   286  	return abci.ResponseCheckTx{}
   287  }
   288  
   289  func (app *testApp) Commit(abci.RequestCommit) abci.ResponseCommit {
   290  	return abci.ResponseCommit{}
   291  }
   292  
   293  func (app *testApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) {
   294  	return
   295  }
   296  
   297  //----------------------------------------------------------------------------------------------------
   298  // Execute block without state. TODO: eliminate
   299  
   300  // ExecCommitBlock executes and commits a block on the proxyApp without validating or mutating the state.
   301  // It returns the application root hash (result of abci.Commit).
   302  func ExecCommitBlock(
   303  	appConnConsensus proxy.AppConnConsensus,
   304  	block *types.Block,
   305  	logger log.Logger,
   306  	stateDB dbm.DB,
   307  ) ([]byte, error) {
   308  
   309  	ctx := &executionTask{
   310  		logger:   logger,
   311  		block:    block,
   312  		db:       stateDB,
   313  		proxyApp: appConnConsensus,
   314  	}
   315  
   316  	_, err := execBlockOnProxyApp(ctx)
   317  	if err != nil {
   318  		logger.Error("Error executing block on proxy app", "height", block.Height, "err", err)
   319  		return nil, err
   320  	}
   321  	// Commit block, get hash back
   322  	res, err := appConnConsensus.CommitSync(abci.RequestCommit{})
   323  	if err != nil {
   324  		logger.Error("Client error during proxyAppConn.CommitSync", "err", res)
   325  		return nil, err
   326  	}
   327  	// ResponseCommit has no error or log, just data
   328  	return res.Data, nil
   329  }
   330  
   331  func execCommitBlockDelta(
   332  	appConnConsensus proxy.AppConnConsensus,
   333  	block *types.Block,
   334  	logger log.Logger,
   335  	stateDB dbm.DB,
   336  ) (*types.Deltas, []byte, error) {
   337  	iavl.SetProduceDelta(true)
   338  	types.UploadDelta = true
   339  	deltas := &types.Deltas{Height: block.Height}
   340  
   341  	ctx := &executionTask{
   342  		logger:   logger,
   343  		block:    block,
   344  		db:       stateDB,
   345  		proxyApp: appConnConsensus,
   346  	}
   347  
   348  	abciResponses, err := execBlockOnProxyApp(ctx)
   349  	if err != nil {
   350  		logger.Error("Error executing block on proxy app", "height", block.Height, "err", err)
   351  		return nil, nil, err
   352  	}
   353  	abciResponsesBytes, err := types.Json.Marshal(abciResponses)
   354  	if err != nil {
   355  		return nil, nil, err
   356  	}
   357  	deltas.Payload.ABCIRsp = abciResponsesBytes
   358  
   359  	// Commit block, get hash back
   360  	res, err := appConnConsensus.CommitSync(abci.RequestCommit{})
   361  	if err != nil {
   362  		logger.Error("Client error during proxyAppConn.CommitSync", "err", res)
   363  		return nil, nil, err
   364  	}
   365  
   366  	if res.DeltaMap != nil {
   367  		deltaBytes, err := types.Json.Marshal(res.DeltaMap)
   368  		if err != nil {
   369  			return nil, nil, err
   370  		}
   371  		deltas.Payload.DeltasBytes = deltaBytes
   372  		wdFunc := evmWatchDataManager.CreateWatchDataGenerator()
   373  		if wd, err := wdFunc(); err == nil {
   374  			deltas.Payload.WatchBytes = wd
   375  		}
   376  		wasmWdFunc := wasmWatchDataManager.CreateWatchDataGenerator()
   377  		if wd, err := wasmWdFunc(); err == nil {
   378  			deltas.Payload.WasmWatchBytes = wd
   379  		}
   380  	}
   381  
   382  	// ResponseCommit has no error or log, just data
   383  	return deltas, res.Data, nil
   384  }