mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
Add new block header validator for store m2 data.
This commit is contained in:
parent
0ae81138f5
commit
5360513293
5 changed files with 86 additions and 3 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue