Compare commits

...

5 commits

9 changed files with 103 additions and 39 deletions

8
.gitignore vendored
View file

@ -1,7 +1 @@
CMakeFiles
CMakeCache.txt
*.exe
librandomx.a
*.cmake
Makefile
gxminer
.idea/

View file

@ -1,10 +1,17 @@
# go-randomx
# randomx-go-bindings
CGO bindings for [tevador/RandomX](https://github.com/tevador/RandomX)
## Building requirements
### RandomX
### RandomX Dependency
| randomx-go-bindings Version | Supported RandomX Versions | Notes |
|:---------------------------:|:--------------------------:|:------------------------------------------:|
| v1.0.0 | v1.2.0+ | Support for `randomx_calculate_commitment` |
```bash
git clone --depth 1 --branch master https://github.com/tevador/RandomX.git /tmp/RandomX && pushd /tmp/RandomX && \
git clone --depth 1 --branch v1.2.1 https://github.com/tevador/RandomX.git /tmp/RandomX && pushd /tmp/RandomX && \
mkdir build && cd build && \
cmake .. -DCMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX:PATH=/usr && \
make -j$(nproc) && \

2
go.mod
View file

@ -1,3 +1,3 @@
module git.gammaspectra.live/P2Pool/randomx-go-bindings
go 1.19
go 1.22

View file

@ -61,6 +61,7 @@ void init_full_dataset(randomx_dataset *dataset, randomx_cache *cache, uint32_t
import "C"
import (
"errors"
"runtime"
"sync"
"unsafe"
)
@ -104,9 +105,11 @@ func InitCache(cache *C.randomx_cache, seed []byte) {
panic("seed cannot be NULL")
}
C.randomx_init_cache(cache, unsafe.Pointer(&seed[0]), C.size_t(len(seed)))
C.randomx_init_cache(cache, unsafe.Pointer(unsafe.SliceData(seed)), C.size_t(len(seed)))
runtime.KeepAlive(seed)
}
// GetCacheMemory Used for p2pool internal consensus hash
func GetCacheMemory(cache *C.randomx_cache) unsafe.Pointer {
//TODO: very unsafe. Maybe fork RandomX?
//This abuses C.randomx_dataset having memory ptr in the same struct location as C.randomx_cache
@ -172,9 +175,9 @@ func FastInitFullDataset(dataset *C.randomx_dataset, cache *C.randomx_cache, wor
var wg sync.WaitGroup
go func() {
defer wg.Done()
wg.Add(1)
C.init_full_dataset(dataset, cache, C.uint32_t(workerNum))
wg.Done()
}()
wg.Wait()
@ -215,30 +218,52 @@ func DestroyVM(vm *C.randomx_vm) {
C.randomx_destroy_vm(vm)
}
func CalculateHash(vm *C.randomx_vm, in []byte) []byte {
out := make([]byte, C.RANDOMX_HASH_SIZE)
// CalculateHash Calculates a RandomX hash value.
func CalculateHash(vm *C.randomx_vm, in []byte) (out RxHash) {
if vm == nil {
panic("failed hashing: using empty vm")
}
C.randomx_calculate_hash(vm, unsafe.Pointer(&in[0]), C.size_t(len(in)), unsafe.Pointer(&out[0]))
C.randomx_calculate_hash(vm, unsafe.Pointer(unsafe.SliceData(in)), C.size_t(len(in)), unsafe.Pointer(&out))
runtime.KeepAlive(in)
return out
}
// CalculateHashFirst will begin a hash calculation.
func CalculateHashFirst(vm *C.randomx_vm, in []byte) {
if vm == nil {
panic("failed hashing: using empty vm")
}
C.randomx_calculate_hash_first(vm, unsafe.Pointer(&in[0]), C.size_t(len(in)))
C.randomx_calculate_hash_first(vm, unsafe.Pointer(unsafe.SliceData(in)), C.size_t(len(in)))
runtime.KeepAlive(in)
}
func CalculateHashNext(vm *C.randomx_vm, in []byte) []byte {
out := make([]byte, C.RANDOMX_HASH_SIZE)
// CalculateHashNext will output the hash value of the previous input and begin the calculation of the next hash.
func CalculateHashNext(vm *C.randomx_vm, in []byte) (out RxHash) {
if vm == nil {
panic("failed hashing: using empty vm")
}
C.randomx_calculate_hash_next(vm, unsafe.Pointer(&in[0]), C.size_t(len(in)), unsafe.Pointer(&out[0]))
C.randomx_calculate_hash_next(vm, unsafe.Pointer(unsafe.SliceData(in)), C.size_t(len(in)), unsafe.Pointer(&out))
runtime.KeepAlive(in)
return out
}
// CalculateHashLast will output the hash value of the previous input.
func CalculateHashLast(vm *C.randomx_vm) (out RxHash) {
if vm == nil {
panic("failed hashing: using empty vm")
}
C.randomx_calculate_hash_last(vm, unsafe.Pointer(&out))
return out
}
// CalculateCommitment Calculate a RandomX commitment from a RandomX hash and its input.
func CalculateCommitment(in []byte, hash RxHash) (out RxHash) {
C.randomx_calculate_commitment(unsafe.Pointer(unsafe.SliceData(in)), C.size_t(len(in)), unsafe.Pointer(&hash), unsafe.Pointer(&out))
runtime.KeepAlive(in)
runtime.KeepAlive(hash)
return out
}
@ -261,3 +286,5 @@ type RxVM struct {
vm *C.randomx_vm
rxDataset *RxDataset
}
type RxHash [C.RANDOMX_HASH_SIZE]byte

View file

@ -16,18 +16,20 @@ import (
"time"
)
var testPairs = [][][]byte{
var testPairs = [][4][]byte{
// randomX
{
[]byte("test key 000"),
[]byte("This is a test"),
[]byte("639183aae1bf4c9a35884cb46b09cad9175f04efd7684e7262a0ac1c2f0b4e3f"),
[]byte("d53ccf348b75291b7be76f0a7ac8208bbced734b912f6fca60539ab6f86be919"),
},
// randomXL
{
[]byte("test key 000"),
[]byte("This is a test"),
[]byte("b291ec8a532bc4f78bd75b43d211e1169bb65b1a8f66d4250376ba1d6fcff1bd"),
[]byte("8f8c686d586498275662a946ec6b7b56d23ba13dd4490229f607e9428dbd33f5"),
},
}
@ -96,8 +98,8 @@ func TestCreateVM(t *testing.T) {
hash := CalculateHash(vm, tp[1])
if bytes.Compare(hash, hashCorrect) != 0 {
t.Log(hex.EncodeToString(hash))
if bytes.Compare(hash[:], hashCorrect) != 0 {
t.Log(hex.EncodeToString(hash[:]))
t.Log(hex.EncodeToString(hashCorrect))
t.Fail()
}
@ -123,8 +125,8 @@ func TestCreateVMLight(t *testing.T) {
hash := CalculateHash(vm, tp[1])
if bytes.Compare(hash, hashCorrect) != 0 {
t.Log(hex.EncodeToString(hash))
if bytes.Compare(hash[:], hashCorrect) != 0 {
t.Log(hex.EncodeToString(hash[:]))
t.Log(hex.EncodeToString(hashCorrect))
t.Fail()
}
@ -156,8 +158,8 @@ func TestNewRxVM(t *testing.T) {
log.Println(err)
}
if bytes.Compare(hash, hashCorrect) != 0 {
t.Log(hex.EncodeToString(hash))
if bytes.Compare(hash[:], hashCorrect) != 0 {
t.Log(hex.EncodeToString(hash[:]))
t.Log(hex.EncodeToString(hashCorrect))
t.Fail()
}
@ -189,8 +191,8 @@ func TestNewRxVMLight(t *testing.T) {
log.Println(err)
}
if bytes.Compare(hash, hashCorrect) != 0 {
t.Log(hex.EncodeToString(hash))
if bytes.Compare(hash[:], hashCorrect) != 0 {
t.Log(hex.EncodeToString(hash[:]))
t.Log(hex.EncodeToString(hashCorrect))
t.Fail()
}
@ -235,7 +237,7 @@ func TestCalculateHashFirst(t *testing.T) {
binary.LittleEndian.PutUint32(nonce, n)
copy(blob[39:43], nonce)
result := vm.CalcHashNext(blob)
if bytes.Compare(result, targetResult) == 0 {
if bytes.Compare(result[:], targetResult[:]) == 0 {
fmt.Println(n, "found")
wg.Done()
} else {
@ -248,6 +250,32 @@ func TestCalculateHashFirst(t *testing.T) {
}
func TestCalculateCommitment(t *testing.T) {
var tp = testPairs[pairToTest]
in := tp[1]
var hash RxHash
_, err := hex.Decode(hash[:], tp[2])
if err != nil {
t.Fatal(err)
}
var outCorrect RxHash
_, err = hex.Decode(outCorrect[:], tp[3])
if err != nil {
t.Fatal(err)
}
out := CalculateCommitment(in, hash)
if out != outCorrect {
t.Log(hex.EncodeToString(out[:]))
t.Log(hex.EncodeToString(outCorrect[:]))
t.Fail()
}
}
// go test -v -bench "." -benchtime=30m
func BenchmarkCalculateHash(b *testing.B) {
cache, _ := AllocCache(Flag(GetFlags()))

View file

@ -17,6 +17,7 @@ func NewRxCache(flags ...Flag) (*RxCache, error) {
func (c *RxCache) Close() {
if c.cache != nil {
ReleaseCache(c.cache)
c.cache = nil
}
}

View file

@ -28,6 +28,7 @@ func NewRxDataset(flags ...Flag) (*RxDataset, error) {
func (ds *RxDataset) Close() {
if ds.dataset != nil {
ReleaseDataset(ds.dataset)
ds.dataset = nil
}
ds.rxCache.Close()

View file

@ -18,10 +18,11 @@ func NewRxVM(rxDataset *RxDataset, flags ...Flag) (*RxVM, error) {
func (vm *RxVM) Close() {
if vm.vm != nil {
DestroyVM(vm.vm)
vm.vm = nil
}
}
func (vm *RxVM) CalcHash(in []byte) []byte {
func (vm *RxVM) CalcHash(in []byte) RxHash {
return CalculateHash(vm.vm, in)
}
@ -29,10 +30,14 @@ func (vm *RxVM) CalcHashFirst(in []byte) {
CalculateHashFirst(vm.vm, in)
}
func (vm *RxVM) CalcHashNext(in []byte) []byte {
func (vm *RxVM) CalcHashNext(in []byte) RxHash {
return CalculateHashNext(vm.vm, in)
}
func (vm *RxVM) CalcHashLast() RxHash {
return CalculateHashLast(vm.vm)
}
func (vm *RxVM) UpdateDataset(rxDataset *RxDataset) {
SetVMCache(vm.vm, rxDataset.rxCache.cache)
SetVMDataset(vm.vm, rxDataset.dataset)

View file

@ -27,22 +27,23 @@ bool search(randomx_vm* vm, void* in, const uint64_t target, const uint64_t max_
*/
import "C"
import (
"runtime"
"unsafe"
)
func Search(vm *C.randomx_vm, in []byte, target uint64, maxTimes uint64, jump uint32, nonce []byte) (Hash []byte, Found bool, Sol []byte) {
hash := make([]byte, C.RANDOMX_HASH_SIZE)
sol := make([]byte, 4)
func Search(vm *C.randomx_vm, in []byte, target uint64, maxTimes uint64, jump uint32, nonce []byte) (hash RxHash, found bool, sol []byte) {
if vm == nil {
panic("failed hashing: using empty vm")
}
sol = make([]byte, 4)
var cFound C.bool
cFound = C.search(vm, unsafe.Pointer(&in[0]), C.uint64_t(target), C.uint64_t(maxTimes), C.uint32_t(jump), unsafe.Pointer(&nonce[0]), unsafe.Pointer(&hash[0]), unsafe.Pointer(&sol[0]))
cFound = C.search(vm, unsafe.Pointer(unsafe.SliceData(in)), C.uint64_t(target), C.uint64_t(maxTimes), C.uint32_t(jump), unsafe.Pointer(unsafe.SliceData(nonce)), unsafe.Pointer(&hash), unsafe.Pointer(unsafe.SliceData(sol)))
runtime.KeepAlive(in)
runtime.KeepAlive(nonce)
return hash, bool(cFound), sol
}
func (vm *RxVM) Search(in []byte, target uint64, maxTimes uint64, jump uint32, nonce []byte) (hash []byte, found bool, sol []byte) {
hash, found, sol = Search(vm.vm, in, target, maxTimes, jump, nonce)
return
func (vm *RxVM) Search(in []byte, target uint64, maxTimes uint64, jump uint32, nonce []byte) (hash RxHash, found bool, sol []byte) {
return Search(vm.vm, in, target, maxTimes, jump, nonce)
}