mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-05 21:14:53 +00:00
abci: implement process proposal to spec (#9122)
This commit is contained in:
@@ -112,7 +112,7 @@ func (blockExec *BlockExecutor) CreateProposalBlock(
|
||||
txs := blockExec.mempool.ReapMaxBytesMaxGas(maxDataBytes, maxGas)
|
||||
block := state.MakeBlock(height, txs, commit, evidence, proposerAddr)
|
||||
|
||||
localLastCommit := getBeginBlockValidatorInfo(block, blockExec.store, state.InitialHeight)
|
||||
localLastCommit := buildLastCommitInfo(block, blockExec.store, state.InitialHeight)
|
||||
rpp, err := blockExec.proxyApp.PrepareProposalSync(
|
||||
abci.RequestPrepareProposal{
|
||||
Hash: block.Hash(),
|
||||
@@ -149,6 +149,30 @@ func (blockExec *BlockExecutor) CreateProposalBlock(
|
||||
return state.MakeBlock(height, itxs, commit, evidence, proposerAddr), nil
|
||||
}
|
||||
|
||||
func (blockExec *BlockExecutor) ProcessProposal(
|
||||
block *types.Block,
|
||||
state State,
|
||||
) (bool, error) {
|
||||
resp, err := blockExec.proxyApp.ProcessProposalSync(abci.RequestProcessProposal{
|
||||
Hash: block.Header.Hash(),
|
||||
Height: block.Header.Height,
|
||||
Time: block.Header.Time,
|
||||
Txs: block.Data.Txs.ToSliceOfBytes(),
|
||||
ProposedLastCommit: buildLastCommitInfo(block, blockExec.store, state.InitialHeight),
|
||||
Misbehavior: block.Evidence.Evidence.ToABCI(),
|
||||
ProposerAddress: block.ProposerAddress,
|
||||
NextValidatorsHash: block.NextValidatorsHash,
|
||||
})
|
||||
if err != nil {
|
||||
return false, ErrInvalidBlock(err)
|
||||
}
|
||||
if resp.IsStatusUnknown() {
|
||||
panic(fmt.Sprintf("ProcessProposal responded with status %s", resp.Status.String()))
|
||||
}
|
||||
|
||||
return resp.IsAccepted(), nil
|
||||
}
|
||||
|
||||
// ValidateBlock validates the given block against the given state.
|
||||
// If the block is invalid, it returns an error.
|
||||
// Validation does not mutate state, but does require historical information from the stateDB,
|
||||
@@ -329,12 +353,7 @@ func execBlockOnProxyApp(
|
||||
}
|
||||
proxyAppConn.SetResponseCallback(proxyCb)
|
||||
|
||||
commitInfo := getBeginBlockValidatorInfo(block, store, initialHeight)
|
||||
|
||||
byzVals := make([]abci.Evidence, 0)
|
||||
for _, evidence := range block.Evidence.Evidence {
|
||||
byzVals = append(byzVals, evidence.ABCI()...)
|
||||
}
|
||||
commitInfo := buildLastCommitInfo(block, store, initialHeight)
|
||||
|
||||
// Begin block
|
||||
var err error
|
||||
@@ -347,7 +366,7 @@ func execBlockOnProxyApp(
|
||||
Hash: block.Hash(),
|
||||
Header: *pbh,
|
||||
LastCommitInfo: commitInfo,
|
||||
ByzantineValidators: byzVals,
|
||||
ByzantineValidators: block.Evidence.Evidence.ToABCI(),
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("error in proxyAppConn.BeginBlock", "err", err)
|
||||
@@ -373,47 +392,48 @@ func execBlockOnProxyApp(
|
||||
return abciResponses, nil
|
||||
}
|
||||
|
||||
func getBeginBlockValidatorInfo(block *types.Block, store Store,
|
||||
initialHeight int64) abci.LastCommitInfo {
|
||||
voteInfos := make([]abci.VoteInfo, block.LastCommit.Size())
|
||||
// Initial block -> LastCommitInfo.Votes are empty.
|
||||
// Remember that the first LastCommit is intentionally empty, so it makes
|
||||
// sense for LastCommitInfo.Votes to also be empty.
|
||||
if block.Height > initialHeight {
|
||||
lastValSet, err := store.LoadValidators(block.Height - 1)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
func buildLastCommitInfo(block *types.Block, store Store, initialHeight int64) abci.CommitInfo {
|
||||
if block.Height == initialHeight {
|
||||
// there is no last commit for the initial height.
|
||||
// return an empty value.
|
||||
return abci.CommitInfo{}
|
||||
}
|
||||
|
||||
// Sanity check that commit size matches validator set size - only applies
|
||||
// after first block.
|
||||
var (
|
||||
commitSize = block.LastCommit.Size()
|
||||
valSetLen = len(lastValSet.Validators)
|
||||
)
|
||||
if commitSize != valSetLen {
|
||||
panic(fmt.Sprintf(
|
||||
"commit size (%d) doesn't match valset length (%d) at height %d\n\n%v\n\n%v",
|
||||
commitSize, valSetLen, block.Height, block.LastCommit.Signatures, lastValSet.Validators,
|
||||
))
|
||||
}
|
||||
lastValSet, err := store.LoadValidators(block.Height - 1)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to load validator set at height %d: %w", block.Height-1, err))
|
||||
}
|
||||
|
||||
for i, val := range lastValSet.Validators {
|
||||
commitSig := block.LastCommit.Signatures[i]
|
||||
voteInfos[i] = abci.VoteInfo{
|
||||
Validator: types.TM2PB.Validator(val),
|
||||
SignedLastBlock: !commitSig.Absent(),
|
||||
}
|
||||
var (
|
||||
commitSize = block.LastCommit.Size()
|
||||
valSetLen = len(lastValSet.Validators)
|
||||
)
|
||||
|
||||
// ensure that the size of the validator set in the last commit matches
|
||||
// the size of the validator set in the state store.
|
||||
if commitSize != valSetLen {
|
||||
panic(fmt.Sprintf(
|
||||
"commit size (%d) doesn't match validator set length (%d) at height %d\n\n%v\n\n%v",
|
||||
commitSize, valSetLen, block.Height, block.LastCommit.Signatures, lastValSet.Validators,
|
||||
))
|
||||
}
|
||||
|
||||
votes := make([]abci.VoteInfo, block.LastCommit.Size())
|
||||
for i, val := range lastValSet.Validators {
|
||||
commitSig := block.LastCommit.Signatures[i]
|
||||
votes[i] = abci.VoteInfo{
|
||||
Validator: types.TM2PB.Validator(val),
|
||||
SignedLastBlock: commitSig.BlockIDFlag != types.BlockIDFlagAbsent,
|
||||
}
|
||||
}
|
||||
|
||||
return abci.LastCommitInfo{
|
||||
return abci.CommitInfo{
|
||||
Round: block.LastCommit.Round,
|
||||
Votes: voteInfos,
|
||||
Votes: votes,
|
||||
}
|
||||
}
|
||||
|
||||
func extendedCommitInfo(c abci.LastCommitInfo, votes []*types.Vote) abci.ExtendedCommitInfo {
|
||||
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{
|
||||
|
||||
Reference in New Issue
Block a user