Merge pull request #3279 from nspcc-dev/fix-next-vals-panic

native: prevent improper Neo cache invalidation
This commit is contained in:
Roman Khimov 2023-12-21 22:17:43 +03:00 committed by GitHub
commit a872c200b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 6 deletions

View file

@ -681,12 +681,12 @@ func (s *service) getValidators(txes ...block.Transaction) []crypto.PublicKey {
// block's validators, thus should return validators from the current
// epoch without recalculation.
pKeys, err = s.Chain.GetNextBlockValidators()
} else {
// getValidators with non-empty args is used by dbft to fill block's
// NextConsensus field, ComputeNextBlockValidators will return proper
// value for NextConsensus wrt dBFT epoch start/end.
pKeys = s.Chain.ComputeNextBlockValidators()
}
// getValidators with non-empty args is used by dbft to fill block's
// NextConsensus field, but NeoGo doesn't provide WithGetConsensusAddress
// callback and fills NextConsensus by itself via WithNewBlockFromContext
// callback. Thus, leave pKeys empty if txes != nil.
if err != nil {
s.log.Error("error while trying to get validators", zap.Error(err))
}
@ -727,6 +727,16 @@ func (s *service) newBlockFromContext(ctx *dbft.Context) block.Block {
block.PrevStateRoot = sr.Root
}
// ComputeNextBlockValidators returns proper set of validators wrt dBFT epochs
// boundary. I.e. for the last block in the dBFT epoch this method returns the
// list of validators recalculated from the latest relevant information about
// NEO votes; in this case list of validators may differ from the one returned
// by GetNextBlockValidators. For the not-last block of dBFT epoch this method
// returns the same list as GetNextBlockValidators. Note, that by this moment
// we must be sure that previous block was successfully persisted to chain
// (i.e. PostPersist was completed for native Neo contract and PostPersist
// execution cache was persisted to s.Chain's DAO), otherwise the wrong
// (outdated, relevant for the previous dBFT epoch) value will be returned.
var validators = s.Chain.ComputeNextBlockValidators()
script, err := smartcontract.CreateDefaultMultiSigRedeemScript(validators)
if err != nil {

View file

@ -971,7 +971,6 @@ func (n *NEO) ModifyAccountVotes(acc *state.NEOBalance, d *dao.Simple, value *bi
return nil
}
}
cache.newEpochNextValidators = nil
return putConvertibleToDAO(n.ID, d, key, cd)
}
return nil