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.
|
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:
|
// The work package consists of 3 strings:
|
||||||
// result[0] - 32 bytes hex encoded current block header pow-hash
|
// result[0] - 32 bytes hex encoded current block header pow-hash
|
||||||
// result[1] - 32 bytes hex encoded seed hash used for DAG
|
// result[1] - 32 bytes hex encoded seed hash used for DAG
|
||||||
// result[2] - 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty
|
// 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 {
|
if api.ethash.config.PowMode != ModeNormal && api.ethash.config.PowMode != ModeTest {
|
||||||
return [3]string{}, errors.New("not supported")
|
return [3]string{}, errors.New("not supported")
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +51,7 @@ func (api *API) GetWork() ([3]string, error) {
|
||||||
)
|
)
|
||||||
|
|
||||||
select {
|
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:
|
case <-api.ethash.exitCh:
|
||||||
return [3]string{}, errEthashStopped
|
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.
|
// SubmitWork can be used by external miner to submit their POW solution.
|
||||||
// It returns an indication if the work was accepted.
|
// It returns an indication if the work was accepted.
|
||||||
// Note either an invalid solution, a stale work a non-existent work will return false.
|
// Note either an invalid solution, a stale work a non-existent work will return false.
|
||||||
|
|
|
||||||
|
|
@ -431,8 +431,9 @@ type hashrate struct {
|
||||||
|
|
||||||
// sealWork wraps a seal work package for remote sealer.
|
// sealWork wraps a seal work package for remote sealer.
|
||||||
type sealWork struct {
|
type sealWork struct {
|
||||||
errc chan error
|
extra string // The specified string used to fill the block extra field
|
||||||
res chan [3]string
|
errc chan error
|
||||||
|
res chan [3]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ethash is a consensus engine based on proof-of-work implementing the ethash
|
// Ethash is a consensus engine based on proof-of-work implementing the ethash
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,7 @@ func TestRemoteSealer(t *testing.T) {
|
||||||
if res := api.SubmitWork(types.BlockNonce{}, sealhash, common.Hash{}); res {
|
if res := api.SubmitWork(types.BlockNonce{}, sealhash, common.Hash{}); res {
|
||||||
t.Error("expect to return false when submit a fake solution")
|
t.Error("expect to return false when submit a fake solution")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push new block with same block number to replace the original one.
|
// Push new block with same block number to replace the original one.
|
||||||
header = &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(1000)}
|
header = &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(1000)}
|
||||||
block = types.NewBlockWithHeader(header)
|
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) {
|
func TestHashRate(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
hashrate = []hexutil.Uint64{100, 200, 300}
|
hashrate = []hexutil.Uint64{100, 200, 300}
|
||||||
|
|
|
||||||
|
|
@ -245,6 +245,24 @@ func (ethash *Ethash) remote(notify []string, noverify bool) {
|
||||||
currentBlock = block
|
currentBlock = block
|
||||||
works[hash] = 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
|
// submitWork verifies the submitted pow solution, returning
|
||||||
// whether the solution was accepted or not (not can be both a bad pow as well as
|
// 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).
|
// any other error, like no pending work or stale mining result).
|
||||||
|
|
@ -313,11 +331,16 @@ func (ethash *Ethash) remote(notify []string, noverify bool) {
|
||||||
notifyWork()
|
notifyWork()
|
||||||
|
|
||||||
case work := <-ethash.fetchWorkCh:
|
case work := <-ethash.fetchWorkCh:
|
||||||
// Return current mining work to remote miner.
|
|
||||||
if currentBlock == nil {
|
if currentBlock == nil {
|
||||||
|
// Return error message if there is no available mining work yet.
|
||||||
work.errc <- errNoMiningWork
|
work.errc <- errNoMiningWork
|
||||||
} else {
|
} else if work.extra == "" {
|
||||||
|
// Return the default current mining work if no extra customized data
|
||||||
|
// specified.
|
||||||
work.res <- currentWork
|
work.res <- currentWork
|
||||||
|
} else {
|
||||||
|
// Return the customized mining work.
|
||||||
|
work.res <- customizeWork(work.extra)
|
||||||
}
|
}
|
||||||
|
|
||||||
case result := <-ethash.submitWorkCh:
|
case result := <-ethash.submitWorkCh:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue