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

Perform initial getwork when solo mining. #224

Merged
merged 1 commit into from
Oct 12, 2023
Merged
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
65 changes: 47 additions & 18 deletions miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,30 @@ func newStratum(devices []*Device) (*Miner, error) {
return m, nil
}

// onSoloWork prepares the provided getwork-based work data, which might have
// either come from getwork directly or from asynchronous work notifications,
// and updates all of the provided devices with that prepared work.
func onSoloWork(ctx context.Context, data, target []byte, reason string, devices []*Device) {
minrLog.Debugf("Work received: (data: %x, target: %x, reason: %s)", data,
target, reason)

// The bigTarget difficulty is provided in little endian, but big integers
// expect big endian, so reverse it accordingly.
bigTarget := new(big.Int).SetBytes(util.Reverse(target))

var workData [192]byte
copy(workData[:], data)

const isGetWork = true
timestamp := binary.LittleEndian.Uint32(workData[128+4*work.TimestampWord:])
w := work.NewWork(workData, bigTarget, timestamp, uint32(time.Now().Unix()),
isGetWork)

for _, d := range devices {
d.SetWork(ctx, w)
}
}

func newSoloMiner(ctx context.Context, devices []*Device) (*Miner, error) {
var rpc *rpcclient.Client
ntfnHandlers := rpcclient.NotificationHandlers{
Expand All @@ -61,24 +85,7 @@ func newSoloMiner(ctx context.Context, devices []*Device) (*Miner, error) {
minrLog.Infof("Block disconnected: %x", blockHeader)
},
OnWork: func(data, target []byte, reason string) {
minrLog.Infof("Work received: %x %x %s", data, target, reason)

// The bigTarget difficulty is provided in little endian, but big integers
// expect big endian, so reverse it accordingly.
bigTarget := new(big.Int).SetBytes(util.Reverse(target))

var workData [192]byte
copy(workData[:], data)

const isGetWork = true
timestamp := binary.LittleEndian.Uint32(workData[128+4*work.TimestampWord:])
w := work.NewWork(workData, bigTarget, timestamp, uint32(time.Now().Unix()),
isGetWork)

// Solo
for _, d := range devices {
d.SetWork(ctx, w)
}
onSoloWork(ctx, data, target, reason, devices)
},
}
// Connect to local dcrd RPC server using websockets.
Expand Down Expand Up @@ -144,6 +151,28 @@ func NewMiner(ctx context.Context) (*Miner, error) {
m.workDone = workDone
m.started = uint32(time.Now().Unix())

// Perform an initial call to getwork when solo mining so work is available
// immediately.
if cfg.Pool == "" {
workResult, err := m.rpc.GetWork(ctx)
if err != nil {
m.rpc.Shutdown()
return nil, fmt.Errorf("unable to retrieve initial work: %w", err)
}

data, err := hex.DecodeString(workResult.Data)
if err != nil {
m.rpc.Shutdown()
return nil, fmt.Errorf("unable to decode work data: %w", err)
}
target, err := hex.DecodeString(workResult.Target)
if err != nil {
m.rpc.Shutdown()
return nil, fmt.Errorf("unable to decode work target: %w", err)
}
onSoloWork(ctx, data, target, "initialwork", devices)
}

return m, nil
}

Expand Down
Loading