This commit is contained in:
Peter Pratscher 2018-08-09 10:18:09 +00:00 committed by GitHub
commit 2b9cf5d8a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 138 additions and 0 deletions

View file

@ -122,6 +122,7 @@ var (
utils.GpoBlocksFlag, utils.GpoBlocksFlag,
utils.GpoPercentileFlag, utils.GpoPercentileFlag,
utils.ExtraDataFlag, utils.ExtraDataFlag,
utils.NotifyWorkFlag,
configFileFlag, configFileFlag,
} }

View file

@ -189,6 +189,7 @@ var AppHelpFlagGroups = []flagGroup{
utils.TargetGasLimitFlag, utils.TargetGasLimitFlag,
utils.GasPriceFlag, utils.GasPriceFlag,
utils.ExtraDataFlag, utils.ExtraDataFlag,
utils.NotifyWorkFlag,
}, },
}, },
{ {

View file

@ -341,6 +341,10 @@ var (
Name: "extradata", Name: "extradata",
Usage: "Block extra data set by the miner (default = client version)", Usage: "Block extra data set by the miner (default = client version)",
} }
NotifyWorkFlag = cli.StringFlag{
Name: "notifywork",
Usage: "URLs to which work package notifications are pushed. URLS should be a comma-delimited list of HTTP URLs.",
}
// Account settings // Account settings
UnlockedAccountFlag = cli.StringFlag{ UnlockedAccountFlag = cli.StringFlag{
Name: "unlock", Name: "unlock",
@ -1099,6 +1103,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
if ctx.GlobalIsSet(ExtraDataFlag.Name) { if ctx.GlobalIsSet(ExtraDataFlag.Name) {
cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name)) cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name))
} }
if ctx.GlobalIsSet(NotifyWorkFlag.Name) {
cfg.NotifyWork = ctx.GlobalString(NotifyWorkFlag.Name)
}
if ctx.GlobalIsSet(GasPriceFlag.Name) { if ctx.GlobalIsSet(GasPriceFlag.Name) {
cfg.GasPrice = GlobalBig(ctx, GasPriceFlag.Name) cfg.GasPrice = GlobalBig(ctx, GasPriceFlag.Name)
} }

View file

@ -170,6 +170,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine) eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine)
eth.miner.SetExtra(makeExtraData(config.ExtraData)) eth.miner.SetExtra(makeExtraData(config.ExtraData))
// Set up mining work push notifications if requested
if len(config.NotifyWork) > 0 {
eth.miner.Register(miner.NewNotificationAgent(eth.blockchain, eth.engine, config.NotifyWork))
}
eth.APIBackend = &EthAPIBackend{eth, nil} eth.APIBackend = &EthAPIBackend{eth, nil}
gpoParams := config.GPO gpoParams := config.GPO
if gpoParams.Default == nil { if gpoParams.Default == nil {

View file

@ -98,6 +98,7 @@ type Config struct {
Etherbase common.Address `toml:",omitempty"` Etherbase common.Address `toml:",omitempty"`
MinerThreads int `toml:",omitempty"` MinerThreads int `toml:",omitempty"`
ExtraData []byte `toml:",omitempty"` ExtraData []byte `toml:",omitempty"`
NotifyWork string `toml:",omitempty"`
GasPrice *big.Int GasPrice *big.Int
// Ethash options // Ethash options

123
miner/notification_agent.go Normal file
View file

@ -0,0 +1,123 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package miner
import (
"sync"
"bytes"
"encoding/json"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/log"
"math/big"
"net/http"
"strings"
"time"
)
// The notification agent pushes new work packages to a preset list of HTTP endpoints
type NotificationAgent struct {
wg sync.WaitGroup
workCh chan *Work
stop chan struct{}
returnCh chan<- *Result
targets []string
client *http.Client
chain consensus.ChainReader
engine consensus.Engine
}
func NewNotificationAgent(chain consensus.ChainReader, engine consensus.Engine, targets string) *NotificationAgent {
miner := &NotificationAgent{
chain: chain,
engine: engine,
stop: make(chan struct{}, 1),
workCh: make(chan *Work, 1),
targets: strings.Split(targets, ","),
client: &http.Client{Timeout: time.Second * 10},
}
return miner
}
func (self *NotificationAgent) Work() chan<- *Work { return self.workCh }
func (self *NotificationAgent) SetReturnCh(ch chan<- *Result) { self.returnCh = ch }
func (self *NotificationAgent) Stop() {
self.stop <- struct{}{}
done:
// Empty work channel
for {
select {
case <-self.workCh:
default:
break done
}
}
}
func (self *NotificationAgent) Start() {
go self.update()
}
func (self *NotificationAgent) update() {
out:
for {
select {
case work := <-self.workCh:
var res [3]string
block := work.Block
res[0] = block.HashNoNonce().Hex()
seedHash := ethash.SeedHash(block.NumberU64())
res[1] = common.BytesToHash(seedHash).Hex()
// Calculate the "target" to be returned to the external miner
n := big.NewInt(1)
n.Lsh(n, 255)
n.Div(n, block.Difficulty())
n.Lsh(n, 1)
res[2] = common.BytesToHash(n.Bytes()).Hex()
resJson, err := json.Marshal(res)
if err != nil {
log.Error("Unable to marshal work package into JSON string")
continue
}
self.wg.Add(len(self.targets))
for _, target := range self.targets {
func(t string) {
_, err := self.client.Post(t, "application/json", bytes.NewBuffer(resJson))
if err != nil {
log.Error("Error invoking work notification handler", "handler", t, "err", err)
}
self.wg.Done()
}(target)
}
self.wg.Wait()
case <-self.stop:
break out
}
}
}
func (self *NotificationAgent) GetHashRate() int64 {
return 0
}