Add new block header validator for store m2 data.

This commit is contained in:
DinhLN 2018-10-24 15:06:49 +07:00 committed by Tuna
parent 0ae81138f5
commit 5360513293
5 changed files with 86 additions and 3 deletions

View file

@ -179,6 +179,10 @@ func sigHash(header *types.Header) (hash common.Hash) {
return hash
}
func SigHash(header *types.Header) (hash common.Hash) {
return sigHash(header)
}
// ecrecover extracts the Ethereum account address from a signed header.
func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) {
// If the signature's already cached, return that
@ -645,7 +649,7 @@ func (c *Posv) verifySeal(chain consensus.ChainReader, header *types.Header, par
}
// verify validator
assignedValidator, err := c.getValidator(creator, snap, chain, header)
assignedValidator, err := c.GetValidator(creator, snap, chain, header)
if err != nil {
return err
}
@ -656,7 +660,7 @@ func (c *Posv) verifySeal(chain consensus.ChainReader, header *types.Header, par
return nil
}
func (c *Posv) getValidator(creator common.Address, snap *Snapshot, chain consensus.ChainReader, header *types.Header) (common.Address, error) {
func (c *Posv) GetValidator(creator common.Address, snap *Snapshot, chain consensus.ChainReader, header *types.Header) (common.Address, error) {
epoch := c.config.Epoch
no := header.Number.Uint64()
cpNo := no
@ -946,6 +950,30 @@ func (c *Posv) RecoverSigner(header *types.Header) (common.Address, error) {
return ecrecover(header, c.signatures)
}
func (c *Posv) RecoverValidator(header *types.Header) (common.Address, error) {
// If the signature's already cached, return that
hash := header.Hash()
if address, known := c.signatures.Get(hash); known {
return address.(common.Address), nil
}
// Retrieve the signature from the header extra-data
if len(header.Validator) < extraSeal {
return common.Address{}, errMissingSignature
}
signature := header.Validator[len(header.Validator)-extraSeal:]
// Recover the public key and the Ethereum address
pubkey, err := crypto.Ecrecover(sigHash(header).Bytes(), signature)
if err != nil {
return common.Address{}, err
}
var signer common.Address
copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
c.signatures.Add(hash, signer)
return signer, nil
}
// Get master nodes over extra data of previous checkpoint block.
func (c *Posv) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types.Header, n, e uint64) []common.Address {
if preCheckpointHeader == nil {

View file

@ -85,6 +85,7 @@ type Header struct {
MixDigest common.Hash `json:"mixHash" gencodec:"required"`
Nonce BlockNonce `json:"nonce" gencodec:"required"`
Validators []byte `json:"validators" gencodec:"required"`
Validator []byte `json:"validator" gencodec:"required"`
Penalties []byte `json:"penalties" gencodec:"required"`
}
@ -256,6 +257,10 @@ func CopyHeader(h *Header) *Header {
cpy.Extra = make([]byte, len(h.Extra))
copy(cpy.Extra, h.Extra)
}
if len(h.Validator) > 0 {
cpy.Validator = make([]byte, len(h.Validator))
copy(cpy.Validator, h.Validator)
}
return &cpy
}
@ -322,6 +327,7 @@ func (b *Block) ReceiptHash() common.Hash { return b.header.ReceiptHash }
func (b *Block) UncleHash() common.Hash { return b.header.UncleHash }
func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Extra) }
func (b *Block) Penalties() []byte { return common.CopyBytes(b.header.Penalties) }
func (b *Block) Validator() []byte { return common.CopyBytes(b.header.Validator) }
func (b *Block) Header() *Header { return CopyHeader(b.header) }

View file

@ -187,7 +187,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
if eth.chainConfig.Posv != nil {
c := eth.engine.(*posv.Posv)
signHook := func(block *types.Block) error {
if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil {
return fmt.Errorf("Fail to create tx sign for importing block: %v", err)
@ -195,7 +194,41 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
return nil
}
appendM2HeaderHook := func(block *types.Block) (*types.Block, error) {
eb, err := eth.Etherbase()
if err != nil {
log.Error("Cannot get etherbase for append m2 header", "err", err)
return block, fmt.Errorf("etherbase missing: %v", err)
}
// Get m1.
snap, err := c.GetSnapshot(eth.blockchain, eth.blockchain.CurrentHeader())
if err != nil {
return block, fmt.Errorf("can't get snapshot: %v", err)
}
m1, err := c.RecoverSigner(block.Header())
if err != nil {
return block, fmt.Errorf("can't get block creator: %v", err)
}
m2, err := c.GetValidator(m1, snap, eth.blockchain, block.Header())
if err != nil {
return block, fmt.Errorf("can't get block validator: %v", err)
}
if m2 == eb {
wallet, _ := eth.accountManager.Find(accounts.Account{Address: eb})
header := block.Header()
sighash, _ := wallet.SignHash(accounts.Account{Address: eb}, posv.SigHash(header).Bytes())
header.Validator = sighash
block = types.NewBlockWithHeader(header)
//c := eth.engine.(*posv.Posv)
//validator, _ := c.RecoverValidator(block.Header())
//log.Error("addr", "addr", validator)
}
return block, nil
}
eth.protocolManager.fetcher.SetSignHook(signHook)
eth.protocolManager.fetcher.SetAppendM2HeaderHook(appendM2HeaderHook)
// Hook prepares validators M2 for the current epoch
c.HookValidator = func(header *types.Header, signers []common.Address) error {

View file

@ -144,6 +144,7 @@ type Fetcher struct {
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
appendM2HeaderHook func(*types.Block) (*types.Block, error)
}
// New creates a block fetcher to retrieve blocks based on hash announcements.
@ -653,6 +654,15 @@ func (f *Fetcher) insert(peer string, block *types.Block) {
// Quickly validate the header and propagate the block if it passes
switch err := f.verifyHeader(block.Header()); err {
case nil:
// Append m2 to block header.
// Invoke the dv hook to run double validation layer
if f.appendM2HeaderHook != nil {
if block, err = f.appendM2HeaderHook(block); err != nil {
log.Error("Append m2 to block header fail", "err", err)
return
}
}
// All ok, quickly propagate to our peers
propBroadcastOutTimer.UpdateSince(block.ReceivedAt)
go f.broadcastBlock(block, true)
@ -757,3 +767,8 @@ func (f *Fetcher) SetDoubleValidateHook(doubleValidateHook func(*types.Block) er
func (f *Fetcher) SetSignHook(signHook func(*types.Block) error) {
f.signHook = signHook
}
// Bind append m2 to block header hook when imported into chain.
func (f *Fetcher) SetAppendM2HeaderHook(appendM2HeaderHook func(*types.Block) (*types.Block, error)) {
f.appendM2HeaderHook = appendM2HeaderHook
}

View file

@ -817,6 +817,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
"transactionsRoot": head.TxHash,
"receiptsRoot": head.ReceiptHash,
"validators": hexutil.Bytes(head.Validators),
"validator": hexutil.Bytes(head.Validator),
"penalties": hexutil.Bytes(head.Penalties),
}