mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
consensus: customized getWork endpoint
This commit is contained in:
parent
7c71e936a7
commit
dc62da5c8c
4 changed files with 72 additions and 7 deletions
|
|
@ -31,13 +31,16 @@ type API struct {
|
|||
ethash *Ethash // Make sure the mode of ethash is normal.
|
||||
}
|
||||
|
||||
// GetWork returns a work package for external miner.
|
||||
// getWork returns a work package for external miner.
|
||||
//
|
||||
// User can specify a customized extra to replace the extra field
|
||||
// in the block header when the given string is not empty.
|
||||
//
|
||||
// The work package consists of 3 strings:
|
||||
// result[0] - 32 bytes hex encoded current block header pow-hash
|
||||
// result[1] - 32 bytes hex encoded seed hash used for DAG
|
||||
// result[2] - 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty
|
||||
func (api *API) GetWork() ([3]string, error) {
|
||||
func (api *API) getWork(extra string) ([3]string, error) {
|
||||
if api.ethash.config.PowMode != ModeNormal && api.ethash.config.PowMode != ModeTest {
|
||||
return [3]string{}, errors.New("not supported")
|
||||
}
|
||||
|
|
@ -48,7 +51,7 @@ func (api *API) GetWork() ([3]string, error) {
|
|||
)
|
||||
|
||||
select {
|
||||
case api.ethash.fetchWorkCh <- &sealWork{errc: errc, res: workCh}:
|
||||
case api.ethash.fetchWorkCh <- &sealWork{extra: extra, errc: errc, res: workCh}:
|
||||
case <-api.ethash.exitCh:
|
||||
return [3]string{}, errEthashStopped
|
||||
}
|
||||
|
|
@ -61,6 +64,18 @@ func (api *API) GetWork() ([3]string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// GetWork returns a default work package for external miner.
|
||||
//
|
||||
// Note this function is a legacy for backward compatibility.
|
||||
func (api *API) GetWork() ([3]string, error) {
|
||||
return api.getWork("")
|
||||
}
|
||||
|
||||
// GetCustomizedWork returns a customized work package for external miner.
|
||||
func (api *API) GetCustomizedWork(extra string) ([3]string, error) {
|
||||
return api.getWork(extra)
|
||||
}
|
||||
|
||||
// SubmitWork can be used by external miner to submit their POW solution.
|
||||
// It returns an indication if the work was accepted.
|
||||
// Note either an invalid solution, a stale work a non-existent work will return false.
|
||||
|
|
|
|||
|
|
@ -431,6 +431,7 @@ type hashrate struct {
|
|||
|
||||
// sealWork wraps a seal work package for remote sealer.
|
||||
type sealWork struct {
|
||||
extra string // The specified string used to fill the block extra field
|
||||
errc chan error
|
||||
res chan [3]string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ func TestRemoteSealer(t *testing.T) {
|
|||
if res := api.SubmitWork(types.BlockNonce{}, sealhash, common.Hash{}); res {
|
||||
t.Error("expect to return false when submit a fake solution")
|
||||
}
|
||||
|
||||
// Push new block with same block number to replace the original one.
|
||||
header = &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(1000)}
|
||||
block = types.NewBlockWithHeader(header)
|
||||
|
|
@ -128,6 +129,31 @@ func TestRemoteSealer(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCustomizedWork(t *testing.T) {
|
||||
ethash := NewTester(nil, true)
|
||||
defer ethash.Close()
|
||||
|
||||
api := &API{ethash}
|
||||
header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)}
|
||||
block := types.NewBlockWithHeader(header)
|
||||
|
||||
// Push new work.
|
||||
results := make(chan *types.Block, 1)
|
||||
ethash.Seal(nil, block, results, nil)
|
||||
|
||||
// Get customized mining work.
|
||||
expect := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100), Extra: []byte("extra")}
|
||||
expectSealhash := ethash.SealHash(expect)
|
||||
if work, err := api.GetCustomizedWork("extra"); err != nil || work[0] != expectSealhash.Hex() {
|
||||
t.Errorf("expect to return a customized work, have %s, want %s", work[0], expectSealhash.Hex())
|
||||
}
|
||||
|
||||
// Submit fake solution for customized work
|
||||
if !api.SubmitWork(types.BlockNonce{}, expectSealhash, common.Hash{}) {
|
||||
t.Error("submit solution for customized work failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashRate(t *testing.T) {
|
||||
var (
|
||||
hashrate = []hexutil.Uint64{100, 200, 300}
|
||||
|
|
|
|||
|
|
@ -245,6 +245,24 @@ func (ethash *Ethash) remote(notify []string, noverify bool) {
|
|||
currentBlock = block
|
||||
works[hash] = block
|
||||
}
|
||||
// customizeWork creates a work package for external miner
|
||||
// with customized extra data.
|
||||
customizeWork := func(extra string) [3]string {
|
||||
newHeader := currentBlock.Header()
|
||||
newHeader.Extra = []byte(extra)
|
||||
newBlock := types.NewBlockWithHeader(newHeader)
|
||||
|
||||
// Recalculate mining work
|
||||
var work [3]string
|
||||
hash := ethash.SealHash(newHeader)
|
||||
work[0] = hash.Hex()
|
||||
work[1] = currentWork[1]
|
||||
work[2] = currentWork[2]
|
||||
|
||||
// Trace the seal work fetched by remote sealer.
|
||||
works[hash] = newBlock
|
||||
return work
|
||||
}
|
||||
// submitWork verifies the submitted pow solution, returning
|
||||
// whether the solution was accepted or not (not can be both a bad pow as well as
|
||||
// any other error, like no pending work or stale mining result).
|
||||
|
|
@ -313,11 +331,16 @@ func (ethash *Ethash) remote(notify []string, noverify bool) {
|
|||
notifyWork()
|
||||
|
||||
case work := <-ethash.fetchWorkCh:
|
||||
// Return current mining work to remote miner.
|
||||
if currentBlock == nil {
|
||||
// Return error message if there is no available mining work yet.
|
||||
work.errc <- errNoMiningWork
|
||||
} else {
|
||||
} else if work.extra == "" {
|
||||
// Return the default current mining work if no extra customized data
|
||||
// specified.
|
||||
work.res <- currentWork
|
||||
} else {
|
||||
// Return the customized mining work.
|
||||
work.res <- customizeWork(work.extra)
|
||||
}
|
||||
|
||||
case result := <-ethash.submitWorkCh:
|
||||
|
|
|
|||
Loading…
Reference in a new issue