118 lines
2.6 KiB
Go
118 lines
2.6 KiB
Go
package randomxT
|
||
|
||
/*
|
||
#cgo CFLAGS: -I/home/lizixuan/桌面/tari-server/internal/server/include
|
||
#cgo LDFLAGS: -L/home/lizixuan/桌面/tari-server/internal/server/lib/randomx -lrandomx
|
||
#include <randomx.h>
|
||
#include <stdlib.h>
|
||
#include <sys/mman.h>
|
||
#include <unistd.h>
|
||
*/
|
||
import "C"
|
||
|
||
import (
|
||
"fmt"
|
||
"unsafe"
|
||
|
||
"golang.org/x/sys/cpu"
|
||
)
|
||
|
||
type RandomXValidator struct {
|
||
cache *C.randomx_cache
|
||
vm *C.randomx_vm
|
||
flags C.randomx_flags
|
||
seed []byte
|
||
}
|
||
|
||
// NewRandomXValidator 初始化 cache + vm
|
||
func NewRandomXValidator(seed []byte) (*RandomXValidator, error) {
|
||
if len(seed) != 32 {
|
||
return nil, fmt.Errorf("seed must be 32 bytes")
|
||
}
|
||
|
||
var flags C.randomx_flags = 0
|
||
|
||
// 检测 AES-NI 支持
|
||
if cpu.X86.HasAES {
|
||
flags |= C.RANDOMX_FLAG_HARD_AES
|
||
} else {
|
||
fmt.Println("[RandomX] CPU 不支持 AES-NI,将使用纯软件模式")
|
||
}
|
||
|
||
// ⚠️ 默认启用 JIT(如果系统禁止会报错)
|
||
flags |= C.RANDOMX_FLAG_JIT
|
||
|
||
// 分配 cache
|
||
cache := C.randomx_alloc_cache(flags)
|
||
if cache == nil {
|
||
return nil, fmt.Errorf("failed to alloc cache")
|
||
}
|
||
C.randomx_init_cache(cache, unsafe.Pointer(&seed[0]), C.size_t(len(seed)))
|
||
|
||
// 创建 vm
|
||
vm := C.randomx_create_vm(flags, cache, nil)
|
||
if vm == nil {
|
||
C.randomx_release_cache(cache)
|
||
return nil, fmt.Errorf("failed to create randomx vm")
|
||
}
|
||
|
||
return &RandomXValidator{
|
||
cache: cache,
|
||
vm: vm,
|
||
flags: flags,
|
||
seed: append([]byte{}, seed...),
|
||
}, nil
|
||
}
|
||
|
||
// SetSeed 更新 seed(替换 cache,并重置 vm)
|
||
func (v *RandomXValidator) SetSeed(seed []byte) error {
|
||
if len(seed) != 32 {
|
||
return fmt.Errorf("seed must be 32 bytes")
|
||
}
|
||
|
||
// 如果相同 seed,不用更新
|
||
if string(seed) == string(v.seed) {
|
||
return nil
|
||
}
|
||
|
||
C.randomx_init_cache(v.cache, unsafe.Pointer(&seed[0]), C.size_t(len(seed)))
|
||
C.randomx_vm_set_cache(v.vm, v.cache)
|
||
|
||
v.seed = append(v.seed[:0], seed...)
|
||
return nil
|
||
}
|
||
|
||
// Destroy 释放 vm + cache
|
||
func (v *RandomXValidator) Destroy() {
|
||
if v.vm != nil {
|
||
C.randomx_destroy_vm(v.vm)
|
||
v.vm = nil
|
||
}
|
||
if v.cache != nil {
|
||
C.randomx_release_cache(v.cache)
|
||
v.cache = nil
|
||
}
|
||
}
|
||
|
||
// BuildPowHash 计算区块哈希
|
||
func (v *RandomXValidator) BuildPowHash(blockBlob, nonce []byte) ([]byte, []byte, error) {
|
||
if v.vm == nil {
|
||
return nil, nil, fmt.Errorf("vm is nil")
|
||
}
|
||
|
||
if len(nonce) != 4 {
|
||
return nil, nil, fmt.Errorf("nonce must be 4 bytes")
|
||
}
|
||
blockHeader := make([]byte, len(blockBlob))
|
||
copy(blockHeader, blockBlob)
|
||
copy(blockHeader[39:43], nonce)
|
||
var hash [32]byte
|
||
C.randomx_calculate_hash(v.vm,
|
||
unsafe.Pointer(&blockHeader[0]),
|
||
C.size_t(len(blockHeader)),
|
||
unsafe.Pointer(&hash[0]),
|
||
)
|
||
|
||
return hash[:], blockHeader, nil
|
||
}
|