consensus, core, ethstats: use engine specific block beneficiary

This commit is contained in:
Péter Szilágyi 2017-04-12 12:50:12 +03:00
parent 9de257505b
commit 4fca35e2eb
No known key found for this signature in database
GPG key ID: E9AE538CEDF8293D
10 changed files with 55 additions and 8 deletions

View file

@ -220,6 +220,12 @@ func New(config *params.CliqueConfig, db ethdb.Database) *Clique {
} }
} }
// Author implements consensus.Engine, returning the Ethereum address recovered
// from the signature in the header's extra-data section.
func (c *Clique) Author(header *types.Header) (common.Address, error) {
return ecrecover(header)
}
// VerifyHeader checks whether a header conforms to the consensus rules. // VerifyHeader checks whether a header conforms to the consensus rules.
func (c *Clique) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { func (c *Clique) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
return c.verifyHeader(chain, header, nil) return c.verifyHeader(chain, header, nil)

View file

@ -46,6 +46,11 @@ type ChainReader interface {
// Engine is an algorithm agnostic consensus engine. // Engine is an algorithm agnostic consensus engine.
type Engine interface { type Engine interface {
// Author retrieves the Ethereum address of the account that minted the given
// block, which may be different from the header's coinbase if a consensus
// engine is based on signatures.
Author(header *types.Header) (common.Address, error)
// VerifyHeader checks whether a header conforms to the consensus rules of a // VerifyHeader checks whether a header conforms to the consensus rules of a
// given engine. Verifying the seal may be done optionally here, or explicitly // given engine. Verifying the seal may be done optionally here, or explicitly
// via the VerifySeal method. // via the VerifySeal method.

View file

@ -59,6 +59,12 @@ var (
errInvalidPoW = errors.New("invalid proof-of-work") errInvalidPoW = errors.New("invalid proof-of-work")
) )
// Author implements consensus.Engine, returning the header's coinbase as the
// proof-of-work verified author of the block.
func (ethash *Ethash) Author(header *types.Header) (common.Address, error) {
return header.Coinbase, nil
}
// VerifyHeader checks whether a header conforms to the consensus rules of the // VerifyHeader checks whether a header conforms to the consensus rules of the
// stock Ethereum ethash engine. // stock Ethereum ethash engine.
func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {

View file

@ -1398,3 +1398,6 @@ func (self *BlockChain) GetHeaderByNumber(number uint64) *types.Header {
// Config retrieves the blockchain's chain configuration. // Config retrieves the blockchain's chain configuration.
func (self *BlockChain) Config() *params.ChainConfig { return self.config } func (self *BlockChain) Config() *params.ChainConfig { return self.config }
// Engine retrieves the blockchain's consensus engine.
func (self *BlockChain) Engine() consensus.Engine { return self.engine }

View file

@ -85,7 +85,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
b.SetCoinbase(common.Address{}) b.SetCoinbase(common.Address{})
} }
b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs)) b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs))
receipt, _, err := ApplyTransaction(b.config, nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{}) receipt, _, err := ApplyTransaction(b.config, &BlockChain{engine: ethash.NewFaker()}, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -20,25 +20,34 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
) )
// BlockFetcher retrieves headers by their hash // ChainContext supports retrieving headers and consensus parameters from the
type HeaderFetcher interface { // current blockchain to be used during transaction processing.
// GetHeader returns the hash corresponding to their hash type ChainContext interface {
// Engine retrieves the chain's consensus engine.
Engine() consensus.Engine
// GetHeader returns the hash corresponding to their hash.
GetHeader(common.Hash, uint64) *types.Header GetHeader(common.Hash, uint64) *types.Header
} }
// NewEVMContext creates a new context for use in the EVM. // NewEVMContext creates a new context for use in the EVM.
func NewEVMContext(msg Message, header *types.Header, chain HeaderFetcher) vm.Context { func NewEVMContext(msg Message, header *types.Header, chain ChainContext) vm.Context {
author, err := chain.Engine().Author(header)
if err != nil {
// Explicitly ignore, don't crash. Header is invalid.
}
return vm.Context{ return vm.Context{
CanTransfer: CanTransfer, CanTransfer: CanTransfer,
Transfer: Transfer, Transfer: Transfer,
GetHash: GetHashFn(header, chain), GetHash: GetHashFn(header, chain),
Origin: msg.From(), Origin: msg.From(),
Coinbase: header.Coinbase, Coinbase: author,
BlockNumber: new(big.Int).Set(header.Number), BlockNumber: new(big.Int).Set(header.Number),
Time: new(big.Int).Set(header.Time), Time: new(big.Int).Set(header.Time),
Difficulty: new(big.Int).Set(header.Difficulty), Difficulty: new(big.Int).Set(header.Difficulty),
@ -48,7 +57,7 @@ func NewEVMContext(msg Message, header *types.Header, chain HeaderFetcher) vm.Co
} }
// GetHashFn returns a GetHashFunc which retrieves header hashes by number // GetHashFn returns a GetHashFunc which retrieves header hashes by number
func GetHashFn(ref *types.Header, chain HeaderFetcher) func(n uint64) common.Hash { func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash {
return func(n uint64) common.Hash { return func(n uint64) common.Hash {
for header := chain.GetHeader(ref.ParentHash, ref.Number.Uint64()-1); header != nil; header = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) { for header := chain.GetHeader(ref.ParentHash, ref.Number.Uint64()-1); header != nil; header = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) {
if header.Number.Uint64() == n { if header.Number.Uint64() == n {

View file

@ -442,6 +442,9 @@ func (hc *HeaderChain) SetGenesis(head *types.Header) {
// Config retrieves the header chain's chain configuration. // Config retrieves the header chain's chain configuration.
func (hc *HeaderChain) Config() *params.ChainConfig { return hc.config } func (hc *HeaderChain) Config() *params.ChainConfig { return hc.config }
// Engine retrieves the header chain's consensus engine.
func (hc *HeaderChain) Engine() consensus.Engine { return hc.engine }
// GetBlock implements consensus.ChainReader, and returns nil for every input as // GetBlock implements consensus.ChainReader, and returns nil for every input as
// a header chain does not have blocks available for retrieval. // a header chain does not have blocks available for retrieval.
func (hc *HeaderChain) GetBlock(hash common.Hash, number uint64) *types.Block { func (hc *HeaderChain) GetBlock(hash common.Hash, number uint64) *types.Block {

View file

@ -30,6 +30,7 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
@ -54,6 +55,7 @@ type Service struct {
server *p2p.Server // Peer-to-peer server to retrieve networking infos server *p2p.Server // Peer-to-peer server to retrieve networking infos
eth *eth.Ethereum // Full Ethereum service if monitoring a full node eth *eth.Ethereum // Full Ethereum service if monitoring a full node
les *les.LightEthereum // Light Ethereum service if monitoring a light node les *les.LightEthereum // Light Ethereum service if monitoring a light node
engine consensus.Engine // Consensus engine to retrieve variadic block fields
node string // Name of the node to display on the monitoring page node string // Name of the node to display on the monitoring page
pass string // Password to authorize access to the monitoring page pass string // Password to authorize access to the monitoring page
@ -72,9 +74,16 @@ func New(url string, ethServ *eth.Ethereum, lesServ *les.LightEthereum) (*Servic
return nil, fmt.Errorf("invalid netstats url: \"%s\", should be nodename:secret@host:port", url) return nil, fmt.Errorf("invalid netstats url: \"%s\", should be nodename:secret@host:port", url)
} }
// Assemble and return the stats service // Assemble and return the stats service
var engine consensus.Engine
if ethServ != nil {
engine = ethServ.Engine()
} else {
engine = lesServ.Engine()
}
return &Service{ return &Service{
eth: ethServ, eth: ethServ,
les: lesServ, les: lesServ,
engine: engine,
node: parts[1], node: parts[1],
pass: parts[3], pass: parts[3],
host: parts[4], host: parts[4],
@ -493,12 +502,14 @@ func (s *Service) assembleBlockStats(block *types.Block) *blockStats {
td = s.les.BlockChain().GetTd(header.Hash(), header.Number.Uint64()) td = s.les.BlockChain().GetTd(header.Hash(), header.Number.Uint64())
} }
// Assemble and return the block stats // Assemble and return the block stats
author, _ := s.engine.Author(header)
return &blockStats{ return &blockStats{
Number: header.Number, Number: header.Number,
Hash: header.Hash(), Hash: header.Hash(),
ParentHash: header.ParentHash, ParentHash: header.ParentHash,
Timestamp: header.Time, Timestamp: header.Time,
Miner: header.Coinbase, Miner: author,
GasUsed: new(big.Int).Set(header.GasUsed), GasUsed: new(big.Int).Set(header.GasUsed),
GasLimit: new(big.Int).Set(header.GasLimit), GasLimit: new(big.Int).Set(header.GasLimit),
Diff: header.Difficulty.String(), Diff: header.Difficulty.String(),

View file

@ -176,6 +176,7 @@ func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) {
func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain } func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain }
func (s *LightEthereum) TxPool() *light.TxPool { return s.txPool } func (s *LightEthereum) TxPool() *light.TxPool { return s.txPool }
func (s *LightEthereum) Engine() consensus.Engine { return s.engine }
func (s *LightEthereum) LesVersion() int { return int(s.protocolManager.SubProtocols[0].Version) } func (s *LightEthereum) LesVersion() int { return int(s.protocolManager.SubProtocols[0].Version) }
func (s *LightEthereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } func (s *LightEthereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }
func (s *LightEthereum) EventMux() *event.TypeMux { return s.eventMux } func (s *LightEthereum) EventMux() *event.TypeMux { return s.eventMux }

View file

@ -213,6 +213,9 @@ func (bc *LightChain) ResetWithGenesisBlock(genesis *types.Block) {
// Accessors // Accessors
// Engine retrieves the light chain's consensus engine.
func (bc *LightChain) Engine() consensus.Engine { return bc.engine }
// Genesis returns the genesis block // Genesis returns the genesis block
func (bc *LightChain) Genesis() *types.Block { func (bc *LightChain) Genesis() *types.Block {
return bc.genesisBlock return bc.genesisBlock