Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ func (ethash *Ethash) VerifySeal(chain consensus.ChainHeaderReader, header *type
// to make remote mining fast.
func (ethash *Ethash) verifySeal(chain consensus.ChainHeaderReader, header *types.Header, fulldag bool) error {
// If we're running a fake PoW, accept any seal as valid
if ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModeFullFake {
if ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModePoissonFake || ethash.config.PowMode == ModeFullFake {
time.Sleep(ethash.fakeDelay)
if ethash.fakeFail == header.Number.Uint64() {
return errInvalidPoW
Expand Down
19 changes: 19 additions & 0 deletions consensus/ethash/ethash.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,9 +499,28 @@ const (
ModeShared
ModeTest
ModeFake
ModePoissonFake
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 ModePoissonFake:
return "PoissonFake"
case ModeFullFake:
return "FullFake"
}
return "unknown"
}

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

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

// makePoissonFakeDelay 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) makePoissonFakeDelay() float64 {
p := distuv.Poisson{
Lambda: float64(ethash.Threads()),
Comment thread
ziogaschr marked this conversation as resolved.
Src: exprand.NewSource(uint64(time.Now().UnixNano())),
}
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 {
Expand All @@ -59,6 +76,35 @@ func (ethash *Ethash) Seal(chain consensus.ChainHeaderReader, block *types.Block
ethash.config.Log.Warn("Sealing result is not read by miner", "mode", "fake", "sealhash", ethash.SealHash(block.Header()))
}
return nil
} else if ethash.config.PowMode == ModePoissonFake {
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.makePoissonFakeDelay()) * 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
if ethash.shared != nil {
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 TestSealFakePoisson(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.makePoissonFakeDelay()
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
9 changes: 4 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ require (
github.com/dlclark/regexp2 v1.2.0 // indirect
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498
github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813 // indirect
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c
github.com/fatih/color v1.7.0
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc
Expand All @@ -29,8 +28,8 @@ require (
github.com/go-test/deep v1.0.5
github.com/golang/protobuf v1.4.2
github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26
github.com/gorilla/websocket v1.4.2
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa
github.com/gorilla/websocket v1.4.2
github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277
github.com/hashicorp/golang-lru v0.5.4
github.com/holiman/uint256 v1.1.1
Expand Down Expand Up @@ -66,15 +65,15 @@ require (
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/mobile v0.0.0-20200801112145-973feb4309de // indirect
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8
golang.org/x/text v0.3.3
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
gonum.org/v1/gonum v0.8.1
gonum.org/v1/plot v0.8.0
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
gotest.tools v2.2.0+incompatible
gotest.tools v2.2.0+incompatible // indirect
)
Loading