Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workshares changes for stratum #2104

Merged
merged 2 commits into from
Sep 9, 2024
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
33 changes: 8 additions & 25 deletions consensus/blake3pow/consensus.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package blake3pow

import (
"errors"
"fmt"
"math/big"
"runtime"
Expand Down Expand Up @@ -47,22 +46,6 @@ var (
big2e256 = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0)) // 2^256
)

// Various error messages to mark blocks invalid. These should be private to
// prevent engine specific errors from being referenced in the remainder of the
// codebase, inherently breaking if the engine is swapped out. Please put common
// error types into the consensus package.
var (
errOlderBlockTime = errors.New("timestamp older than parent")
errTooManyUncles = errors.New("too many uncles")
errDuplicateUncle = errors.New("duplicate uncle")
errUncleIsAncestor = errors.New("uncle is ancestor")
errDanglingUncle = errors.New("uncle's parent is not ancestor")
errInvalidDifficulty = errors.New("non-positive difficulty")
errDifficultyCrossover = errors.New("sub's difficulty exceeds dom's")
errInvalidPoW = errors.New("invalid proof-of-work")
errInvalidOrder = errors.New("invalid order")
)

// Author implements consensus.Engine, returning the header's coinbase as the
// proof-of-work verified author of the block.
func (blake3pow *Blake3pow) Author(header *types.WorkObject) (common.Address, error) {
Expand Down Expand Up @@ -194,7 +177,7 @@ func (blake3pow *Blake3pow) VerifyUncles(chain consensus.ChainReader, block *typ
}
// Verify that there are at most params.MaxWorkShareCount uncles included in this block
if len(block.Uncles()) > params.MaxWorkShareCount {
return errTooManyUncles
return consensus.ErrTooManyUncles
}
if len(block.Uncles()) == 0 {
return nil
Expand Down Expand Up @@ -230,13 +213,13 @@ func (blake3pow *Blake3pow) VerifyUncles(chain consensus.ChainReader, block *typ
// Make sure every uncle is rewarded only once
hash := uncle.Hash()
if uncles.Contains(hash) {
return errDuplicateUncle
return consensus.ErrDuplicateUncle
}
uncles.Add(hash)

// Make sure the uncle has a valid ancestry
if ancestors[hash] != nil {
return errUncleIsAncestor
return consensus.ErrUncleIsAncestor
}
// Siblings are not allowed to be included in the workshares list if its an
// uncle but can be if its a workshare
Expand All @@ -246,7 +229,7 @@ func (blake3pow *Blake3pow) VerifyUncles(chain consensus.ChainReader, block *typ
workShare = true
}
if ancestors[uncle.ParentHash()] == nil || (!workShare && (uncle.ParentHash() == block.ParentHash(nodeCtx))) {
return errDanglingUncle
return consensus.ErrDanglingUncle
}

// make sure that the work can be computed
Expand Down Expand Up @@ -300,7 +283,7 @@ func (blake3pow *Blake3pow) verifyHeader(chain consensus.ChainHeaderReader, head
}
}
if header.Time() < parent.Time() {
return errOlderBlockTime
return consensus.ErrOlderBlockTime
}
// Verify the block's difficulty based on its timestamp and parent's difficulty
// difficulty adjustment can only be checked in zone
Expand Down Expand Up @@ -583,18 +566,18 @@ func (blake3pow *Blake3pow) verifySeal(header *types.WorkObjectHeader) error {
if blake3pow.config.PowMode == ModeFake || blake3pow.config.PowMode == ModeFullFake {
time.Sleep(blake3pow.fakeDelay)
if blake3pow.fakeFail == header.NumberU64() {
return errInvalidPoW
return consensus.ErrInvalidPoW
}
return nil
}
// Ensure that we have a valid difficulty for the block
if header.Difficulty().Sign() <= 0 {
return errInvalidDifficulty
return consensus.ErrInvalidDifficulty
}

target := new(big.Int).Div(big2e256, header.Difficulty())
if new(big.Int).SetBytes(header.Hash().Bytes()).Cmp(target) > 0 {
return errInvalidPoW
return consensus.ErrInvalidPoW
}
return nil
}
Expand Down
16 changes: 6 additions & 10 deletions consensus/blake3pow/poem.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ func (blake3pow *Blake3pow) CalcOrder(chain consensus.BlockReader, header *types
func (blake3pow *Blake3pow) IntrinsicLogS(powHash common.Hash) *big.Int {
x := new(big.Int).SetBytes(powHash.Bytes())
d := new(big.Int).Div(big2e256, x)
c, m := mathutil.BinaryLog(d, mantBits)
bigBits := new(big.Int).Mul(big.NewInt(int64(c)), new(big.Int).Exp(big.NewInt(2), big.NewInt(mantBits), nil))
c, m := mathutil.BinaryLog(d, consensus.MantBits)
bigBits := new(big.Int).Mul(big.NewInt(int64(c)), new(big.Int).Exp(big.NewInt(2), big.NewInt(consensus.MantBits), nil))
bigBits = new(big.Int).Add(bigBits, m)
return bigBits
}
Expand Down Expand Up @@ -269,18 +269,14 @@ func (blake3pow *Blake3pow) CalcRank(chain consensus.ChainHeaderReader, header *
}

func (blake3pow *Blake3pow) CheckIfValidWorkShare(workShare *types.WorkObjectHeader) bool {
// Extract some data from the header
diff := new(big.Int).Set(workShare.Difficulty())
c, _ := mathutil.BinaryLog(diff, mantBits)
if c <= params.WorkSharesThresholdDiff {
workShareMinTarget, err := consensus.CalcWorkShareThreshold(workShare)
if err != nil {
blake3pow.logger.Error(err)
return false
}
workShareThreshold := c - params.WorkSharesThresholdDiff
workShareDiff := new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(workShareThreshold)), nil)
workShareMintarget := new(big.Int).Div(big2e256, workShareDiff)
powHash, err := blake3pow.ComputePowHash(workShare)
if err != nil {
return false
}
return new(big.Int).SetBytes(powHash.Bytes()).Cmp(workShareMintarget) <= 0
return new(big.Int).SetBytes(powHash.Bytes()).Cmp(workShareMinTarget) <= 0
}
9 changes: 2 additions & 7 deletions consensus/blake3pow/sealer.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,13 @@ import (
"runtime/debug"
"sync"

"github.com/dominant-strategies/go-quai/consensus"
"github.com/dominant-strategies/go-quai/core/types"
"github.com/dominant-strategies/go-quai/log"
"github.com/dominant-strategies/go-quai/params"
"modernc.org/mathutil"
)

const (
// staleThreshold is the maximum depth of the acceptable stale but valid blake3pow solution.
staleThreshold = 7
mantBits = 64
)

var (
errNoMiningWork = errors.New("no mining work available yet")
errInvalidSealResult = errors.New("invalid or stale proof-of-work solution")
Expand Down Expand Up @@ -130,7 +125,7 @@ func (blake3pow *Blake3pow) Seal(header *types.WorkObject, results chan<- *types
func (blake3pow *Blake3pow) mine(header *types.WorkObject, id int, seed uint64, abort chan struct{}, found chan *types.WorkObject) {
// Extract some data from the header
diff := new(big.Int).Set(header.Difficulty())
c, _ := mathutil.BinaryLog(diff, mantBits)
c, _ := mathutil.BinaryLog(diff, consensus.MantBits)
if c <= params.WorkSharesThresholdDiff {
return
}
Expand Down
53 changes: 53 additions & 0 deletions consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,52 @@
package consensus

import (
"errors"
"math/big"

"github.com/dominant-strategies/go-quai/common"
"github.com/dominant-strategies/go-quai/core/state"
"github.com/dominant-strategies/go-quai/core/types"
"github.com/dominant-strategies/go-quai/params"
"modernc.org/mathutil"
)

const (
// staleThreshold is the maximum depth of the acceptable stale but valid solution.
StaleThreshold = 7
MantBits = 64
)

// Some useful constants to avoid constant memory allocs for them.
var (
ExpDiffPeriod = big.NewInt(100000)
Big0 = big.NewInt(0)
Big1 = big.NewInt(1)
Big2 = big.NewInt(2)
Big3 = big.NewInt(3)
Big8 = big.NewInt(8)
Big9 = big.NewInt(9)
Big10 = big.NewInt(10)
Big32 = big.NewInt(32)
BigMinus99 = big.NewInt(-99)
Big2e256 = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0)) // 2^256
)

// Various error messages to mark blocks invalid. These should be private to
// prevent engine specific errors from being referenced in the remainder of the
// codebase, inherently breaking if the engine is swapped out. Please put common
// error types into the consensus package.
var (
ErrOlderBlockTime = errors.New("timestamp older than parent")
ErrTooManyUncles = errors.New("too many uncles")
ErrDuplicateUncle = errors.New("duplicate uncle")
ErrUncleIsAncestor = errors.New("uncle is ancestor")
ErrDanglingUncle = errors.New("uncle's parent is not ancestor")
ErrInvalidDifficulty = errors.New("difficulty too low")
ErrDifficultyCrossover = errors.New("sub's difficulty exceeds dom's")
ErrInvalidMixHash = errors.New("invalid mixHash")
ErrInvalidPoW = errors.New("invalid proof-of-work")
ErrInvalidOrder = errors.New("invalid order")
)

// ChainHeaderReader defines a small collection of methods needed to access the local
Expand Down Expand Up @@ -191,6 +231,19 @@ func DifficultyToTarget(difficulty *big.Int) *big.Int {
return TargetToDifficulty(difficulty)
}

func CalcWorkShareThreshold(workShare *types.WorkObjectHeader) (*big.Int, error) {
// Extract some data from the header
diff := new(big.Int).Set(workShare.Difficulty())
c, _ := mathutil.BinaryLog(diff, MantBits)
if c <= params.WorkSharesThresholdDiff {
return nil, ErrInvalidDifficulty
}
workShareThreshold := c - params.WorkSharesThresholdDiff
workShareDiff := new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(workShareThreshold)), nil)
workShareMinTarget := new(big.Int).Div(Big2e256, workShareDiff)
return workShareMinTarget, nil
}

// PoW is a consensus engine based on proof-of-work.
type PoW interface {
Engine
Expand Down
38 changes: 10 additions & 28 deletions consensus/progpow/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package progpow

import (
"bytes"
"errors"
"fmt"
"math/big"
"runtime"
Expand Down Expand Up @@ -48,23 +47,6 @@ var (
big2e256 = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0)) // 2^256
)

// Various error messages to mark blocks invalid. These should be private to
// prevent engine specific errors from being referenced in the remainder of the
// codebase, inherently breaking if the engine is swapped out. Please put common
// error types into the consensus package.
var (
errOlderBlockTime = errors.New("timestamp older than parent")
errTooManyUncles = errors.New("too many uncles")
errDuplicateUncle = errors.New("duplicate uncle")
errUncleIsAncestor = errors.New("uncle is ancestor")
errDanglingUncle = errors.New("uncle's parent is not ancestor")
errInvalidDifficulty = errors.New("non-positive difficulty")
errDifficultyCrossover = errors.New("sub's difficulty exceeds dom's")
errInvalidMixHash = errors.New("invalid mixHash")
errInvalidPoW = errors.New("invalid proof-of-work")
errInvalidOrder = errors.New("invalid order")
)

// Author implements consensus.Engine, returning the header's coinbase as the
// proof-of-work verified author of the block.
func (progpow *Progpow) Author(header *types.WorkObject) (common.Address, error) {
Expand Down Expand Up @@ -197,7 +179,7 @@ func (progpow *Progpow) VerifyUncles(chain consensus.ChainReader, block *types.W
}
// Verify that there are at most params.MaxWorkShareCount uncles included in this block
if len(block.Uncles()) > params.MaxWorkShareCount {
return errTooManyUncles
return consensus.ErrTooManyUncles
}
if len(block.Uncles()) == 0 {
return nil
Expand Down Expand Up @@ -233,13 +215,13 @@ func (progpow *Progpow) VerifyUncles(chain consensus.ChainReader, block *types.W
// Make sure every uncle is rewarded only once
hash := uncle.Hash()
if uncles.Contains(hash) {
return errDuplicateUncle
return consensus.ErrDuplicateUncle
}
uncles.Add(hash)

// Make sure the uncle has a valid ancestry
if ancestors[hash] != nil {
return errUncleIsAncestor
return consensus.ErrUncleIsAncestor
}
// Siblings are not allowed to be included in the workshares list if its an
// uncle but can be if its a workshare
Expand All @@ -249,7 +231,7 @@ func (progpow *Progpow) VerifyUncles(chain consensus.ChainReader, block *types.W
workShare = true
}
if ancestors[uncle.ParentHash()] == nil || (!workShare && (uncle.ParentHash() == block.ParentHash(nodeCtx))) {
return errDanglingUncle
return consensus.ErrDanglingUncle
}
_, err = progpow.ComputePowHash(uncle)
if err != nil {
Expand Down Expand Up @@ -302,7 +284,7 @@ func (progpow *Progpow) verifyHeader(chain consensus.ChainHeaderReader, header,
}
}
if header.Time() < parent.Time() {
return errOlderBlockTime
return consensus.ErrOlderBlockTime
}
// Verify the block's difficulty based on its timestamp and parent's difficulty
// difficulty adjustment can only be checked in zone
Expand Down Expand Up @@ -613,7 +595,7 @@ func (progpow *Progpow) verifySeal(header *types.WorkObjectHeader) (common.Hash,
if progpow.config.PowMode == ModeFake || progpow.config.PowMode == ModeFullFake {
time.Sleep(progpow.fakeDelay)
if progpow.fakeFail == header.NumberU64() {
return common.Hash{}, errInvalidPoW
return common.Hash{}, consensus.ErrInvalidPoW
}
return common.Hash{}, nil
}
Expand All @@ -623,7 +605,7 @@ func (progpow *Progpow) verifySeal(header *types.WorkObjectHeader) (common.Hash,
}
// Ensure that we have a valid difficulty for the block
if header.Difficulty().Sign() <= 0 {
return common.Hash{}, errInvalidDifficulty
return common.Hash{}, consensus.ErrInvalidDifficulty
}
// Check progpow
mixHash := header.PowDigest.Load()
Expand All @@ -633,11 +615,11 @@ func (progpow *Progpow) verifySeal(header *types.WorkObjectHeader) (common.Hash,
}
// Verify the calculated values against the ones provided in the header
if !bytes.Equal(header.MixHash().Bytes(), mixHash.(common.Hash).Bytes()) {
return common.Hash{}, errInvalidMixHash
return common.Hash{}, consensus.ErrInvalidMixHash
}
target := new(big.Int).Div(big2e256, header.Difficulty())
if new(big.Int).SetBytes(powHash.(common.Hash).Bytes()).Cmp(target) > 0 {
return powHash.(common.Hash), errInvalidPoW
return powHash.(common.Hash), consensus.ErrInvalidPoW
}
return powHash.(common.Hash), nil
}
Expand All @@ -651,7 +633,7 @@ func (progpow *Progpow) ComputePowHash(header *types.WorkObjectHeader) (common.H
}
// Verify the calculated values against the ones provided in the header
if !bytes.Equal(header.MixHash().Bytes(), mixHash.(common.Hash).Bytes()) {
return common.Hash{}, errInvalidMixHash
return common.Hash{}, consensus.ErrInvalidMixHash
}
return powHash.(common.Hash), nil
}
Expand Down
16 changes: 6 additions & 10 deletions consensus/progpow/poem.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ func (progpow *Progpow) CalcOrder(chain consensus.BlockReader, header *types.Wor
func (progpow *Progpow) IntrinsicLogS(powHash common.Hash) *big.Int {
x := new(big.Int).SetBytes(powHash.Bytes())
d := new(big.Int).Div(big2e256, x)
c, m := mathutil.BinaryLog(d, mantBits)
bigBits := new(big.Int).Mul(big.NewInt(int64(c)), new(big.Int).Exp(big.NewInt(2), big.NewInt(mantBits), nil))
c, m := mathutil.BinaryLog(d, consensus.MantBits)
bigBits := new(big.Int).Mul(big.NewInt(int64(c)), new(big.Int).Exp(big.NewInt(2), big.NewInt(consensus.MantBits), nil))
bigBits = new(big.Int).Add(bigBits, m)
return bigBits
}
Expand Down Expand Up @@ -270,18 +270,14 @@ func (progpow *Progpow) CalcRank(chain consensus.ChainHeaderReader, header *type
}

func (progpow *Progpow) CheckIfValidWorkShare(workShare *types.WorkObjectHeader) bool {
// Extract some data from the header
diff := new(big.Int).Set(workShare.Difficulty())
c, _ := mathutil.BinaryLog(diff, mantBits)
if c <= params.WorkSharesThresholdDiff {
workShareMinTarget, err := consensus.CalcWorkShareThreshold(workShare)
if err != nil {
progpow.logger.Error(err)
return false
}
workShareThreshold := c - params.WorkSharesThresholdDiff
workShareDiff := new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(workShareThreshold)), nil)
workShareMintarget := new(big.Int).Div(big2e256, workShareDiff)
powHash, err := progpow.ComputePowHash(workShare)
if err != nil {
return false
}
return new(big.Int).SetBytes(powHash.Bytes()).Cmp(workShareMintarget) <= 0
return new(big.Int).SetBytes(powHash.Bytes()).Cmp(workShareMinTarget) <= 0
}
Loading
Loading