Skip to content

Commit

Permalink
K1Pool: improvements, fixes, extradata, MEV profit
Browse files Browse the repository at this point in the history
  • Loading branch information
Admin committed Jun 20, 2022
1 parent 2e855b3 commit ad87ca4
Show file tree
Hide file tree
Showing 13 changed files with 168 additions and 69 deletions.
2 changes: 1 addition & 1 deletion consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
//
// Note, the method returns immediately and will send the result async. More
// than one result may also be returned depending on the consensus algorithm.
func (beacon *Beacon) Seal(chain consensus.ChainHeaderReader, block *types.Block, profit *big.Int, results chan<- *types.Block, stop <-chan struct{}) error {
func (beacon *Beacon) Seal(chain consensus.ChainHeaderReader, block *types.Block, profit *big.Float, results chan<- types.SealResult, stop <-chan struct{}) error {
if !beacon.IsPoSHeader(block.Header()) {
return beacon.ethone.Seal(chain, block, profit, results, stop)
}
Expand Down
4 changes: 2 additions & 2 deletions consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ func (c *Clique) Authorize(signer common.Address, signFn SignerFn) {

// Seal implements consensus.Engine, attempting to create a sealed block using
// the local signing credentials.
func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, profit *big.Int, results chan<- *types.Block, stop <-chan struct{}) error {
func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, profit *big.Float, results chan<- types.SealResult, stop <-chan struct{}) error {
header := block.Header()

// Sealing the genesis block is not supported
Expand Down Expand Up @@ -651,7 +651,7 @@ func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, pro
}

select {
case results <- block.WithSeal(header):
case results <- types.SealResult{Block: block.WithSeal(header)}:
default:
log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header))
}
Expand Down
2 changes: 1 addition & 1 deletion consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ type Engine interface {
//
// Note, the method returns immediately and will send the result async. More
// than one result may also be returned depending on the consensus algorithm.
Seal(chain ChainHeaderReader, block *types.Block, profit *big.Int, results chan<- *types.Block, stop <-chan struct{}) error
Seal(chain ChainHeaderReader, block *types.Block, profit *big.Float, results chan<- types.SealResult, stop <-chan struct{}) error

// SealHash returns the hash of a block prior to it being sealed.
SealHash(header *types.Header) common.Hash
Expand Down
31 changes: 24 additions & 7 deletions consensus/ethash/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,45 +38,62 @@ type API struct {
// result[1] - 32 bytes hex encoded seed hash used for DAG
// result[2] - 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty
// result[3] - hex encoded block number
func (api *API) GetWork() ([4]string, error) {
// result[4], 32 bytes hex encoded parent block header pow-hash
// result[5], hex encoded gas limit
// result[6], hex encoded gas used
// result[7], hex encoded transaction count
// result[8], hex encoded uncle count
// result[9], RLP encoded header with additonal empty extra data bytes
// result[10], MEV Profit as float-to-string "0.124"
func (api *API) GetWork() ([11]string, error) {
if api.ethash.remote == nil {
return [4]string{}, errors.New("not supported")
return [11]string{}, errors.New("not supported")
}

var (
workCh = make(chan [5]string, 1)
workCh = make(chan [11]string, 1)
errc = make(chan error, 1)
)
select {
case api.ethash.remote.fetchWorkCh <- &sealWork{errc: errc, res: workCh}:
case <-api.ethash.remote.exitCh:
return [4]string{}, errEthashStopped
return [11]string{}, errEthashStopped
}
select {
case fullWork := <-workCh:
var work [4]string
var work [11]string
copy(work[:], fullWork[:4])

return work, nil
case err := <-errc:
return [4]string{}, err
return [11]string{}, err
}
}

// 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.
func (api *API) SubmitWork(nonce types.BlockNonce, hash, digest common.Hash) bool {
func (api *API) SubmitWork(nonce types.BlockNonce, hash, digest common.Hash, extraNonceStr *string) bool {
if api.ethash.remote == nil {
return false
}

var extraNonce []byte
if extraNonceStr != nil {
var err error
extraNonce, err = hexutil.Decode(*extraNonceStr)
if err != nil {
return false
}
}

var errc = make(chan error, 1)
select {
case api.ethash.remote.submitWorkCh <- &mineResult{
nonce: nonce,
mixDigest: digest,
hash: hash,
extraNonce: extraNonce,
errc: errc,
}:
case <-api.ethash.remote.exitCh:
Expand Down
8 changes: 4 additions & 4 deletions consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -573,14 +573,14 @@ func (ethash *Ethash) verifySeal(chain consensus.ChainHeaderReader, header *type
// until after the call to hashimotoLight so it's not unmapped while being used.
runtime.KeepAlive(cache)
}
// Verify the calculated values against the ones provided in the header
if !bytes.Equal(header.MixDigest[:], digest) {
return errInvalidMixDigest
}
target := new(big.Int).Div(two256, header.Difficulty)
if new(big.Int).SetBytes(result).Cmp(target) > 0 {
return errInvalidPoW
}
// Fix mix digest if PoW is valid
if !bytes.Equal(header.MixDigest[:], digest) {
header.MixDigest = common.BytesToHash(digest)
}
return nil
}

Expand Down
4 changes: 2 additions & 2 deletions consensus/ethash/ethash.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func (c *cache) generate(dir string, limit int, lock bool, test bool) {
size = 1024
}
// If we don't store anything on disk, generate and return.
if dir == "" {
if dir == "" || limit <= 0 {
c.cache = make([]uint32, size/4)
generateCache(c.cache, c.epoch, seed)
return
Expand Down Expand Up @@ -323,7 +323,7 @@ func (d *dataset) generate(dir string, limit int, lock bool, test bool) {
dsize = 32 * 1024
}
// If we don't store anything on disk, generate and return
if dir == "" {
if dir == "" || limit <= 0 {
cache := make([]uint32, csize/4)
generateCache(cache, d.epoch, seed)

Expand Down
17 changes: 9 additions & 8 deletions consensus/ethash/ethash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ func TestTestMode(t *testing.T) {
ethash := NewTester(nil, false)
defer ethash.Close()

results := make(chan *types.Block)
err := ethash.Seal(nil, types.NewBlockWithHeader(header), nil, results, nil)
results := make(chan types.SealResult)
err := ethash.Seal(nil, types.NewBlockWithHeader(header), big.NewFloat(0), results, nil)
if err != nil {
t.Fatalf("failed to seal block: %v", err)
}
select {
case block := <-results:
case result := <-results:
block := result.Block
header.Nonce = types.EncodeNonce(block.Nonce())
header.MixDigest = block.MixDigest()
if err := ethash.verifySeal(nil, header, false); err != nil {
Expand Down Expand Up @@ -111,25 +112,25 @@ func TestRemoteSealer(t *testing.T) {
sealhash := ethash.SealHash(header)

// Push new work.
results := make(chan *types.Block)
ethash.Seal(nil, block, nil, results, nil)
results := make(chan types.SealResult)
ethash.Seal(nil, block, big.NewFloat(0), results, nil)

var (
work [4]string
work [11]string
err error
)
if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() {
t.Error("expect to return a mining work has same hash")
}

if res := api.SubmitWork(types.BlockNonce{}, sealhash, common.Hash{}); res {
if res := api.SubmitWork(types.BlockNonce{}, sealhash, common.Hash{}, nil); 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)
sealhash = ethash.SealHash(header)
ethash.Seal(nil, block, nil, results, nil)
ethash.Seal(nil, block, big.NewFloat(0), results, nil)

if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() {
t.Error("expect to return the latest pushed work")
Expand Down
18 changes: 12 additions & 6 deletions consensus/ethash/flashbots_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,31 @@ type FlashbotsAPI struct {
// result[1] - 32 bytes hex encoded seed hash used for DAG
// result[2] - 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty
// result[3] - hex encoded block number
// result[4] - hex encoded profit generated from this block
func (api *FlashbotsAPI) GetWork() ([5]string, error) {
// result[4], 32 bytes hex encoded parent block header pow-hash
// result[5], hex encoded gas limit
// result[6], hex encoded gas used
// result[7], hex encoded transaction count
// result[8], hex encoded uncle count
// result[9], RLP encoded header with additonal empty extra data bytes
// result[11], MEV Profit as float-to-string "0.124"
func (api *FlashbotsAPI) GetWork() ([11]string, error) {
if api.ethash.remote == nil {
return [5]string{}, errors.New("not supported")
return [11]string{}, errors.New("not supported")
}

var (
workCh = make(chan [5]string, 1)
workCh = make(chan [11]string, 1)
errc = make(chan error, 1)
)
select {
case api.ethash.remote.fetchWorkCh <- &sealWork{errc: errc, res: workCh}:
case <-api.ethash.remote.exitCh:
return [5]string{}, errEthashStopped
return [11]string{}, errEthashStopped
}
select {
case work := <-workCh:
return work, nil
case err := <-errc:
return [5]string{}, err
return [11]string{}, err
}
}
Loading

0 comments on commit ad87ca4

Please sign in to comment.