github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/bft/state/helpers_test.go (about)

     1  package state_test
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
     8  	"github.com/gnolang/gno/tm2/pkg/bft/appconn"
     9  	"github.com/gnolang/gno/tm2/pkg/bft/proxy"
    10  	sm "github.com/gnolang/gno/tm2/pkg/bft/state"
    11  	"github.com/gnolang/gno/tm2/pkg/bft/types"
    12  	"github.com/gnolang/gno/tm2/pkg/crypto"
    13  	"github.com/gnolang/gno/tm2/pkg/crypto/ed25519"
    14  	dbm "github.com/gnolang/gno/tm2/pkg/db"
    15  	"github.com/gnolang/gno/tm2/pkg/db/memdb"
    16  )
    17  
    18  type paramsChangeTestCase struct {
    19  	height int64
    20  	params abci.ConsensusParams
    21  }
    22  
    23  func newTestApp() appconn.AppConns {
    24  	app := &testApp{}
    25  	cc := proxy.NewLocalClientCreator(app)
    26  	return appconn.NewAppConns(cc)
    27  }
    28  
    29  func makeAndCommitGoodBlock(
    30  	state sm.State,
    31  	height int64,
    32  	lastCommit *types.Commit,
    33  	proposerAddr crypto.Address,
    34  	blockExec *sm.BlockExecutor,
    35  	privVals map[string]types.PrivValidator,
    36  ) (sm.State, types.BlockID, *types.Commit, error) {
    37  	// A good block passes
    38  	state, blockID, err := makeAndApplyGoodBlock(state, height, lastCommit, proposerAddr, blockExec)
    39  	if err != nil {
    40  		return state, types.BlockID{}, nil, err
    41  	}
    42  
    43  	// Simulate a lastCommit for this block from all validators for the next height
    44  	commit, err := makeValidCommit(height, blockID, state.Validators, privVals)
    45  	if err != nil {
    46  		return state, types.BlockID{}, nil, err
    47  	}
    48  	return state, blockID, commit, nil
    49  }
    50  
    51  func makeAndApplyGoodBlock(state sm.State, height int64, lastCommit *types.Commit, proposerAddr crypto.Address,
    52  	blockExec *sm.BlockExecutor,
    53  ) (sm.State, types.BlockID, error) {
    54  	block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, proposerAddr)
    55  	if err := blockExec.ValidateBlock(state, block); err != nil {
    56  		return state, types.BlockID{}, err
    57  	}
    58  	blockID := types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}}
    59  	state, err := blockExec.ApplyBlock(state, blockID, block)
    60  	if err != nil {
    61  		return state, types.BlockID{}, err
    62  	}
    63  	return state, blockID, nil
    64  }
    65  
    66  func makeValidCommit(height int64, blockID types.BlockID, vals *types.ValidatorSet, privVals map[string]types.PrivValidator) (*types.Commit, error) {
    67  	sigs := make([]*types.CommitSig, 0)
    68  	for i := 0; i < vals.Size(); i++ {
    69  		_, val := vals.GetByIndex(i)
    70  		vote, err := types.MakeVote(height, blockID, vals, privVals[val.Address.String()], chainID)
    71  		if err != nil {
    72  			return nil, err
    73  		}
    74  		sigs = append(sigs, vote.CommitSig())
    75  	}
    76  	return types.NewCommit(blockID, sigs), nil
    77  }
    78  
    79  // make some bogus txs
    80  func makeTxs(height int64) (txs []types.Tx) {
    81  	for i := 0; i < nTxsPerBlock; i++ {
    82  		txs = append(txs, types.Tx([]byte{byte(height), byte(i)}))
    83  	}
    84  	return txs
    85  }
    86  
    87  func makeState(nVals, height int) (sm.State, dbm.DB, map[string]types.PrivValidator) {
    88  	vals := make([]types.GenesisValidator, nVals)
    89  	privVals := make(map[string]types.PrivValidator, nVals)
    90  	for i := 0; i < nVals; i++ {
    91  		secret := []byte(fmt.Sprintf("test%d", i))
    92  		pk := ed25519.GenPrivKeyFromSecret(secret)
    93  		valAddr := pk.PubKey().Address()
    94  		vals[i] = types.GenesisValidator{
    95  			Address: valAddr,
    96  			PubKey:  pk.PubKey(),
    97  			Power:   1000,
    98  			Name:    fmt.Sprintf("test%d", i),
    99  		}
   100  		privVals[valAddr.String()] = types.NewMockPVWithParams(pk, false, false)
   101  	}
   102  	s, _ := sm.MakeGenesisState(&types.GenesisDoc{
   103  		ChainID:    chainID,
   104  		Validators: vals,
   105  		AppHash:    nil,
   106  	})
   107  
   108  	stateDB := memdb.NewMemDB()
   109  	sm.SaveState(stateDB, s)
   110  
   111  	for i := 1; i < height; i++ {
   112  		s.LastBlockHeight++
   113  		s.LastValidators = s.Validators.Copy()
   114  		sm.SaveState(stateDB, s)
   115  	}
   116  	return s, stateDB, privVals
   117  }
   118  
   119  func makeBlock(state sm.State, height int64) *types.Block {
   120  	block, _ := state.MakeBlock(height, makeTxs(state.LastBlockHeight), new(types.Commit), state.Validators.GetProposer().Address)
   121  	return block
   122  }
   123  
   124  func genValSet(size int) *types.ValidatorSet {
   125  	vals := make([]*types.Validator, size)
   126  	for i := 0; i < size; i++ {
   127  		vals[i] = types.NewValidator(ed25519.GenPrivKey().PubKey(), 10)
   128  	}
   129  	return types.NewValidatorSet(vals)
   130  }
   131  
   132  func makeConsensusParams( // XXX search and replace
   133  	maxTxBytes, maxDataBytes, maxBlockBytes, maxGas int64,
   134  	timeIotaMS int64,
   135  ) abci.ConsensusParams {
   136  	return abci.ConsensusParams{
   137  		Block: &abci.BlockParams{
   138  			MaxTxBytes:    maxTxBytes,
   139  			MaxDataBytes:  maxDataBytes,
   140  			MaxBlockBytes: maxBlockBytes,
   141  			MaxGas:        maxGas,
   142  			TimeIotaMS:    timeIotaMS,
   143  		},
   144  	}
   145  }
   146  
   147  func makeHeaderPartsResponsesValPubKeyChange(state sm.State, pubkey crypto.PubKey) (types.Header, types.BlockID, *sm.ABCIResponses) {
   148  	block := makeBlock(state, state.LastBlockHeight+1)
   149  	abciResponses := &sm.ABCIResponses{
   150  		EndBlock: abci.ResponseEndBlock{ValidatorUpdates: nil},
   151  	}
   152  
   153  	// If the pubkey is new, remove the old and add the new.
   154  	_, val := state.NextValidators.GetByIndex(0)
   155  	if !bytes.Equal(pubkey.Bytes(), val.PubKey.Bytes()) {
   156  		abciResponses.EndBlock = abci.ResponseEndBlock{
   157  			ValidatorUpdates: []abci.ValidatorUpdate{
   158  				{Address: val.Address, PubKey: val.PubKey, Power: 0},
   159  				{Address: pubkey.Address(), PubKey: pubkey, Power: 10},
   160  			},
   161  		}
   162  	}
   163  
   164  	return block.Header, types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}}, abciResponses
   165  }
   166  
   167  func makeHeaderPartsResponsesValPowerChange(state sm.State, power int64) (types.Header, types.BlockID, *sm.ABCIResponses) {
   168  	block := makeBlock(state, state.LastBlockHeight+1)
   169  	abciResponses := &sm.ABCIResponses{
   170  		EndBlock: abci.ResponseEndBlock{ValidatorUpdates: nil},
   171  	}
   172  
   173  	// If the pubkey is new, remove the old and add the new.
   174  	_, val := state.NextValidators.GetByIndex(0)
   175  	if val.VotingPower != power {
   176  		abciResponses.EndBlock = abci.ResponseEndBlock{
   177  			ValidatorUpdates: []abci.ValidatorUpdate{
   178  				{Address: val.Address, PubKey: val.PubKey, Power: power},
   179  			},
   180  		}
   181  	}
   182  
   183  	return block.Header, types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}}, abciResponses
   184  }
   185  
   186  func makeHeaderPartsResponsesParams(state sm.State, params abci.ConsensusParams) (types.Header, types.BlockID, *sm.ABCIResponses) {
   187  	block := makeBlock(state, state.LastBlockHeight+1)
   188  	abciResponses := &sm.ABCIResponses{
   189  		EndBlock: abci.ResponseEndBlock{ConsensusParams: &params},
   190  	}
   191  	return block.Header, types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}}, abciResponses
   192  }
   193  
   194  // ----------------------------------------------------------------------------
   195  
   196  type testApp struct {
   197  	abci.BaseApplication
   198  
   199  	CommitVotes      []abci.VoteInfo
   200  	ValidatorUpdates []abci.ValidatorUpdate
   201  }
   202  
   203  var _ abci.Application = (*testApp)(nil)
   204  
   205  func (app *testApp) Info(req abci.RequestInfo) (resInfo abci.ResponseInfo) {
   206  	return abci.ResponseInfo{}
   207  }
   208  
   209  func (app *testApp) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock {
   210  	app.CommitVotes = req.LastCommitInfo.Votes
   211  	return abci.ResponseBeginBlock{}
   212  }
   213  
   214  func (app *testApp) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlock {
   215  	return abci.ResponseEndBlock{ValidatorUpdates: app.ValidatorUpdates}
   216  }
   217  
   218  func (app *testApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx {
   219  	return abci.ResponseDeliverTx{}
   220  }
   221  
   222  func (app *testApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx {
   223  	return abci.ResponseCheckTx{}
   224  }
   225  
   226  func (app *testApp) Commit() abci.ResponseCommit {
   227  	return abci.ResponseCommit{}
   228  }
   229  
   230  func (app *testApp) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) {
   231  	return
   232  }