Skip to content

Commit

Permalink
cpuminerd: efficient nonce calc
Browse files Browse the repository at this point in the history
  • Loading branch information
n8maninger committed Sep 2, 2024
1 parent 16af439 commit 2472f9f
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 25 deletions.
21 changes: 5 additions & 16 deletions cmd/cpuminerd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"os"
"os/signal"
"runtime"
"sync"
"time"

"go.sia.tech/core/types"
Expand All @@ -17,7 +16,7 @@ import (
"go.uber.org/zap/zapcore"
)

func runCPUMiner(ctx context.Context, c *api.Client, minerAddr types.Address, log *zap.Logger) {
func runCPUMiner(ctx context.Context, c *api.Client, minerAddr types.Address, workers int, log *zap.Logger) {
log.Info("starting miner", zap.String("minerAddr", minerAddr.String()))

check := func(msg string, err error) bool {
Expand Down Expand Up @@ -50,7 +49,7 @@ func runCPUMiner(ctx context.Context, c *api.Client, minerAddr types.Address, lo
continue
}

b, err := mineBlock(ctx, cs, txns, v2txns, minerAddr)
b, err := mineBlock(ctx, cs, txns, v2txns, minerAddr, workers, log)
if errors.Is(err, context.Canceled) {
return // shutting down
} else if errors.Is(err, context.DeadlineExceeded) {
Expand Down Expand Up @@ -95,7 +94,7 @@ func parseLogLevel(level string) zap.AtomicLevel {

func main() {
var (
threads int
workers int

minerAddrStr string

Expand All @@ -109,7 +108,7 @@ func main() {
flag.StringVar(&apiAddress, "api", "localhost:9980", "address of the walletd API")
flag.StringVar(&apiPassword, "password", "", "password for the walletd API")
flag.StringVar(&logLevel, "log.level", "info", "log level")
flag.IntVar(&threads, "threads", runtime.NumCPU(), "number of threads to use for mining")
flag.IntVar(&workers, "workers", runtime.NumCPU(), "number of workers to use for mining")
flag.Parse()

ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
Expand Down Expand Up @@ -139,15 +138,5 @@ func main() {

zap.RedirectStdLog(log)

var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
runCPUMiner(ctx, c, address, log.With(zap.Int("worker", n)))
}(i + 1)
}

<-ctx.Done()
wg.Wait()
runCPUMiner(ctx, c, address, workers, log)
}
69 changes: 60 additions & 9 deletions cmd/cpuminerd/mine.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ package main
import (
"context"
"encoding/binary"
"sync/atomic"
"time"

"go.sia.tech/core/consensus"
"go.sia.tech/core/types"
"go.uber.org/zap"
)

// mineBlock constructs a block from the provided address and the transactions
// in the txpool, and attempts to find a nonce for it that meets the PoW target.
func mineBlock(ctx context.Context, cs consensus.State, txns []types.Transaction, v2Txns []types.V2Transaction, addr types.Address) (types.Block, error) {
func mineBlock(ctx context.Context, cs consensus.State, txns []types.Transaction, v2Txns []types.V2Transaction, addr types.Address, workers int, log *zap.Logger) (types.Block, error) {
b := types.Block{
ParentID: cs.Index.ID,
Timestamp: types.CurrentTimestamp(),
Expand Down Expand Up @@ -63,15 +65,64 @@ func mineBlock(ctx context.Context, cs consensus.State, txns []types.Transaction
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
defer cancel()

for types.BlockID(types.HashBytes(buf)).CmpWork(cs.ChildTarget) < 0 {
select {
case <-ctx.Done():
return types.Block{}, ctx.Err()
default:
nonceCh := make(chan uint64, workers)
go func() {
for nonce := uint64(0); ; nonce += factor {
select {
case <-ctx.Done():
return
default:
}
nonceCh <- nonce
}
}()

b.Nonce += factor
binary.LittleEndian.PutUint64(buf[32:], b.Nonce)
start := time.Now()
var hashes uint64
go func() {
for {
select {
case <-ctx.Done():
return
case <-time.After(10 * time.Second):
rate := float64(atomic.LoadUint64(&hashes)) / time.Since(start).Seconds()
log.Debug("mining", zap.Float64("rate", rate), zap.Int("workers", workers))
}
}
}()

resultCh := make(chan uint64, 1)
for i := 0; i < workers; i++ {
workerBuf := make([]byte, len(buf))
copy(workerBuf, buf)
go func(n int, nonce uint64, buf []byte) {

for {
select {
case <-ctx.Done():
return
case nonce := <-nonceCh:
binary.LittleEndian.PutUint64(buf[32:], nonce)
h := types.BlockID(types.HashBytes(buf))
atomic.AddUint64(&hashes, 1)
if h.CmpWork(cs.ChildTarget) < 0 {
continue
}

select {
case resultCh <- nonce:
default:
}
return
}
}
}(i+1, b.Nonce, workerBuf)
}

select {
case <-ctx.Done():
return types.Block{}, ctx.Err()
case b.Nonce = <-resultCh:
return b, nil
}
return b, nil
}

0 comments on commit 2472f9f

Please sign in to comment.