abci++: synchronize PrepareProposal with the newest version of the spec (#8094)

This change implements the logic for the PrepareProposal ABCI++ method call. The main logic for creating and issuing the PrepareProposal request lives in execution.go and is tested in a set of new tests in execution_test.go. This change also updates the mempool mock to use a mockery generated version and removes much of the plumbing for the no longer used ABCIResponses.
This commit is contained in:
William Banfield
2022-03-15 15:37:30 -04:00
committed by GitHub
parent 4dce885994
commit 68c624f5de
36 changed files with 2895 additions and 834 deletions

View File

@@ -8,6 +8,7 @@ import (
abciclient "github.com/tendermint/tendermint/abci/client"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/encoding"
"github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/internal/eventbus"
"github.com/tendermint/tendermint/internal/mempool"
"github.com/tendermint/tendermint/libs/log"
@@ -99,10 +100,11 @@ func (blockExec *BlockExecutor) Store() Store {
func (blockExec *BlockExecutor) CreateProposalBlock(
ctx context.Context,
height int64,
state State, commit *types.Commit,
state State,
commit *types.Commit,
proposerAddr []byte,
votes []*types.Vote,
) (*types.Block, *types.PartSet, error) {
) (*types.Block, error) {
maxBytes := state.ConsensusParams.Block.MaxBytes
maxGas := state.ConsensusParams.Block.MaxGas
@@ -113,13 +115,18 @@ func (blockExec *BlockExecutor) CreateProposalBlock(
maxDataBytes := types.MaxDataBytes(maxBytes, evSize, state.Validators.Size())
txs := blockExec.mempool.ReapMaxBytesMaxGas(maxDataBytes, maxGas)
block := state.MakeBlock(height, txs, commit, evidence, proposerAddr)
preparedProposal, err := blockExec.appClient.PrepareProposal(
localLastCommit := buildLastCommitInfo(block, blockExec.store, state.InitialHeight)
rpp, err := blockExec.appClient.PrepareProposal(
ctx,
abci.RequestPrepareProposal{
BlockData: txs.ToSliceOfBytes(),
BlockDataSize: maxDataBytes,
Votes: types.VotesToProto(votes),
Hash: block.Hash(),
Header: *block.Header.ToProto(),
Txs: block.Txs.ToSliceOfBytes(),
LocalLastCommit: extendedCommitInfo(localLastCommit, votes),
ByzantineValidators: block.Evidence.ToABCI(),
MaxTxBytes: maxDataBytes,
},
)
if err != nil {
@@ -133,19 +140,28 @@ func (blockExec *BlockExecutor) CreateProposalBlock(
// purpose for now.
panic(err)
}
newTxs := preparedProposal.GetBlockData()
var txSize int
for _, tx := range newTxs {
txSize += len(tx)
if maxDataBytes < int64(txSize) {
panic("block data exceeds max amount of allowed bytes")
}
if !rpp.ModifiedTx {
return block, nil
}
txrSet := types.NewTxRecordSet(rpp.TxRecords)
if err := txrSet.Validate(maxDataBytes, block.Txs); err != nil {
return nil, err
}
modifiedTxs := types.ToTxs(preparedProposal.GetBlockData())
return state.MakeBlock(height, modifiedTxs, commit, evidence, proposerAddr)
for _, rtx := range txrSet.RemovedTxs() {
if err := blockExec.mempool.RemoveTxByKey(rtx.Key()); err != nil {
blockExec.logger.Debug("error removing transaction from the mempool", "error", err, "tx hash", rtx.Hash())
}
}
for _, atx := range txrSet.AddedTxs() {
if err := blockExec.mempool.CheckTx(ctx, atx, nil, mempool.TxInfo{}); err != nil {
blockExec.logger.Error("error adding tx to the mempool", "error", err, "tx hash", atx.Hash())
}
}
itxs := txrSet.IncludedTxs()
return state.MakeBlock(height, itxs, commit, evidence, proposerAddr), nil
}
func (blockExec *BlockExecutor) ProcessProposal(
@@ -249,7 +265,12 @@ func (blockExec *BlockExecutor) ApplyBlock(
}
// Update the state with the block and responses.
state, err = state.Update(blockID, &block.Header, ABCIResponsesResultsHash(abciResponses), finalizeBlockResponse.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(finalizeBlockResponse.TxResults)
if err != nil {
return state, fmt.Errorf("marshaling TxResults: %w", err)
}
h := merkle.HashFromByteSlices(rs)
state, err = state.Update(blockID, &block.Header, h, finalizeBlockResponse.ConsensusParamUpdates, validatorUpdates)
if err != nil {
return state, fmt.Errorf("commit failed for application: %w", err)
}
@@ -410,6 +431,24 @@ func buildLastCommitInfo(block *types.Block, store Store, initialHeight int64) a
}
}
func extendedCommitInfo(c abci.CommitInfo, votes []*types.Vote) abci.ExtendedCommitInfo {
vs := make([]abci.ExtendedVoteInfo, len(c.Votes))
for i := range vs {
vs[i] = abci.ExtendedVoteInfo{
Validator: c.Votes[i].Validator,
SignedLastBlock: c.Votes[i].SignedLastBlock,
/*
TODO: Include vote extensions information when implementing vote extensions.
VoteExtension: []byte{},
*/
}
}
return abci.ExtendedCommitInfo{
Round: c.Round,
Votes: vs,
}
}
func validateValidatorUpdates(abciUpdates []abci.ValidatorUpdate,
params types.ValidatorParams) error {
for _, valUpdate := range abciUpdates {

View File

@@ -18,7 +18,7 @@ import (
"github.com/tendermint/tendermint/crypto/encoding"
"github.com/tendermint/tendermint/crypto/tmhash"
"github.com/tendermint/tendermint/internal/eventbus"
mmock "github.com/tendermint/tendermint/internal/mempool/mock"
mpmocks "github.com/tendermint/tendermint/internal/mempool/mocks"
"github.com/tendermint/tendermint/internal/proxy"
"github.com/tendermint/tendermint/internal/pubsub"
sm "github.com/tendermint/tendermint/internal/state"
@@ -53,10 +53,20 @@ func TestApplyBlock(t *testing.T) {
state, stateDB, _ := makeState(t, 1, 1)
stateStore := sm.NewStore(stateDB)
blockStore := store.NewBlockStore(dbm.NewMemDB())
blockExec := sm.NewBlockExecutor(stateStore, logger, proxyApp, mmock.Mempool{}, sm.EmptyEvidencePool{}, blockStore, eventBus)
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
blockExec := sm.NewBlockExecutor(stateStore, logger, proxyApp, mp, sm.EmptyEvidencePool{}, blockStore, eventBus)
block, err := sf.MakeBlock(state, 1, new(types.Commit))
require.NoError(t, err)
block := sf.MakeBlock(state, 1, new(types.Commit))
bps, err := block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
@@ -103,11 +113,22 @@ func TestFinalizeBlockDecidedLastCommit(t *testing.T) {
evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, 0)
evpool.On("Update", ctx, mock.Anything, mock.Anything).Return()
evpool.On("CheckEvidence", ctx, mock.Anything).Return(nil)
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
eventBus := eventbus.NewDefault(logger)
require.NoError(t, eventBus.Start(ctx))
blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), appClient, mmock.Mempool{}, evpool, blockStore, eventBus)
blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), appClient, mp, evpool, blockStore, eventBus)
state, _, lastCommit := makeAndCommitGoodBlock(ctx, t, state, 1, new(types.Commit), state.NextValidators.Validators[0].Address, blockExec, privVals, nil)
for idx, isAbsent := range tc.absentCommitSigs {
@@ -117,8 +138,7 @@ func TestFinalizeBlockDecidedLastCommit(t *testing.T) {
}
// block for height 2
block, err := sf.MakeBlock(state, 2, lastCommit)
require.NoError(t, err)
block := sf.MakeBlock(state, 2, lastCommit)
bps, err := block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
@@ -215,6 +235,17 @@ func TestFinalizeBlockByzantineValidators(t *testing.T) {
evpool.On("PendingEvidence", mock.AnythingOfType("int64")).Return(ev, int64(100))
evpool.On("Update", ctx, mock.AnythingOfType("state.State"), mock.AnythingOfType("types.EvidenceList")).Return()
evpool.On("CheckEvidence", ctx, mock.AnythingOfType("types.EvidenceList")).Return(nil)
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
eventBus := eventbus.NewDefault(logger)
require.NoError(t, eventBus.Start(ctx))
@@ -222,10 +253,9 @@ func TestFinalizeBlockByzantineValidators(t *testing.T) {
blockStore := store.NewBlockStore(dbm.NewMemDB())
blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp,
mmock.Mempool{}, evpool, blockStore, eventBus)
mp, evpool, blockStore, eventBus)
block, err := sf.MakeBlock(state, 1, new(types.Commit))
require.NoError(t, err)
block := sf.MakeBlock(state, 1, new(types.Commit))
block.Evidence = ev
block.Header.EvidenceHash = block.Evidence.Hash()
bps, err := block.MakePartSet(testPartSize)
@@ -264,14 +294,13 @@ func TestProcessProposal(t *testing.T) {
stateStore,
logger,
proxyApp,
mmock.Mempool{},
new(mpmocks.Mempool),
sm.EmptyEvidencePool{},
blockStore,
eventBus,
)
block0, err := sf.MakeBlock(state, height-1, new(types.Commit))
require.NoError(t, err)
block0 := sf.MakeBlock(state, height-1, new(types.Commit))
lastCommitSig := []types.CommitSig{}
partSet, err := block0.MakePartSet(types.BlockPartSizeBytes)
require.NoError(t, err)
@@ -295,8 +324,7 @@ func TestProcessProposal(t *testing.T) {
}
lastCommit := types.NewCommit(height-1, 0, types.BlockID{}, lastCommitSig)
block1, err := sf.MakeBlock(state, height, lastCommit)
require.NoError(t, err)
block1 := sf.MakeBlock(state, height, lastCommit)
block1.Txs = txs
expectedRpp := abci.RequestProcessProposal{
@@ -463,6 +491,18 @@ func TestFinalizeBlockValidatorUpdates(t *testing.T) {
state, stateDB, _ := makeState(t, 1, 1)
stateStore := sm.NewStore(stateDB)
blockStore := store.NewBlockStore(dbm.NewMemDB())
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{})
eventBus := eventbus.NewDefault(logger)
require.NoError(t, eventBus.Start(ctx))
@@ -471,7 +511,7 @@ func TestFinalizeBlockValidatorUpdates(t *testing.T) {
stateStore,
logger,
proxyApp,
mmock.Mempool{},
mp,
sm.EmptyEvidencePool{},
blockStore,
eventBus,
@@ -483,8 +523,7 @@ func TestFinalizeBlockValidatorUpdates(t *testing.T) {
})
require.NoError(t, err)
block, err := sf.MakeBlock(state, 1, new(types.Commit))
require.NoError(t, err)
block := sf.MakeBlock(state, 1, new(types.Commit))
bps, err := block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
@@ -542,14 +581,13 @@ func TestFinalizeBlockValidatorUpdatesResultingInEmptySet(t *testing.T) {
stateStore,
log.TestingLogger(),
proxyApp,
mmock.Mempool{},
new(mpmocks.Mempool),
sm.EmptyEvidencePool{},
blockStore,
eventBus,
)
block, err := sf.MakeBlock(state, 1, new(types.Commit))
require.NoError(t, err)
block := sf.MakeBlock(state, 1, new(types.Commit))
bps, err := block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
@@ -566,6 +604,292 @@ func TestFinalizeBlockValidatorUpdatesResultingInEmptySet(t *testing.T) {
assert.NotEmpty(t, state.NextValidators.Validators)
}
func TestEmptyPrepareProposal(t *testing.T) {
const height = 2
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
logger := log.TestingLogger()
eventBus := eventbus.NewDefault(logger)
require.NoError(t, eventBus.Start(ctx))
app := abcimocks.NewBaseMock()
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
err := proxyApp.Start(ctx)
require.NoError(t, err)
state, stateDB, privVals := makeState(t, 1, height)
stateStore := sm.NewStore(stateDB)
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{})
blockExec := sm.NewBlockExecutor(
stateStore,
logger,
proxyApp,
mp,
sm.EmptyEvidencePool{},
nil,
eventBus,
)
pa, _ := state.Validators.GetByIndex(0)
commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
_, err = blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil)
require.NoError(t, err)
}
// TestPrepareProposalRemoveTxs tests that any transactions marked as REMOVED
// are not included in the block produced by CreateProposalBlock. The test also
// ensures that any transactions removed are also removed from the mempool.
func TestPrepareProposalRemoveTxs(t *testing.T) {
const height = 2
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
logger := log.TestingLogger()
eventBus := eventbus.NewDefault(logger)
require.NoError(t, eventBus.Start(ctx))
state, stateDB, privVals := makeState(t, 1, height)
stateStore := sm.NewStore(stateDB)
evpool := &mocks.EvidencePool{}
evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
txs := factory.MakeTenTxs(height)
mp := &mpmocks.Mempool{}
mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs))
trs := txsToTxRecords(types.Txs(txs))
trs[0].Action = abci.TxRecord_REMOVED
trs[1].Action = abci.TxRecord_REMOVED
mp.On("RemoveTxByKey", mock.Anything).Return(nil).Twice()
app := abcimocks.NewBaseMock()
app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{
ModifiedTx: true,
TxRecords: trs,
}, nil)
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
err := proxyApp.Start(ctx)
require.NoError(t, err)
blockExec := sm.NewBlockExecutor(
stateStore,
logger,
proxyApp,
mp,
evpool,
nil,
eventBus,
)
pa, _ := state.Validators.GetByIndex(0)
commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil)
require.NoError(t, err)
require.Len(t, block.Data.Txs.ToSliceOfBytes(), len(trs)-2)
require.Equal(t, -1, block.Data.Txs.Index(types.Tx(trs[0].Tx)))
require.Equal(t, -1, block.Data.Txs.Index(types.Tx(trs[1].Tx)))
mp.AssertCalled(t, "RemoveTxByKey", types.Tx(trs[0].Tx).Key())
mp.AssertCalled(t, "RemoveTxByKey", types.Tx(trs[1].Tx).Key())
mp.AssertExpectations(t)
}
// TestPrepareProposalAddedTxsIncluded tests that any transactions marked as ADDED
// in the prepare proposal response are included in the block. The test also
// ensures that any transactions added are also checked into the mempool.
func TestPrepareProposalAddedTxsIncluded(t *testing.T) {
const height = 2
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
logger := log.TestingLogger()
eventBus := eventbus.NewDefault(logger)
require.NoError(t, eventBus.Start(ctx))
state, stateDB, privVals := makeState(t, 1, height)
stateStore := sm.NewStore(stateDB)
evpool := &mocks.EvidencePool{}
evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
txs := factory.MakeTenTxs(height)
mp := &mpmocks.Mempool{}
mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs[2:]))
mp.On("CheckTx", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Twice()
trs := txsToTxRecords(types.Txs(txs))
trs[0].Action = abci.TxRecord_ADDED
trs[1].Action = abci.TxRecord_ADDED
app := abcimocks.NewBaseMock()
app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{
ModifiedTx: true,
TxRecords: trs,
}, nil)
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
err := proxyApp.Start(ctx)
require.NoError(t, err)
blockExec := sm.NewBlockExecutor(
stateStore,
logger,
proxyApp,
mp,
evpool,
nil,
eventBus,
)
pa, _ := state.Validators.GetByIndex(0)
commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil)
require.NoError(t, err)
require.Equal(t, txs[0], block.Data.Txs[0])
require.Equal(t, txs[1], block.Data.Txs[1])
mp.AssertExpectations(t)
mp.AssertCalled(t, "CheckTx", mock.Anything, types.Tx(trs[0].Tx), mock.Anything, mock.Anything)
mp.AssertCalled(t, "CheckTx", mock.Anything, types.Tx(trs[1].Tx), mock.Anything, mock.Anything)
}
// TestPrepareProposalReorderTxs tests that CreateBlock produces a block with transactions
// in the order matching the order they are returned from PrepareProposal.
func TestPrepareProposalReorderTxs(t *testing.T) {
const height = 2
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
logger := log.TestingLogger()
eventBus := eventbus.NewDefault(logger)
require.NoError(t, eventBus.Start(ctx))
state, stateDB, privVals := makeState(t, 1, height)
stateStore := sm.NewStore(stateDB)
evpool := &mocks.EvidencePool{}
evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
txs := factory.MakeTenTxs(height)
mp := &mpmocks.Mempool{}
mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs))
trs := txsToTxRecords(types.Txs(txs))
trs = trs[2:]
trs = append(trs[len(trs)/2:], trs[:len(trs)/2]...)
app := abcimocks.NewBaseMock()
app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{
ModifiedTx: true,
TxRecords: trs,
}, nil)
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
err := proxyApp.Start(ctx)
require.NoError(t, err)
blockExec := sm.NewBlockExecutor(
stateStore,
logger,
proxyApp,
mp,
evpool,
nil,
eventBus,
)
pa, _ := state.Validators.GetByIndex(0)
commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil)
require.NoError(t, err)
for i, tx := range block.Data.Txs {
require.Equal(t, types.Tx(trs[i].Tx), tx)
}
mp.AssertExpectations(t)
}
// TestPrepareProposalModifiedTxFalse tests that CreateBlock correctly ignores
// the ResponsePrepareProposal TxRecords if ResponsePrepareProposal does not
// set ModifiedTx to true.
func TestPrepareProposalModifiedTxFalse(t *testing.T) {
const height = 2
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
logger := log.TestingLogger()
eventBus := eventbus.NewDefault(logger)
require.NoError(t, eventBus.Start(ctx))
state, stateDB, privVals := makeState(t, 1, height)
stateStore := sm.NewStore(stateDB)
evpool := &mocks.EvidencePool{}
evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
txs := factory.MakeTenTxs(height)
mp := &mpmocks.Mempool{}
mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs))
trs := txsToTxRecords(types.Txs(txs))
trs = append(trs[len(trs)/2:], trs[:len(trs)/2]...)
trs = trs[1:]
trs[0].Action = abci.TxRecord_REMOVED
trs[1] = &abci.TxRecord{
Tx: []byte("new"),
Action: abci.TxRecord_ADDED,
}
app := abcimocks.NewBaseMock()
app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{
ModifiedTx: false,
TxRecords: trs,
}, nil)
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
err := proxyApp.Start(ctx)
require.NoError(t, err)
blockExec := sm.NewBlockExecutor(
stateStore,
logger,
proxyApp,
mp,
evpool,
nil,
eventBus,
)
pa, _ := state.Validators.GetByIndex(0)
commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil)
require.NoError(t, err)
for i, tx := range block.Data.Txs {
require.Equal(t, txs[i], tx)
}
mp.AssertExpectations(t)
}
func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.BlockID {
var (
h = make([]byte, tmhash.Size)
@@ -581,3 +905,14 @@ func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.Bloc
},
}
}
func txsToTxRecords(txs []types.Tx) []*abci.TxRecord {
trs := make([]*abci.TxRecord, len(txs))
for i, tx := range txs {
trs[i] = &abci.TxRecord{
Action: abci.TxRecord_UNMODIFIED,
Tx: tx,
}
}
return trs
}

View File

@@ -18,7 +18,6 @@ import (
sm "github.com/tendermint/tendermint/internal/state"
sf "github.com/tendermint/tendermint/internal/state/test/factory"
"github.com/tendermint/tendermint/internal/test/factory"
tmrand "github.com/tendermint/tendermint/libs/rand"
tmtime "github.com/tendermint/tendermint/libs/time"
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
@@ -63,12 +62,13 @@ func makeAndApplyGoodBlock(
evidence []types.Evidence,
) (sm.State, types.BlockID) {
t.Helper()
block, _, err := state.MakeBlock(height, factory.MakeTenTxs(height), lastCommit, evidence, proposerAddr)
block := state.MakeBlock(height, factory.MakeTenTxs(height), lastCommit, evidence, proposerAddr)
partSet, err := block.MakePartSet(types.BlockPartSizeBytes)
require.NoError(t, err)
require.NoError(t, blockExec.ValidateBlock(ctx, state, block))
blockID := types.BlockID{Hash: block.Hash(),
PartSetHeader: types.PartSetHeader{Total: 3, Hash: tmrand.Bytes(32)}}
PartSetHeader: partSet.Header()}
state, err = blockExec.ApplyBlock(ctx, state, blockID, block)
require.NoError(t, err)
@@ -144,8 +144,7 @@ func makeHeaderPartsResponsesValPubKeyChange(
pubkey crypto.PubKey,
) (types.Header, types.BlockID, *tmstate.ABCIResponses) {
block, err := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit))
require.NoError(t, err)
block := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit))
abciResponses := &tmstate.ABCIResponses{}
// If the pubkey is new, remove the old and add the new.
_, val := state.NextValidators.GetByIndex(0)
@@ -173,8 +172,7 @@ func makeHeaderPartsResponsesValPowerChange(
) (types.Header, types.BlockID, *tmstate.ABCIResponses) {
t.Helper()
block, err := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit))
require.NoError(t, err)
block := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit))
abciResponses := &tmstate.ABCIResponses{}
@@ -202,8 +200,7 @@ func makeHeaderPartsResponsesParams(
) (types.Header, types.BlockID, *tmstate.ABCIResponses) {
t.Helper()
block, err := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit))
require.NoError(t, err)
block := sf.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit))
pbParams := params.ToProto()
abciResponses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{ConsensusParamUpdates: &pbParams},

View File

@@ -260,7 +260,7 @@ func (state State) MakeBlock(
commit *types.Commit,
evidence []types.Evidence,
proposerAddress []byte,
) (*types.Block, *types.PartSet, error) {
) *types.Block {
// Build base block with block data.
block := types.MakeBlock(height, txs, commit, evidence)
@@ -274,12 +274,7 @@ func (state State) MakeBlock(
proposerAddress,
)
bps, err := block.MakePartSet(types.BlockPartSizeBytes)
if err != nil {
return nil, nil, err
}
return block, bps, nil
return block
}
//------------------------------------------------------------------------

View File

@@ -18,6 +18,7 @@ import (
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/encoding"
"github.com/tendermint/tendermint/crypto/merkle"
sm "github.com/tendermint/tendermint/internal/state"
statefactory "github.com/tendermint/tendermint/internal/state/test/factory"
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
@@ -103,8 +104,7 @@ func TestABCIResponsesSaveLoad1(t *testing.T) {
state.LastBlockHeight++
// Build mock responses.
block, err := statefactory.MakeBlock(state, 2, new(types.Commit))
require.NoError(t, err)
block := statefactory.MakeBlock(state, 2, new(types.Commit))
abciResponses := new(tmstate.ABCIResponses)
dtxs := make([]*abci.ExecTxResult, 2)
@@ -205,14 +205,13 @@ func TestABCIResponsesSaveLoad2(t *testing.T) {
res, err := stateStore.LoadABCIResponses(h)
if assert.NoError(t, err, "%d", i) {
t.Log(res)
responses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
TxResults: tc.expected,
},
}
sm.ABCIResponsesResultsHash(res)
sm.ABCIResponsesResultsHash(responses)
assert.Equal(t, sm.ABCIResponsesResultsHash(responses), sm.ABCIResponsesResultsHash(res), "%d", i)
e, err := abci.MarshalTxResults(tc.expected)
require.NoError(t, err)
he := merkle.HashFromByteSlices(e)
rs, err := abci.MarshalTxResults(res.FinalizeBlock.TxResults)
hrs := merkle.HashFromByteSlices(rs)
require.NoError(t, err)
assert.Equal(t, he, hrs, "%d", i)
}
}
}
@@ -278,9 +277,12 @@ func TestOneValidatorChangesSaveLoad(t *testing.T) {
header, blockID, responses := makeHeaderPartsResponsesValPowerChange(t, state, power)
validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.FinalizeBlock.ValidatorUpdates)
require.NoError(t, err)
state, err = state.Update(blockID, &header, sm.ABCIResponsesResultsHash(responses), responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(responses.FinalizeBlock.TxResults)
require.NoError(t, err)
err := stateStore.Save(state)
h := merkle.HashFromByteSlices(rs)
state, err = state.Update(blockID, &header, h, responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
require.NoError(t, err)
err = stateStore.Save(state)
require.NoError(t, err)
}
@@ -451,19 +453,19 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) {
// NewValidatorSet calls IncrementProposerPriority but uses on a copy of val1
assert.EqualValues(t, 0, val1.ProposerPriority)
block, err := statefactory.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit))
require.NoError(t, err)
block := statefactory.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit))
bps, err := block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
abciResponses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
},
fb := &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
}
validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates)
validatorUpdates, err := types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates)
require.NoError(t, err)
updatedState, err := state.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h := merkle.HashFromByteSlices(rs)
updatedState, err := state.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
assert.NoError(t, err)
curTotal := val1VotingPower
// one increment step and one validator: 0 + power - total_power == 0
@@ -478,7 +480,10 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) {
updateAddVal := abci.ValidatorUpdate{PubKey: fvp, Power: val2VotingPower}
validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal})
assert.NoError(t, err)
updatedState2, err := updatedState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err = abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h = merkle.HashFromByteSlices(rs)
updatedState2, err := updatedState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
assert.NoError(t, err)
require.Equal(t, len(updatedState2.NextValidators.Validators), 2)
@@ -517,7 +522,10 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) {
// this will cause the diff of priorities (77)
// to be larger than threshold == 2*totalVotingPower (22):
updatedState3, err := updatedState2.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err = abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h = merkle.HashFromByteSlices(rs)
updatedState3, err := updatedState2.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
assert.NoError(t, err)
require.Equal(t, len(updatedState3.NextValidators.Validators), 2)
@@ -569,21 +577,21 @@ func TestProposerPriorityProposerAlternates(t *testing.T) {
// we only have one validator:
assert.Equal(t, val1PubKey.Address(), state.Validators.Proposer.Address)
block, err := statefactory.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit))
require.NoError(t, err)
block := statefactory.MakeBlock(state, state.LastBlockHeight+1, new(types.Commit))
bps, err := block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
// no updates:
abciResponses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
},
fb := &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
}
validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates)
validatorUpdates, err := types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates)
require.NoError(t, err)
updatedState, err := state.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h := merkle.HashFromByteSlices(rs)
updatedState, err := state.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
assert.NoError(t, err)
// 0 + 10 (initial prio) - 10 (avg) - 10 (mostest - total) = -10
@@ -600,7 +608,10 @@ func TestProposerPriorityProposerAlternates(t *testing.T) {
validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal})
assert.NoError(t, err)
updatedState2, err := updatedState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err = abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h = merkle.HashFromByteSlices(rs)
updatedState2, err := updatedState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
assert.NoError(t, err)
require.Equal(t, len(updatedState2.NextValidators.Validators), 2)
@@ -640,10 +651,13 @@ func TestProposerPriorityProposerAlternates(t *testing.T) {
updatedVal2,
)
validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates)
validatorUpdates, err = types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates)
require.NoError(t, err)
updatedState3, err := updatedState2.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err = abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h = merkle.HashFromByteSlices(rs)
updatedState3, err := updatedState2.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
assert.NoError(t, err)
assert.Equal(t, updatedState3.Validators.Proposer.Address, updatedState3.NextValidators.Proposer.Address)
@@ -679,15 +693,16 @@ func TestProposerPriorityProposerAlternates(t *testing.T) {
// no changes in voting power and both validators have same voting power
// -> proposers should alternate:
oldState := updatedState3
abciResponses = &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
},
fb = &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
}
validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates)
validatorUpdates, err = types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates)
require.NoError(t, err)
oldState, err = oldState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err = abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h = merkle.HashFromByteSlices(rs)
oldState, err = oldState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
assert.NoError(t, err)
expectedVal1Prio2 = 1
expectedVal2Prio2 = -1
@@ -696,15 +711,16 @@ func TestProposerPriorityProposerAlternates(t *testing.T) {
for i := 0; i < 1000; i++ {
// no validator updates:
abciResponses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
},
fb := &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
}
validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates)
validatorUpdates, err = types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates)
require.NoError(t, err)
updatedState, err := oldState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h := merkle.HashFromByteSlices(rs)
updatedState, err := oldState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
assert.NoError(t, err)
// alternate (and cyclic priorities):
assert.NotEqual(
@@ -755,21 +771,21 @@ func TestLargeGenesisValidator(t *testing.T) {
oldState := state
for i := 0; i < 10; i++ {
// no updates:
abciResponses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
},
fb := &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
}
validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates)
validatorUpdates, err := types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates)
require.NoError(t, err)
block, err := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit))
require.NoError(t, err)
block := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit))
bps, err := block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
updatedState, err := oldState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h := merkle.HashFromByteSlices(rs)
updatedState, err := oldState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
require.NoError(t, err)
// no changes in voting power (ProposerPrio += VotingPower == Voting in 1st round; than shiftByAvg == 0,
// than -Total == -Voting)
@@ -791,41 +807,41 @@ func TestLargeGenesisValidator(t *testing.T) {
firstAddedVal := abci.ValidatorUpdate{PubKey: fvp, Power: firstAddedValVotingPower}
validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{firstAddedVal})
assert.NoError(t, err)
abciResponses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
ValidatorUpdates: []abci.ValidatorUpdate{firstAddedVal},
},
fb := &abci.ResponseFinalizeBlock{
ValidatorUpdates: []abci.ValidatorUpdate{firstAddedVal},
}
block, err := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit))
require.NoError(t, err)
block := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit))
bps, err := block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
updatedState, err := oldState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h := merkle.HashFromByteSlices(rs)
updatedState, err := oldState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
require.NoError(t, err)
lastState := updatedState
for i := 0; i < 200; i++ {
// no updates:
abciResponses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
},
fb := &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
}
validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates)
validatorUpdates, err := types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates)
require.NoError(t, err)
block, err := statefactory.MakeBlock(lastState, lastState.LastBlockHeight+1, new(types.Commit))
require.NoError(t, err)
block := statefactory.MakeBlock(lastState, lastState.LastBlockHeight+1, new(types.Commit))
bps, err = block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
updatedStateInner, err := lastState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h := merkle.HashFromByteSlices(rs)
updatedStateInner, err := lastState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
require.NoError(t, err)
lastState = updatedStateInner
}
@@ -851,18 +867,18 @@ func TestLargeGenesisValidator(t *testing.T) {
validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{addedVal})
assert.NoError(t, err)
abciResponses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
ValidatorUpdates: []abci.ValidatorUpdate{addedVal},
},
fb := &abci.ResponseFinalizeBlock{
ValidatorUpdates: []abci.ValidatorUpdate{addedVal},
}
block, err := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit))
require.NoError(t, err)
block := statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit))
bps, err := block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
state, err = state.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h := merkle.HashFromByteSlices(rs)
state, err = state.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
require.NoError(t, err)
}
require.Equal(t, 10+2, len(state.NextValidators.Validators))
@@ -871,22 +887,23 @@ func TestLargeGenesisValidator(t *testing.T) {
gp, err := encoding.PubKeyToProto(genesisPubKey)
require.NoError(t, err)
removeGenesisVal := abci.ValidatorUpdate{PubKey: gp, Power: 0}
abciResponses = &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
ValidatorUpdates: []abci.ValidatorUpdate{removeGenesisVal},
},
fb = &abci.ResponseFinalizeBlock{
ValidatorUpdates: []abci.ValidatorUpdate{removeGenesisVal},
}
block, err = statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit))
block = statefactory.MakeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit))
require.NoError(t, err)
bps, err = block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates)
validatorUpdates, err = types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates)
require.NoError(t, err)
updatedState, err = state.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err = abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h = merkle.HashFromByteSlices(rs)
updatedState, err = state.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
require.NoError(t, err)
// only the first added val (not the genesis val) should be left
assert.Equal(t, 11, len(updatedState.NextValidators.Validators))
@@ -897,21 +914,21 @@ func TestLargeGenesisValidator(t *testing.T) {
count := 0
isProposerUnchanged := true
for isProposerUnchanged {
abciResponses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
},
fb = &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
}
validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates)
require.NoError(t, err)
block, err = statefactory.MakeBlock(curState, curState.LastBlockHeight+1, new(types.Commit))
validatorUpdates, err = types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates)
require.NoError(t, err)
block = statefactory.MakeBlock(curState, curState.LastBlockHeight+1, new(types.Commit))
bps, err := block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
curState, err = curState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h := merkle.HashFromByteSlices(rs)
curState, err = curState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
require.NoError(t, err)
if !bytes.Equal(curState.Validators.Proposer.Address, curState.NextValidators.Proposer.Address) {
isProposerUnchanged = false
@@ -927,23 +944,23 @@ func TestLargeGenesisValidator(t *testing.T) {
proposers := make([]*types.Validator, numVals)
for i := 0; i < 100; i++ {
// no updates:
abciResponses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
},
fb := &abci.ResponseFinalizeBlock{
ValidatorUpdates: nil,
}
validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.FinalizeBlock.ValidatorUpdates)
validatorUpdates, err := types.PB2TM.ValidatorUpdates(fb.ValidatorUpdates)
require.NoError(t, err)
block, err := statefactory.MakeBlock(updatedState, updatedState.LastBlockHeight+1, new(types.Commit))
require.NoError(t, err)
block := statefactory.MakeBlock(updatedState, updatedState.LastBlockHeight+1, new(types.Commit))
bps, err := block.MakePartSet(testPartSize)
require.NoError(t, err)
blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
updatedState, err = updatedState.Update(blockID, &block.Header, sm.ABCIResponsesResultsHash(abciResponses), abciResponses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(fb.TxResults)
require.NoError(t, err)
h := merkle.HashFromByteSlices(rs)
updatedState, err = updatedState.Update(blockID, &block.Header, h, fb.ConsensusParamUpdates, validatorUpdates)
require.NoError(t, err)
if i > numVals { // expect proposers to cycle through after the first iteration (of numVals blocks):
if proposers[i%numVals] == nil {
@@ -1002,7 +1019,10 @@ func TestManyValidatorChangesSaveLoad(t *testing.T) {
var validatorUpdates []*types.Validator
validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.FinalizeBlock.ValidatorUpdates)
require.NoError(t, err)
state, err = state.Update(blockID, &header, sm.ABCIResponsesResultsHash(responses), responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(responses.FinalizeBlock.TxResults)
require.NoError(t, err)
h := merkle.HashFromByteSlices(rs)
state, err = state.Update(blockID, &header, h, responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
require.NoError(t, err)
nextHeight := state.LastBlockHeight + 1
err = stateStore.Save(state)
@@ -1035,8 +1055,7 @@ func TestStateMakeBlock(t *testing.T) {
proposerAddress := state.Validators.GetProposer().Address
stateVersion := state.Version.Consensus
block, err := statefactory.MakeBlock(state, 2, new(types.Commit))
require.NoError(t, err)
block := statefactory.MakeBlock(state, 2, new(types.Commit))
// test we set some fields
assert.Equal(t, stateVersion, block.Version)
@@ -1080,10 +1099,13 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) {
header, blockID, responses := makeHeaderPartsResponsesParams(t, state, &cp)
validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.FinalizeBlock.ValidatorUpdates)
require.NoError(t, err)
state, err = state.Update(blockID, &header, sm.ABCIResponsesResultsHash(responses), responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
rs, err := abci.MarshalTxResults(responses.FinalizeBlock.TxResults)
require.NoError(t, err)
h := merkle.HashFromByteSlices(rs)
state, err = state.Update(blockID, &header, h, responses.FinalizeBlock.ConsensusParamUpdates, validatorUpdates)
require.NoError(t, err)
err := stateStore.Save(state)
err = stateStore.Save(state)
require.NoError(t, err)
}

View File

@@ -396,14 +396,6 @@ func (store dbStore) reverseBatchDelete(batch dbm.Batch, start, end []byte) ([]b
//------------------------------------------------------------------------
// ABCIResponsesResultsHash returns the root hash of a Merkle tree of
// ResponseDeliverTx responses (see ABCIResults.Hash)
//
// See merkle.SimpleHashFromByteSlices
func ABCIResponsesResultsHash(ar *tmstate.ABCIResponses) []byte {
return types.NewResults(ar.FinalizeBlock.TxResults).Hash()
}
// LoadABCIResponses loads the ABCIResponses for the given height from the
// database. If not found, ErrNoABCIResponsesForHeight is returned.
//

View File

@@ -7,7 +7,6 @@ import (
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
dbm "github.com/tendermint/tm-db"
@@ -299,25 +298,3 @@ func TestPruneStates(t *testing.T) {
})
}
}
func TestABCIResponsesResultsHash(t *testing.T) {
responses := &tmstate.ABCIResponses{
FinalizeBlock: &abci.ResponseFinalizeBlock{
TxResults: []*abci.ExecTxResult{
{Code: 32, Data: []byte("Hello"), Log: "Huh?"},
},
},
}
root := sm.ABCIResponsesResultsHash(responses)
// root should be Merkle tree root of FinalizeBlock tx responses
results := types.NewResults(responses.FinalizeBlock.TxResults)
assert.Equal(t, root, results.Hash())
// test we can prove first tx in FinalizeBlock
proof := results.ProveResult(0)
bz, err := results[0].Marshal()
require.NoError(t, err)
assert.NoError(t, proof.Verify(root, bz))
}

View File

@@ -42,19 +42,14 @@ func MakeBlocks(ctx context.Context, t *testing.T, n int, state *sm.State, privV
return blocks
}
func MakeBlock(state sm.State, height int64, c *types.Commit) (*types.Block, error) {
block, _, err := state.MakeBlock(
func MakeBlock(state sm.State, height int64, c *types.Commit) *types.Block {
return state.MakeBlock(
height,
factory.MakeTenTxs(state.LastBlockHeight),
c,
nil,
state.Validators.GetProposer().Address,
)
if err != nil {
return nil, err
}
return block, nil
}
func makeBlockAndPartSet(
@@ -82,7 +77,8 @@ func makeBlockAndPartSet(
lastBlockMeta.BlockID, []types.CommitSig{vote.CommitSig()})
}
block, partSet, err := state.MakeBlock(height, []types.Tx{}, lastCommit, nil, state.Validators.GetProposer().Address)
block := state.MakeBlock(height, []types.Tx{}, lastCommit, nil, state.Validators.GetProposer().Address)
partSet, err := block.MakePartSet(types.BlockPartSizeBytes)
require.NoError(t, err)
return block, partSet

View File

@@ -15,7 +15,7 @@ import (
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/tmhash"
"github.com/tendermint/tendermint/internal/eventbus"
memmock "github.com/tendermint/tendermint/internal/mempool/mock"
mpmocks "github.com/tendermint/tendermint/internal/mempool/mocks"
"github.com/tendermint/tendermint/internal/proxy"
sm "github.com/tendermint/tendermint/internal/state"
"github.com/tendermint/tendermint/internal/state/mocks"
@@ -42,12 +42,24 @@ func TestValidateBlockHeader(t *testing.T) {
state, stateDB, privVals := makeState(t, 3, 1)
stateStore := sm.NewStore(stateDB)
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
blockStore := store.NewBlockStore(dbm.NewMemDB())
blockExec := sm.NewBlockExecutor(
stateStore,
logger,
proxyApp,
memmock.Mempool{},
mp,
sm.EmptyEvidencePool{},
blockStore,
eventBus,
@@ -98,10 +110,9 @@ func TestValidateBlockHeader(t *testing.T) {
Invalid blocks don't pass
*/
for _, tc := range testCases {
block, err := statefactory.MakeBlock(state, height, lastCommit)
require.NoError(t, err)
block := statefactory.MakeBlock(state, height, lastCommit)
tc.malleateBlock(block)
err = blockExec.ValidateBlock(ctx, state, block)
err := blockExec.ValidateBlock(ctx, state, block)
t.Logf("%s: %v", tc.name, err)
require.Error(t, err, tc.name)
}
@@ -114,10 +125,9 @@ func TestValidateBlockHeader(t *testing.T) {
}
nextHeight := validationTestsStopHeight
block, err := statefactory.MakeBlock(state, nextHeight, lastCommit)
require.NoError(t, err)
block := statefactory.MakeBlock(state, nextHeight, lastCommit)
state.InitialHeight = nextHeight + 1
err = blockExec.ValidateBlock(ctx, state, block)
err := blockExec.ValidateBlock(ctx, state, block)
require.Error(t, err, "expected an error when state is ahead of block")
assert.Contains(t, err.Error(), "lower than initial height")
}
@@ -135,12 +145,24 @@ func TestValidateBlockCommit(t *testing.T) {
state, stateDB, privVals := makeState(t, 1, 1)
stateStore := sm.NewStore(stateDB)
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
blockStore := store.NewBlockStore(dbm.NewMemDB())
blockExec := sm.NewBlockExecutor(
stateStore,
logger,
proxyApp,
memmock.Mempool{},
mp,
sm.EmptyEvidencePool{},
blockStore,
eventBus,
@@ -174,8 +196,7 @@ func TestValidateBlockCommit(t *testing.T) {
state.LastBlockID,
[]types.CommitSig{wrongHeightVote.CommitSig()},
)
block, err := statefactory.MakeBlock(state, height, wrongHeightCommit)
require.NoError(t, err)
block := statefactory.MakeBlock(state, height, wrongHeightCommit)
err = blockExec.ValidateBlock(ctx, state, block)
_, isErrInvalidCommitHeight := err.(types.ErrInvalidCommitHeight)
require.True(t, isErrInvalidCommitHeight, "expected ErrInvalidCommitHeight at height %d but got: %v", height, err)
@@ -183,8 +204,7 @@ func TestValidateBlockCommit(t *testing.T) {
/*
#2589: test len(block.LastCommit.Signatures) == state.LastValidators.Size()
*/
block, err = statefactory.MakeBlock(state, height, wrongSigsCommit)
require.NoError(t, err)
block = statefactory.MakeBlock(state, height, wrongSigsCommit)
err = blockExec.ValidateBlock(ctx, state, block)
_, isErrInvalidCommitSignatures := err.(types.ErrInvalidCommitSignatures)
require.True(t, isErrInvalidCommitSignatures,
@@ -274,13 +294,24 @@ func TestValidateBlockEvidence(t *testing.T) {
eventBus := eventbus.NewDefault(logger)
require.NoError(t, eventBus.Start(ctx))
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
state.ConsensusParams.Evidence.MaxBytes = 1000
blockExec := sm.NewBlockExecutor(
stateStore,
log.TestingLogger(),
proxyApp,
memmock.Mempool{},
mp,
evpool,
blockStore,
eventBus,
@@ -304,10 +335,9 @@ func TestValidateBlockEvidence(t *testing.T) {
evidence = append(evidence, newEv)
currentBytes += int64(len(newEv.Bytes()))
}
block, _, err := state.MakeBlock(height, testfactory.MakeTenTxs(height), lastCommit, evidence, proposerAddr)
require.NoError(t, err)
block := state.MakeBlock(height, testfactory.MakeTenTxs(height), lastCommit, evidence, proposerAddr)
err = blockExec.ValidateBlock(ctx, state, block)
err := blockExec.ValidateBlock(ctx, state, block)
if assert.Error(t, err) {
_, ok := err.(*types.ErrEvidenceOverflow)
require.True(t, ok, "expected error to be of type ErrEvidenceOverflow at height %d but got %v", height, err)