Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dash/quorum/validator_conn_executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,10 @@ func TestFinalizeBlock(t *testing.T) {
require.NoError(t, err)
block.NextValidatorsHash = newVals.Hash()
const round = int32(0)
candidateState, err := blockExec.ProcessProposal(ctx, block, round, state, true)
candidateState, err := blockExec.ProcessProposal(ctx, block, round, state, true, types.VerifiedCommit{})
require.NoError(t, err)

state, err = blockExec.FinalizeBlock(ctx, state, candidateState, blockID, block, new(types.Commit))
state, err = blockExec.FinalizeBlock(ctx, state, candidateState, blockID, block, new(types.Commit), types.VerifiedCommit{})
require.NoError(t, err)

// test new validator was added to NextValidators
Expand Down
40 changes: 28 additions & 12 deletions internal/blocksync/applier.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ type (
state sm.State
metrics *consensus.Metrics
stats applyStats
// lastCommit is the commit of the block most recently applied onto state,
// with the proof of its verification. The next block carries that commit
// as its LastCommit, so this is offered back when that block is validated
// and applied, sparing a second threshold verification of the same commit.
// Guarded by mtx, like state.
lastCommit types.VerifiedCommit
// lastDone is when the previous Apply returned, so the time the applier
// sits idle waiting for the next block can be measured
lastDone time.Time
Expand Down Expand Up @@ -85,7 +91,7 @@ func (e *blockApplier) Apply(ctx context.Context, block *types.Block, commit *ty
partSetTime := e.observeSince("partset", start)

start = time.Now()
err = e.verify(ctx, blockID, block, commit)
verified, err := e.verify(ctx, blockID, block, commit)
if err != nil {
return err
}
Expand All @@ -94,7 +100,7 @@ func (e *blockApplier) Apply(ctx context.Context, block *types.Block, commit *ty
// Validate the app response before persisting; save before FinalizeBlock so
// crash recovery never finds the block store behind the application.
start = time.Now()
uncommittedState, err := e.blockExec.ProcessProposal(ctx, block, commit.Round, e.state, true)
uncommittedState, err := e.blockExec.ProcessProposal(ctx, block, commit.Round, e.state, true, e.lastCommit)
if err != nil {
panic(fmt.Sprintf("failed to process committed block (%d:%X): %v", block.Height, block.Hash(), err))
}
Expand All @@ -105,10 +111,12 @@ func (e *blockApplier) Apply(ctx context.Context, block *types.Block, commit *ty
saveTime := e.observeSince("save", start)

start = time.Now()
e.state, err = e.blockExec.FinalizeBlock(ctx, e.state, uncommittedState, blockID, block, commit)
e.state, err = e.blockExec.FinalizeBlock(ctx, e.state, uncommittedState, blockID, block, commit, e.lastCommit)
if err != nil {
panic(fmt.Sprintf("failed to finalize committed block (%d:%X): %v", block.Height, block.Hash(), err))
}
// commit comes back as the next block's LastCommit
e.lastCommit = verified
execTime := processTime + time.Since(start)
e.metrics.ObserveBlockSyncStage("exec", execTime)

Expand Down Expand Up @@ -138,14 +146,22 @@ func (e *blockApplier) UpdateState(newState sm.State) {
e.mtx.Lock()
defer e.mtx.Unlock()
e.state = newState
// the commit lastCommit verified was applied onto the replaced state, not onto
// newState
e.lastCommit = types.VerifiedCommit{}
}

func (e *blockApplier) verify(ctx context.Context, blockID types.BlockID, block *types.Block, commit *types.Commit) error {
// The two checks are timed separately: the commit check is a BLS threshold
// signature verification and is nearly the whole stage, block validation is
// free.
// verify checks commit and then block against the current state, before the
// block is persisted. It returns commit with the proof of its verification;
// the next block carries commit as its LastCommit.
func (e *blockApplier) verify(
ctx context.Context,
blockID types.BlockID,
block *types.Block,
commit *types.Commit,
) (types.VerifiedCommit, error) {
start := time.Now()
err := e.state.Validators.VerifyCommit(e.state.ChainID, blockID, block.Height, commit)
verified, err := e.blockExec.VerifyCommit(e.state, blockID, block.Height, commit)
e.observeSince("verify_commit", start)

// If either of the checks failed we log the error and request for a new block
Expand All @@ -157,11 +173,11 @@ func (e *blockApplier) verify(ctx context.Context, blockID types.BlockID, block
"block_id", blockID,
"height", block.Height,
)
return err
return types.VerifiedCommit{}, err
}
// validate the block before we persist it
start = time.Now()
err = e.blockExec.ValidateBlock(ctx, e.state, block)
err = e.blockExec.ValidateBlock(ctx, e.state, block, e.lastCommit)
e.observeSince("verify_block", start)
if err != nil {
err = fmt.Errorf("invalid block: %w", err)
Expand All @@ -170,9 +186,9 @@ func (e *blockApplier) verify(ctx context.Context, blockID types.BlockID, block
"block_id", blockID,
"height", block.Height,
)
return err
return types.VerifiedCommit{}, err
}
return nil
return verified, nil
}

// observeSince records the time since start under stage and returns it, so the
Expand Down
Loading
Loading