Merge pull request #238 from nguyenbatam/fix_dv

fix error double validation
This commit is contained in:
Tuna 2018-10-25 17:00:03 +07:00 committed by GitHub
commit d4051ee145
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 34 deletions

View file

@ -34,4 +34,6 @@ var (
// ErrInvalidNumber is returned if a block's number doesn't equal it's parent's // ErrInvalidNumber is returned if a block's number doesn't equal it's parent's
// plus one. // plus one.
ErrInvalidNumber = errors.New("invalid block number") ErrInvalidNumber = errors.New("invalid block number")
ErrMissingValidatorSignature = errors.New("missing validator in header")
) )

View file

@ -216,7 +216,7 @@ type Posv struct {
recents *lru.ARCCache // Snapshots for recent block to speed up reorgs recents *lru.ARCCache // Snapshots for recent block to speed up reorgs
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
validatorSignatures *lru.ARCCache // Signatures of recent blocks to speed up mining
proposals map[common.Address]bool // Current list of proposals we are pushing proposals map[common.Address]bool // Current list of proposals we are pushing
signer common.Address // Ethereum address of the signing key signer common.Address // Ethereum address of the signing key
@ -240,12 +240,13 @@ func New(config *params.PosvConfig, db ethdb.Database) *Posv {
// Allocate the snapshot caches and create the engine // Allocate the snapshot caches and create the engine
recents, _ := lru.NewARC(inmemorySnapshots) recents, _ := lru.NewARC(inmemorySnapshots)
signatures, _ := lru.NewARC(inmemorySignatures) signatures, _ := lru.NewARC(inmemorySignatures)
validatorSignatures, _ := lru.NewARC(inmemorySignatures)
return &Posv{ return &Posv{
config: &conf, config: &conf,
db: db, db: db,
recents: recents, recents: recents,
signatures: signatures, signatures: signatures,
validatorSignatures: validatorSignatures,
proposals: make(map[common.Address]bool), proposals: make(map[common.Address]bool),
} }
} }
@ -956,12 +957,12 @@ func (c *Posv) RecoverSigner(header *types.Header) (common.Address, error) {
func (c *Posv) RecoverValidator(header *types.Header) (common.Address, error) { func (c *Posv) RecoverValidator(header *types.Header) (common.Address, error) {
// If the signature's already cached, return that // If the signature's already cached, return that
hash := header.Hash() hash := header.Hash()
if address, known := c.signatures.Get(hash); known { if address, known := c.validatorSignatures.Get(hash); known {
return address.(common.Address), nil return address.(common.Address), nil
} }
// Retrieve the signature from the header extra-data // Retrieve the signature from the header extra-data
if len(header.Validator) < extraSeal { if len(header.Validator) < extraSeal {
return common.Address{}, errMissingSignature return common.Address{}, consensus.ErrMissingValidatorSignature
} }
signature := header.Validator[len(header.Validator)-extraSeal:] signature := header.Validator[len(header.Validator)-extraSeal:]
@ -973,7 +974,7 @@ func (c *Posv) RecoverValidator(header *types.Header) (common.Address, error) {
var signer common.Address var signer common.Address
copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
c.signatures.Add(hash, signer) c.validatorSignatures.Add(hash, signer)
return signer, nil return signer, nil
} }

View file

@ -142,7 +142,6 @@ type Fetcher struct {
queueChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a block from the import queue queueChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a block from the import queue
fetchingHook func([]common.Hash) // Method to call upon starting a block (eth/61) or header (eth/62) fetch fetchingHook func([]common.Hash) // Method to call upon starting a block (eth/61) or header (eth/62) fetch
completingHook func([]common.Hash) // Method to call upon starting a block body fetch (eth/62) completingHook func([]common.Hash) // Method to call upon starting a block body fetch (eth/62)
doubleValidateHook func(*types.Block) error
signHook func(*types.Block) error signHook func(*types.Block) error
appendM2HeaderHook func(*types.Block) (*types.Block, error) appendM2HeaderHook func(*types.Block) (*types.Block, error)
} }
@ -654,33 +653,30 @@ func (f *Fetcher) insert(peer string, block *types.Block) {
// Quickly validate the header and propagate the block if it passes // Quickly validate the header and propagate the block if it passes
switch err := f.verifyHeader(block.Header()); err { switch err := f.verifyHeader(block.Header()); err {
case nil: case nil:
// All ok, quickly propagate to our peers
propBroadcastOutTimer.UpdateSince(block.ReceivedAt)
go f.broadcastBlock(block, true)
case consensus.ErrFutureBlock:
case consensus.ErrMissingValidatorSignature:
newBlock := block
if f.appendM2HeaderHook != nil { if f.appendM2HeaderHook != nil {
if block, err = f.appendM2HeaderHook(block); err != nil { if newBlock, err = f.appendM2HeaderHook(block); err != nil {
log.Error("Append m2 to block header fail", "err", err) log.Error("Append m2 to block header fail", "err", err)
return return
} }
} }
// All ok, quickly propagate to our peers
propBroadcastOutTimer.UpdateSince(block.ReceivedAt)
go f.broadcastBlock(block, true) go f.broadcastBlock(block, true)
if newBlock.Hash() == block.Hash() {
case consensus.ErrFutureBlock: return
// Weird future block, don't fail, but neither propagate }
block = newBlock
propBroadcastOutTimer.UpdateSince(block.ReceivedAt)
default: default:
// Something went very wrong, drop the peer // Something went very wrong, drop the peer
log.Debug("Propagated block verification failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) log.Debug("Propagated block verification failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err)
f.dropPeer(peer) f.dropPeer(peer)
return return
} }
// Invoke the dv hook to run double validation layer
if f.doubleValidateHook != nil {
if err := f.doubleValidateHook(block); err != nil {
log.Error("Double validation failed", "err", err, "Discard this block!")
return
}
}
// Run the actual import and log any issues // Run the actual import and log any issues
if _, err := f.insertChain(types.Blocks{block}); err != nil { if _, err := f.insertChain(types.Blocks{block}); err != nil {
@ -756,11 +752,6 @@ func (f *Fetcher) forgetBlock(hash common.Hash) {
} }
} }
// Bind double validate hook before block imported into chain.
func (f *Fetcher) SetDoubleValidateHook(doubleValidateHook func(*types.Block) error) {
f.doubleValidateHook = doubleValidateHook
}
// Bind double validate hook before block imported into chain. // Bind double validate hook before block imported into chain.
func (f *Fetcher) SetSignHook(signHook func(*types.Block) error) { func (f *Fetcher) SetSignHook(signHook func(*types.Block) error) {
f.signHook = signHook f.signHook = signHook