mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
xin-176 use local masternode to verify signature (#98)
* use local masternode to verify signature * refactor verify header
This commit is contained in:
parent
50ae0c95fd
commit
1cac82825d
4 changed files with 39 additions and 49 deletions
|
|
@ -86,6 +86,7 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
return utils.ErrInvalidDifficulty
|
||||
}
|
||||
|
||||
var masterNodes []common.Address
|
||||
isEpochSwitch, _, err := x.IsEpochSwitch(header) // Verify v2 block that is on the epoch switch
|
||||
if err != nil {
|
||||
log.Error("[verifyHeader] error when checking if header is epoch switch header", "Hash", header.Hash(), "Number", header.Number, "Error", err)
|
||||
|
|
@ -102,20 +103,23 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
return utils.ErrInvalidCheckpointSigners
|
||||
}
|
||||
|
||||
_, localPenalties, err := x.calcMasternodes(chain, header.Number, header.ParentHash)
|
||||
localMasterNodes, localPenalties, err := x.calcMasternodes(chain, header.Number, header.ParentHash)
|
||||
masterNodes = localMasterNodes
|
||||
if err != nil {
|
||||
log.Error("[verifyHeader] Fail to calculate master nodes list with penalty", "Number", header.Number, "Hash", header.Hash())
|
||||
return err
|
||||
}
|
||||
|
||||
isLegit, err := x.isValidatorsLegit(chain, header, localPenalties)
|
||||
if err != nil {
|
||||
log.Error("[verifyHeader] Error while trying to check if the validators are legit", "Hash", header.Hash(), "Number", header.Number, "ValidatorsLength", len(header.Validators))
|
||||
return err
|
||||
}
|
||||
if !isLegit {
|
||||
validatorsAddress := common.ExtractAddressFromBytes(header.Validators)
|
||||
if !utils.CompareSignersLists(localMasterNodes, validatorsAddress) {
|
||||
return utils.ErrValidatorsNotLegit
|
||||
}
|
||||
|
||||
penaltiesAddress := common.ExtractAddressFromBytes(header.Penalties)
|
||||
if !utils.CompareSignersLists(localPenalties, penaltiesAddress) {
|
||||
return utils.ErrPenaltiesNotLegit
|
||||
}
|
||||
|
||||
} else {
|
||||
if len(header.Validators) != 0 {
|
||||
log.Warn("[verifyHeader] Validators shall not have values in non-epochSwitch block", "Hash", header.Hash(), "Number", header.Number, "header.Validators", header.Validators)
|
||||
|
|
@ -125,6 +129,7 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
log.Warn("[verifyHeader] Penalties shall not have values in non-epochSwitch block", "Hash", header.Hash(), "Number", header.Number, "header.Penalties", header.Penalties)
|
||||
return utils.ErrInvalidFieldInNonEpochSwitch
|
||||
}
|
||||
masterNodes = x.GetMasternodes(chain, header)
|
||||
}
|
||||
|
||||
// If all checks passed, validate any special fields for hard forks
|
||||
|
|
@ -133,7 +138,6 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
}
|
||||
|
||||
// Check its validator
|
||||
masterNodes := x.GetMasternodes(chain, header)
|
||||
verified, validatorAddress, err := x.verifyMsgSignature(sigHash(header), header.Validator, masterNodes)
|
||||
if err != nil {
|
||||
for index, mn := range masterNodes {
|
||||
|
|
@ -161,34 +165,3 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
x.verifiedHeaders.Add(header.Hash(), true)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify the header validators address is legit by checking against its snapshot masternode list minutes the penalty list, we also ensure the order matches
|
||||
func (x *XDPoS_v2) isValidatorsLegit(chain consensus.ChainReader, header *types.Header, penalties []common.Address) (bool, error) {
|
||||
|
||||
if header.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
|
||||
log.Info("[isValidatorsLegit] examing last v1 block")
|
||||
return true, nil
|
||||
}
|
||||
|
||||
snap, err := x.getSnapshot(chain, header.Number.Uint64(), false)
|
||||
if err != nil {
|
||||
log.Error("[isValidatorsLegit] Error while trying to get snapshot", "BlockNumber", header.Number.Int64(), "Hash", header.Hash().Hex(), "error", err)
|
||||
return false, err
|
||||
}
|
||||
// snap.NextEpochMasterNodes
|
||||
penaltyMap := make(map[common.Address]bool)
|
||||
for _, item := range penalties {
|
||||
penaltyMap[item] = true
|
||||
}
|
||||
|
||||
var finalValidMasternodes []common.Address
|
||||
for _, mn := range snap.NextEpochMasterNodes {
|
||||
if penaltyMap[mn] {
|
||||
continue
|
||||
} else {
|
||||
finalValidMasternodes = append(finalValidMasternodes, mn)
|
||||
}
|
||||
}
|
||||
validatorsAddress := common.ExtractAddressFromBytes(header.Validators)
|
||||
return utils.CompareSignersLists(finalValidMasternodes, validatorsAddress), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ var (
|
|||
|
||||
ErrInvalidCheckpointPenalties = errors.New("invalid penalty list on checkpoint block")
|
||||
|
||||
ErrValidatorsNotLegit = errors.New("Validators does not match what's stored in snapshot minutes its penalty")
|
||||
ErrValidatorsNotLegit = errors.New("validators does not match what's stored in snapshot minutes its penalty")
|
||||
ErrPenaltiesNotLegit = errors.New("penalties does not match")
|
||||
|
||||
// errInvalidMixDigest is returned if a block's mix digest is non-zero.
|
||||
ErrInvalidMixDigest = errors.New("non-zero mix digest")
|
||||
|
|
|
|||
|
|
@ -53,16 +53,27 @@ func ExtractValidatorsFromBytes(byteValidators []byte) []int64 {
|
|||
// compare 2 signers lists
|
||||
// return true if they are same elements, otherwise return false
|
||||
func CompareSignersLists(list1 []common.Address, list2 []common.Address) bool {
|
||||
if len(list1) == 0 && len(list2) == 0 {
|
||||
l1 := make([]common.Address, len(list1))
|
||||
l2 := make([]common.Address, len(list2))
|
||||
|
||||
copy(l1, list1)
|
||||
copy(l2, list2)
|
||||
|
||||
if len(l1) == 0 && len(l2) == 0 {
|
||||
return true
|
||||
}
|
||||
sort.Slice(list1, func(i, j int) bool {
|
||||
return list1[i].String() <= list1[j].String()
|
||||
|
||||
if len(l1) != len(l2) {
|
||||
return false
|
||||
}
|
||||
|
||||
sort.Slice(l1, func(i, j int) bool {
|
||||
return l1[i].String() <= l1[j].String()
|
||||
})
|
||||
sort.Slice(list2, func(i, j int) bool {
|
||||
return list2[i].String() <= list2[j].String()
|
||||
sort.Slice(l2, func(i, j int) bool {
|
||||
return l2[i].String() <= l2[j].String()
|
||||
})
|
||||
return reflect.DeepEqual(list1, list2)
|
||||
return reflect.DeepEqual(l1, l2)
|
||||
}
|
||||
|
||||
// Decode extra fields for consensus version >= 2 (XDPoS 2.0 and future versions)
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ func TestShouldVerifyBlock(t *testing.T) {
|
|||
assert.Equal(t, consensus.ErrUnknownAncestor, err)
|
||||
|
||||
tooFastMinedBlock := blockchain.GetBlockByNumber(902).Header()
|
||||
tooFastMinedBlock.Time = big.NewInt(time.Now().Unix() - 2)
|
||||
tooFastMinedBlock.Time = big.NewInt(time.Now().Unix() - 10)
|
||||
err = adaptor.VerifyHeader(blockchain, tooFastMinedBlock, true)
|
||||
assert.Equal(t, utils.ErrInvalidTimestamp, err)
|
||||
|
||||
|
|
@ -156,12 +156,17 @@ func TestShouldVerifyBlock(t *testing.T) {
|
|||
err = adaptor.VerifyHeader(blockchain, coinbaseValidatorMismatchBlock, true)
|
||||
assert.Equal(t, utils.ErrCoinbaseAndValidatorMismatch, err)
|
||||
|
||||
// Make the validators not legit by adding something to the penalty
|
||||
// Make the validators not legit by adding something to the validator
|
||||
validatorsNotLegit := blockchain.GetBlockByNumber(901).Header()
|
||||
|
||||
validatorsNotLegit.Validators = append(validatorsNotLegit.Validators, acc1Addr[:]...)
|
||||
err = adaptor.VerifyHeader(blockchain, validatorsNotLegit, true)
|
||||
assert.Equal(t, utils.ErrValidatorsNotLegit, err)
|
||||
|
||||
// Make the penalties not legit by adding something to the penalty
|
||||
penaltiesNotLegit := blockchain.GetBlockByNumber(901).Header()
|
||||
penaltiesNotLegit.Penalties = append(penaltiesNotLegit.Penalties, acc1Addr[:]...)
|
||||
err = adaptor.VerifyHeader(blockchain, penaltiesNotLegit, true)
|
||||
assert.Equal(t, utils.ErrPenaltiesNotLegit, err)
|
||||
}
|
||||
|
||||
func TestShouldFailIfNotEnoughQCSignatures(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue