Skip to content

Commit

Permalink
Merge branch 'feat/fakepow-delaysealer' into rc/messnet-1
Browse files Browse the repository at this point in the history
Conflicts:
      go.mod
      go.sum
  • Loading branch information
meowsbits committed Sep 13, 2020
2 parents 5bc3fc2 + 0177c08 commit 5c5b001
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 45 deletions.
3 changes: 3 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -1415,6 +1415,9 @@ func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
}

func setEthash(ctx *cli.Context, cfg *eth.Config) {
if ctx.GlobalBool(FakePoWFlag.Name) {
cfg.Ethash.PowMode = ethash.ModeFake
}
if ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name)
}
Expand Down
16 changes: 16 additions & 0 deletions consensus/ethash/ethash.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,22 @@ const (
ModeFullFake
)

func (m Mode) String() string {
switch m {
case ModeNormal:
return "Normal"
case ModeShared:
return "Shared"
case ModeTest:
return "Test"
case ModeFake:
return "Fake"
case ModeFullFake:
return "FullFake"
}
return "unknown"
}

// Config are the configuration parameters of the ethash.
type Config struct {
CacheDir string
Expand Down
52 changes: 44 additions & 8 deletions consensus/ethash/sealer.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/types"
"gonum.org/v1/gonum/stat/distuv"
)

const (
Expand All @@ -46,18 +47,53 @@ var (
errInvalidSealResult = errors.New("invalid or stale proof-of-work solution")
)

// makeFakeDelay uses the ethash.threads value as a mean time (lambda)
// for a Poisson distribution, returning a random value from
// that discrete function. I think a Poisson distribution probably
// fairly accurately models real world block times.
// Note that this is a hacky way to use ethash.threads since
// lower values will yield faster blocks, but it saves having
// to add or modify any more code than necessary.
func (ethash *Ethash) makeFakeDelay() float64 {
p := distuv.Poisson{
Lambda: float64(ethash.Threads()),
}
return p.Rand()
}

// Seal implements consensus.Engine, attempting to find a nonce that satisfies
// the block's difficulty requirements.
func (ethash *Ethash) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
// If we're running a fake PoW, simply return a 0 nonce immediately
if ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModeFullFake {
header := block.Header()
header.Nonce, header.MixDigest = types.BlockNonce{}, common.Hash{}
select {
case results <- block.WithSeal(header):
default:
ethash.config.Log.Warn("Sealing result is not read by miner", "mode", "fake", "sealhash", ethash.SealHash(block.Header()))
}
faking := ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModeFullFake
if faking {
go func(header *types.Header) {
// Assign random (but non-zero) values to header nonce and mix.
header.Nonce = types.EncodeNonce(uint64(rand.Int63n(math.MaxInt64)))
b, _ := header.Nonce.MarshalText()
header.MixDigest = common.BytesToHash(b)

// Wait some amount of time.
timeout := time.NewTimer(time.Duration(ethash.makeFakeDelay()) * time.Second)
defer timeout.Stop()

select {
case <-stop:
return
case <-ethash.update:
timeout.Stop()
if err := ethash.Seal(chain, block, results, stop); err != nil {
ethash.config.Log.Error("Failed to restart sealing after update", "err", err)
}
case <-timeout.C:
// Send the results when the timeout expires.
select {
case results <- block.WithSeal(header):
default:
ethash.config.Log.Warn("Sealing result is not read by miner", "mode", "fake", "sealhash", ethash.SealHash(block.Header()))
}
}
}(block.Header())
return nil
}
// If we're running a shared PoW, delegate sealing to it
Expand Down
19 changes: 19 additions & 0 deletions consensus/ethash/sealer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"math/big"
"net/http"
"net/http/httptest"
"sort"
"testing"
"time"

Expand All @@ -31,6 +32,24 @@ import (
"github.com/ethereum/go-ethereum/log"
)

func TestSealFakeDelay(t *testing.T) {
cases := []int{
3, 10, 19, 33,
}
for _, c := range cases {
e := &Ethash{threads: c} // "threads" is actually the desired MEAN (lambda) of the Poisson distribution
got := []float64{}
for i := 0; i < 20; i++ {
d := e.makeFakeDelay()
got = append(got, d)
}
sort.Slice(got, func(i, j int) bool {
return got[i] < got[j]
})
t.Logf("ethash.threads,lamda=%2d %v", c, got)
}
}

// Tests whether remote HTTP servers are correctly notified of new work.
func TestRemoteNotify(t *testing.T) {
// Start a simple web server to capture notifications.
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ require (
golang.org/x/text v0.3.3
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
gonum.org/v1/plot v0.8.0
gonum.org/v1/gonum v0.8.1
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6
gopkg.in/urfave/cli.v1 v1.20.0
Expand Down
Loading

0 comments on commit 5c5b001

Please sign in to comment.