diff --git a/cache_test.go b/cache_test.go new file mode 100644 index 0000000..d3b3662 --- /dev/null +++ b/cache_test.go @@ -0,0 +1,89 @@ +package randomx + +import "testing" + +func Test_Cache_Init(t *testing.T) { + t.Parallel() + + cache := NewCache(GetFlags()) + cache.Init(Tests[1].key) + + memory := cache.GetMemory() + + var tests = []struct { + index int + value uint64 + }{ + {0, 0x191e0e1d23c02186}, + {1568413, 0xf1b62fe6210bf8b1}, + {33554431, 0x1f47f056d05cd99b}, + } + + for i, tt := range tests { + if memory[tt.index/128][tt.index%128] != tt.value { + t.Errorf("i=%d, index=%d", i, tt.index) + t.Errorf("expected=%016x, actual=%016x", tt.value, memory[tt.index/128][tt.index%128]) + } + } + +} + +func Test_Cache_InitDataset(t *testing.T) { + t.Parallel() + + var tests = []struct { + index int + value uint64 + }{ + {0, 0x680588a85ae222db}, + {10000000, 0x7943a1f6186ffb72}, + {20000000, 0x9035244d718095e1}, + {30000000, 0x145a5091f7853099}, + } + + t.Run("interpreter", func(t *testing.T) { + t.Parallel() + + flags := GetFlags() + flags &^= RANDOMX_FLAG_JIT + + cache := NewCache(flags) + cache.Init(Tests[1].key) + + var datasetItem RegisterLine + + for i, tt := range tests { + cache.initDataset(&datasetItem, uint64(tt.index)) + if datasetItem[0] != tt.value { + t.Errorf("i=%d, index=%d", i, tt.index) + t.Errorf("expected=%016x, actual=%016x", tt.value, datasetItem[0]) + } + } + }) + + t.Run("compiler", func(t *testing.T) { + t.Parallel() + + flags := GetFlags() + flags |= RANDOMX_FLAG_JIT + if !flags.HasJIT() { + t.Skip("not supported on this platform") + } + + cache := NewCache(flags) + cache.Init(Tests[1].key) + if !cache.hasInitializedJIT() { + t.Skip("not supported on this platform") + } + + var datasetItem RegisterLine + + for i, tt := range tests { + cache.initDataset(&datasetItem, uint64(tt.index)) + if datasetItem[0] != tt.value { + t.Errorf("i=%d, index=%d", i, tt.index) + t.Errorf("expected=%016x, actual=%016x", tt.value, datasetItem[0]) + } + } + }) +} diff --git a/commitment.go b/commitment.go new file mode 100644 index 0000000..302f8d8 --- /dev/null +++ b/commitment.go @@ -0,0 +1,15 @@ +package randomx + +import "golang.org/x/crypto/blake2b" + +// CalculateCommitment Calculate a RandomX commitment from a RandomX hash and its input. +func CalculateCommitment(input []byte, hashIn, hashOut *[RANDOMX_HASH_SIZE]byte) { + hasher, err := blake2b.New(RANDOMX_HASH_SIZE, nil) + if err != nil { + panic(err) + } + + hasher.Write(input) + hasher.Write(hashIn[:]) + hasher.Sum(hashOut[:0]) +} diff --git a/commitment_test.go b/commitment_test.go new file mode 100644 index 0000000..6917ba9 --- /dev/null +++ b/commitment_test.go @@ -0,0 +1,38 @@ +package randomx + +import ( + "encoding/hex" + "testing" +) + +func Test_CalculateCommitment(t *testing.T) { + t.Parallel() + + cache := NewCache(GetFlags()) + defer cache.Close() + + test := Tests[1] + + cache.Init(test.key) + + vm, err := NewVM(GetFlags(), cache, nil) + if err != nil { + t.Fatal(err) + } + defer vm.Close() + + var outputHash [RANDOMX_HASH_SIZE]byte + + vm.CalculateHash(test.input, &outputHash) + CalculateCommitment(test.input, &outputHash, &outputHash) + + outputHex := hex.EncodeToString(outputHash[:]) + + expected := "d53ccf348b75291b7be76f0a7ac8208bbced734b912f6fca60539ab6f86be919" + + if expected != outputHex { + t.Errorf("key=%v, input=%v", test.key, test.input) + t.Errorf("expected=%s, actual=%s", expected, outputHex) + t.FailNow() + } +} diff --git a/math_test.go b/math_test.go new file mode 100644 index 0000000..76589dd --- /dev/null +++ b/math_test.go @@ -0,0 +1,28 @@ +package randomx + +import "testing" + +func TestReciprocal(t *testing.T) { + t.Parallel() + + var tests = []struct { + a uint32 + b uint64 + }{ + {3, 12297829382473034410}, + {13, 11351842506898185609}, + {33, 17887751829051686415}, + {65537, 18446462603027742720}, + {15000001, 10316166306300415204}, + {3845182035, 10302264209224146340}, + {0xffffffff, 9223372039002259456}, + } + + for i, tt := range tests { + r := reciprocal(tt.a) + if r != tt.b { + t.Errorf("i=%d, a=%d", i, tt.a) + t.Errorf("expected=%016x, actual=%016x", tt.b, r) + } + } +} diff --git a/randomx_test.go b/randomx_test.go index 30ede0a..8588989 100644 --- a/randomx_test.go +++ b/randomx_test.go @@ -90,8 +90,10 @@ func testFlags(name string, flags Flags) (f Flags, skip bool) { } func Test_RandomXLight(t *testing.T) { + t.Parallel() for _, n := range []string{"interpreter", "compiler", "softaes", "hardaes"} { t.Run(n, func(t *testing.T) { + t.Parallel() tFlags, skip := testFlags(t.Name(), 0) if skip { t.Skip("not supported on this platform") diff --git a/vm.go b/vm.go index 0809ca9..61c2158 100644 --- a/vm.go +++ b/vm.go @@ -270,9 +270,12 @@ func (vm *VM) runLoops() { defer runtime.UnlockOSThread() } - // always force a restore + // always force a restore before startup ResetRoundingMode(&vm.registerFile) + // restore rounding mode at the end + defer ResetRoundingMode(&vm.registerFile) + for chain := 0; chain < RANDOMX_PROGRAM_COUNT-1; chain++ { vm.run() @@ -282,9 +285,6 @@ func (vm *VM) runLoops() { // final loop executes here vm.run() - - // restore rounding mode - ResetRoundingMode(&vm.registerFile) } // SetCache Reinitializes a virtual machine with a new Cache.