Split hard/soft AES implementations
This commit is contained in:
parent
25b7fc4cc0
commit
1d83de4880
4
cache.go
4
cache.go
|
@ -23,10 +23,10 @@ type Cache struct {
|
|||
|
||||
JitPrograms [RANDOMX_PROGRAM_COUNT]SuperScalarProgramFunc
|
||||
|
||||
Flags uint64
|
||||
Flags Flag
|
||||
}
|
||||
|
||||
func NewCache(flags uint64) *Cache {
|
||||
func NewCache(flags Flag) *Cache {
|
||||
if flags == RANDOMX_FLAG_DEFAULT {
|
||||
flags = RANDOMX_FLAG_JIT
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ type Dataset interface {
|
|||
InitDataset(startItem, itemCount uint64)
|
||||
ReadDataset(address uint64, r *RegisterLine)
|
||||
PrefetchDataset(address uint64)
|
||||
Flags() uint64
|
||||
Flags() Flag
|
||||
Cache() *Cache
|
||||
Memory() []RegisterLine
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ func (d *DatasetFull) Cache() *Cache {
|
|||
return d.cache
|
||||
}
|
||||
|
||||
func (d *DatasetFull) Flags() uint64 {
|
||||
func (d *DatasetFull) Flags() Flag {
|
||||
return d.cache.Flags
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ func (d *DatasetLight) ReadDataset(address uint64, r *RegisterLine) {
|
|||
}
|
||||
}
|
||||
|
||||
func (d *DatasetLight) Flags() uint64 {
|
||||
func (d *DatasetLight) Flags() Flag {
|
||||
return d.cache.Flags
|
||||
}
|
||||
|
||||
|
|
26
flags.go
26
flags.go
|
@ -1,15 +1,18 @@
|
|||
package randomx
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v3/internal/aes"
|
||||
"golang.org/x/sys/cpu"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const RANDOMX_FLAG_DEFAULT = 0
|
||||
type Flag uint64
|
||||
|
||||
const RANDOMX_FLAG_DEFAULT Flag = 0
|
||||
|
||||
const (
|
||||
// RANDOMX_FLAG_LARGE_PAGES not implemented
|
||||
RANDOMX_FLAG_LARGE_PAGES = 1 << iota
|
||||
RANDOMX_FLAG_LARGE_PAGES = Flag(1 << iota)
|
||||
// RANDOMX_FLAG_HARD_AES not implemented
|
||||
RANDOMX_FLAG_HARD_AES
|
||||
// RANDOMX_FLAG_FULL_MEM Selects between full or light mode dataset
|
||||
|
@ -20,17 +23,30 @@ const (
|
|||
RANDOMX_FLAG_SECURE
|
||||
RANDOMX_FLAG_ARGON2_SSSE3
|
||||
RANDOMX_FLAG_ARGON2_AVX2
|
||||
RANDOMX_FLAG_ARGON2
|
||||
RANDOMX_FLAG_ARGON2 = RANDOMX_FLAG_ARGON2_AVX2 | RANDOMX_FLAG_ARGON2_SSSE3
|
||||
)
|
||||
|
||||
func GetFlags() (flags uint64) {
|
||||
func GetFlags() (flags Flag) {
|
||||
flags = RANDOMX_FLAG_DEFAULT
|
||||
if runtime.GOARCH == "amd64" {
|
||||
flags |= RANDOMX_FLAG_JIT
|
||||
|
||||
if cpu.X86.HasAES {
|
||||
if aes.HasHardAESImplementation && cpu.X86.HasAES {
|
||||
flags |= RANDOMX_FLAG_HARD_AES
|
||||
}
|
||||
|
||||
if cpu.X86.HasSSSE3 {
|
||||
flags |= RANDOMX_FLAG_ARGON2_SSSE3
|
||||
}
|
||||
|
||||
if cpu.X86.HasAVX2 {
|
||||
flags |= RANDOMX_FLAG_ARGON2_AVX2
|
||||
}
|
||||
}
|
||||
|
||||
if runtime.GOOS == "openbsd" || runtime.GOOS == "netbsd" || ((runtime.GOOS == "darwin" || runtime.GOOS == "ios") && runtime.GOARCH == "arm64") {
|
||||
flags |= RANDOMX_FLAG_SECURE
|
||||
}
|
||||
|
||||
return flags
|
||||
}
|
||||
|
|
63
internal/aes/hard_amd64.go
Normal file
63
internal/aes/hard_amd64.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
//go:build amd64 && !purego
|
||||
|
||||
package aes
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v3/internal/asm"
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v3/internal/keys"
|
||||
"golang.org/x/sys/cpu"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const HasHardAESImplementation = true
|
||||
|
||||
type hardAES struct {
|
||||
}
|
||||
|
||||
func NewHardAES() AES {
|
||||
if cpu.X86.HasAES {
|
||||
return hardAES{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h hardAES) HashAes1Rx4(input []byte, output *[64]byte) {
|
||||
if len(input)%len(output) != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
|
||||
asm.HashAes1Rx4(&keys.AesHash1R_State, &keys.AesHash1R_XKeys, output, unsafe.SliceData(input), uint64(len(input)))
|
||||
}
|
||||
|
||||
func (h hardAES) FillAes1Rx4(state *[64]byte, output []byte) {
|
||||
if len(output)%len(state) != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
|
||||
// Reference to state without copying
|
||||
states := (*[4][4]uint32)(unsafe.Pointer(state))
|
||||
asm.FillAes1Rx4(states, &keys.AesGenerator1R_Keys, unsafe.SliceData(output), uint64(len(output)))
|
||||
runtime.KeepAlive(state)
|
||||
}
|
||||
|
||||
func (h hardAES) FillAes4Rx4(state [64]byte, output []byte) {
|
||||
if len(output)%len(state) != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
|
||||
// state is copied on caller
|
||||
|
||||
// Copy state
|
||||
states := (*[4][4]uint32)(unsafe.Pointer(&state))
|
||||
|
||||
for outptr := 0; outptr < len(output); outptr += len(state) {
|
||||
asm.AESRoundTrip_DecEnc(states, &fillAes4Rx4Keys0)
|
||||
asm.AESRoundTrip_DecEnc(states, &fillAes4Rx4Keys1)
|
||||
asm.AESRoundTrip_DecEnc(states, &fillAes4Rx4Keys2)
|
||||
asm.AESRoundTrip_DecEnc(states, &fillAes4Rx4Keys3)
|
||||
|
||||
copy(output[outptr:], state[:])
|
||||
}
|
||||
}
|
9
internal/aes/hard_generic.go
Normal file
9
internal/aes/hard_generic.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
//go:build !amd64 || purego
|
||||
|
||||
package aes
|
||||
|
||||
const HasHardAESImplementation = false
|
||||
|
||||
func NewHardAES() AES {
|
||||
return nil
|
||||
}
|
|
@ -31,45 +31,8 @@ package aes
|
|||
|
||||
import (
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v3/internal/keys"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// HashAes1Rx4
|
||||
//
|
||||
// Calculate a 512-bit hash of 'input' using 4 lanes of AES.
|
||||
// The input is treated as a set of round keys for the encryption
|
||||
// of the initial state.
|
||||
//
|
||||
// 'inputSize' must be a multiple of 64.
|
||||
//
|
||||
// For a 2 MiB input, this has the same security as 32768-round
|
||||
// AES encryption.
|
||||
//
|
||||
// Hashing throughput: >20 GiB/s per CPU core with hardware AES
|
||||
func HashAes1Rx4(input []byte, output *[64]byte) {
|
||||
if len(input)%64 != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
hashAes1Rx4(input, output)
|
||||
}
|
||||
|
||||
// FillAes1Rx4
|
||||
//
|
||||
// Fill 'output' with pseudorandom data based on 512-bit 'state'.
|
||||
// The state is encrypted using a single AES round per 16 bytes of output
|
||||
// in 4 lanes.
|
||||
//
|
||||
// 'output' size must be a multiple of 64.
|
||||
//
|
||||
// The modified state is written back to 'state' to allow multiple
|
||||
// calls to this function.
|
||||
func FillAes1Rx4(state *[64]byte, output []byte) {
|
||||
if len(output)%len(state) != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
fillAes1Rx4(state, output)
|
||||
}
|
||||
|
||||
var fillAes4Rx4Keys0 = [4][4]uint32{
|
||||
keys.AesGenerator4R_Keys[0],
|
||||
keys.AesGenerator4R_Keys[0],
|
||||
|
@ -94,25 +57,3 @@ var fillAes4Rx4Keys3 = [4][4]uint32{
|
|||
keys.AesGenerator4R_Keys[7],
|
||||
keys.AesGenerator4R_Keys[7],
|
||||
}
|
||||
|
||||
// FillAes4Rx4 used to generate final program
|
||||
func FillAes4Rx4(state [64]byte, output []byte) {
|
||||
if len(output)%len(state) != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
|
||||
// state is copied on caller
|
||||
|
||||
// Copy state
|
||||
states := (*[4][4]uint32)(unsafe.Pointer(&state))
|
||||
|
||||
for outptr := 0; outptr < len(output); outptr += len(state) {
|
||||
aesroundtrip_decenc(states, &fillAes4Rx4Keys0)
|
||||
aesroundtrip_decenc(states, &fillAes4Rx4Keys1)
|
||||
aesroundtrip_decenc(states, &fillAes4Rx4Keys2)
|
||||
aesroundtrip_decenc(states, &fillAes4Rx4Keys3)
|
||||
|
||||
copy(output[outptr:], state[:])
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
//go:build amd64 && !purego
|
||||
|
||||
package aes
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v3/internal/asm"
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v3/internal/keys"
|
||||
"golang.org/x/sys/cpu"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var supportsAES = cpu.X86.HasAES
|
||||
|
||||
func fillAes1Rx4(state *[64]byte, output []byte) {
|
||||
// Reference to state without copying
|
||||
states := (*[4][4]uint32)(unsafe.Pointer(state))
|
||||
|
||||
if supportsAES {
|
||||
asm.FillAes1Rx4(states, &keys.AesGenerator1R_Keys, unsafe.SliceData(output), uint64(len(output)))
|
||||
return
|
||||
}
|
||||
|
||||
for outptr := 0; outptr < len(output); outptr += len(state) {
|
||||
aesroundtrip_decenc(states, &keys.AesGenerator1R_Keys)
|
||||
|
||||
copy(output[outptr:], state[:])
|
||||
}
|
||||
}
|
||||
|
||||
func hashAes1Rx4(input []byte, output *[64]byte) {
|
||||
if supportsAES {
|
||||
asm.HashAes1Rx4(&keys.AesHash1R_State, &keys.AesHash1R_XKeys, output, unsafe.SliceData(input), uint64(len(input)))
|
||||
return
|
||||
}
|
||||
|
||||
// states are copied
|
||||
states := keys.AesHash1R_State
|
||||
|
||||
for input_ptr := 0; input_ptr < len(input); input_ptr += 64 {
|
||||
in := (*[4][4]uint32)(unsafe.Pointer(unsafe.SliceData(input[input_ptr:])))
|
||||
|
||||
aesroundtrip_encdec(&states, in)
|
||||
}
|
||||
|
||||
aesroundtrip_encdec1(&states, &keys.AesHash1R_XKeys[0])
|
||||
|
||||
aesroundtrip_encdec1(&states, &keys.AesHash1R_XKeys[1])
|
||||
|
||||
copy(output[:], (*[64]byte)(unsafe.Pointer(&states))[:])
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
//go:build !amd64 || purego
|
||||
|
||||
package aes
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v3/internal/keys"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func fillAes1Rx4(state *[64]byte, output []byte) {
|
||||
// Reference to state without copying
|
||||
states := (*[4][4]uint32)(unsafe.Pointer(state))
|
||||
|
||||
for outptr := 0; outptr < len(output); outptr += len(state) {
|
||||
aesroundtrip_decenc(states, &keys.AesGenerator1R_Keys)
|
||||
|
||||
copy(output[outptr:], state[:])
|
||||
}
|
||||
}
|
||||
|
||||
func hashAes1Rx4(input []byte, output *[64]byte) {
|
||||
// states are copied
|
||||
states := keys.AesHash1R_State
|
||||
|
||||
for input_ptr := 0; input_ptr < len(input); input_ptr += 64 {
|
||||
in := (*[4][4]uint32)(unsafe.Pointer(unsafe.SliceData(input[input_ptr:])))
|
||||
|
||||
aesroundtrip_encdec(&states, in)
|
||||
}
|
||||
|
||||
aesroundtrip_encdec1(&states, &keys.AesHash1R_XKeys[0])
|
||||
|
||||
aesroundtrip_encdec1(&states, &keys.AesHash1R_XKeys[1])
|
||||
|
||||
copy(output[:], (*[64]byte)(unsafe.Pointer(&states))[:])
|
||||
}
|
35
internal/aes/impl.go
Normal file
35
internal/aes/impl.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package aes
|
||||
|
||||
type AES interface {
|
||||
|
||||
// HashAes1Rx4
|
||||
//
|
||||
// Calculate a 512-bit hash of 'input' using 4 lanes of AES.
|
||||
// The input is treated as a set of round keys for the encryption
|
||||
// of the initial state.
|
||||
//
|
||||
// 'input' size must be a multiple of 64.
|
||||
//
|
||||
// For a 2 MiB input, this has the same security as 32768-round
|
||||
// AES encryption.
|
||||
//
|
||||
// Hashing throughput: >20 GiB/s per CPU core with hardware AES
|
||||
HashAes1Rx4(input []byte, output *[64]byte)
|
||||
|
||||
// FillAes1Rx4
|
||||
//
|
||||
// Fill 'output' with pseudorandom data based on 512-bit 'state'.
|
||||
// The state is encrypted using a single AES round per 16 bytes of output
|
||||
// in 4 lanes.
|
||||
//
|
||||
// 'output' size must be a multiple of 64.
|
||||
//
|
||||
// The modified state is written back to 'state' to allow multiple
|
||||
// calls to this function.
|
||||
FillAes1Rx4(state *[64]byte, output []byte)
|
||||
|
||||
// FillAes4Rx4 used to generate final program
|
||||
//
|
||||
// 'state' is copied when calling
|
||||
FillAes4Rx4(state [64]byte, output []byte)
|
||||
}
|
|
@ -29,3 +29,24 @@ func soft_aesdec(state *[4]uint32, key *[4]uint32) {
|
|||
state[2] = key[2] ^ td0[uint8(s2)] ^ td1[uint8(s1>>8)] ^ td2[uint8(s0>>16)] ^ td3[uint8(s3>>24)]
|
||||
state[3] = key[3] ^ td0[uint8(s3)] ^ td1[uint8(s2>>8)] ^ td2[uint8(s1>>16)] ^ td3[uint8(s0>>24)]
|
||||
}
|
||||
|
||||
func soft_aesroundtrip_decenc(states *[4][4]uint32, keys *[4][4]uint32) {
|
||||
soft_aesdec(&states[0], &keys[0])
|
||||
soft_aesenc(&states[1], &keys[1])
|
||||
soft_aesdec(&states[2], &keys[2])
|
||||
soft_aesenc(&states[3], &keys[3])
|
||||
}
|
||||
|
||||
func soft_aesroundtrip_encdec(states *[4][4]uint32, keys *[4][4]uint32) {
|
||||
soft_aesenc(&states[0], &keys[0])
|
||||
soft_aesdec(&states[1], &keys[1])
|
||||
soft_aesenc(&states[2], &keys[2])
|
||||
soft_aesdec(&states[3], &keys[3])
|
||||
}
|
||||
|
||||
func soft_aesroundtrip_encdec1(states *[4][4]uint32, key *[4]uint32) {
|
||||
soft_aesenc(&states[0], key)
|
||||
soft_aesdec(&states[1], key)
|
||||
soft_aesenc(&states[2], key)
|
||||
soft_aesdec(&states[3], key)
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
//go:build amd64 && !purego
|
||||
|
||||
package aes
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v3/internal/asm"
|
||||
)
|
||||
|
||||
func aesroundtrip_decenc(states *[4][4]uint32, keys *[4][4]uint32) {
|
||||
if supportsAES {
|
||||
asm.AESRoundTrip_DecEnc(states, keys)
|
||||
} else {
|
||||
soft_aesdec(&states[0], &keys[0])
|
||||
soft_aesenc(&states[1], &keys[1])
|
||||
soft_aesdec(&states[2], &keys[2])
|
||||
soft_aesenc(&states[3], &keys[3])
|
||||
}
|
||||
}
|
||||
|
||||
func aesroundtrip_encdec(states *[4][4]uint32, keys *[4][4]uint32) {
|
||||
if supportsAES {
|
||||
asm.AESRoundTrip_EncDec(states, keys)
|
||||
} else {
|
||||
soft_aesenc(&states[0], &keys[0])
|
||||
soft_aesdec(&states[1], &keys[1])
|
||||
soft_aesenc(&states[2], &keys[2])
|
||||
soft_aesdec(&states[3], &keys[3])
|
||||
}
|
||||
}
|
||||
|
||||
func aesroundtrip_encdec1(states *[4][4]uint32, key *[4]uint32) {
|
||||
if supportsAES {
|
||||
asm.AESRoundTrip_EncDec1(states, key)
|
||||
} else {
|
||||
soft_aesenc(&states[0], key)
|
||||
soft_aesdec(&states[1], key)
|
||||
soft_aesenc(&states[2], key)
|
||||
soft_aesdec(&states[3], key)
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
//go:build !amd64 || purego
|
||||
|
||||
package aes
|
||||
|
||||
func aesenc(state *[4]uint32, key *[4]uint32) {
|
||||
soft_aesenc(state, key)
|
||||
}
|
||||
|
||||
func aesdec(state *[4]uint32, key *[4]uint32) {
|
||||
soft_aesdec(state, key)
|
||||
}
|
||||
|
||||
func aesroundtrip_decenc(states *[4][4]uint32, keys *[4][4]uint32) {
|
||||
aesdec(&states[0], &keys[0])
|
||||
aesenc(&states[1], &keys[1])
|
||||
aesdec(&states[2], &keys[2])
|
||||
aesenc(&states[3], &keys[3])
|
||||
}
|
||||
|
||||
func aesroundtrip_encdec(states *[4][4]uint32, keys *[4][4]uint32) {
|
||||
aesenc(&states[0], &keys[0])
|
||||
aesdec(&states[1], &keys[1])
|
||||
aesenc(&states[2], &keys[2])
|
||||
aesdec(&states[3], &keys[3])
|
||||
}
|
||||
|
||||
func aesroundtrip_encdec1(states *[4][4]uint32, key *[4]uint32) {
|
||||
aesenc(&states[0], key)
|
||||
aesdec(&states[1], key)
|
||||
aesenc(&states[2], key)
|
||||
aesdec(&states[3], key)
|
||||
}
|
69
internal/aes/soft.go
Normal file
69
internal/aes/soft.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
package aes
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v3/internal/keys"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type softAES struct {
|
||||
}
|
||||
|
||||
func NewSoftAES() AES {
|
||||
return softAES{}
|
||||
}
|
||||
|
||||
func (aes softAES) HashAes1Rx4(input []byte, output *[64]byte) {
|
||||
if len(input)%len(output) != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
// states are copied
|
||||
states := (*[4][4]uint32)(unsafe.Pointer(output))
|
||||
*states = keys.AesHash1R_State
|
||||
|
||||
for input_ptr := 0; input_ptr < len(input); input_ptr += 64 {
|
||||
in := (*[4][4]uint32)(unsafe.Pointer(unsafe.SliceData(input[input_ptr:])))
|
||||
|
||||
soft_aesroundtrip_encdec(states, in)
|
||||
}
|
||||
|
||||
soft_aesroundtrip_encdec1(states, &keys.AesHash1R_XKeys[0])
|
||||
|
||||
soft_aesroundtrip_encdec1(states, &keys.AesHash1R_XKeys[1])
|
||||
|
||||
runtime.KeepAlive(output)
|
||||
}
|
||||
|
||||
func (aes softAES) FillAes1Rx4(state *[64]byte, output []byte) {
|
||||
if len(output)%len(state) != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
// Reference to state without copying
|
||||
states := (*[4][4]uint32)(unsafe.Pointer(state))
|
||||
|
||||
for outptr := 0; outptr < len(output); outptr += len(state) {
|
||||
soft_aesroundtrip_decenc(states, &keys.AesGenerator1R_Keys)
|
||||
|
||||
copy(output[outptr:], state[:])
|
||||
}
|
||||
}
|
||||
|
||||
func (aes softAES) FillAes4Rx4(state [64]byte, output []byte) {
|
||||
if len(output)%len(state) != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
|
||||
// state is copied on caller
|
||||
|
||||
// Copy state
|
||||
states := (*[4][4]uint32)(unsafe.Pointer(&state))
|
||||
|
||||
for outptr := 0; outptr < len(output); outptr += len(state) {
|
||||
soft_aesroundtrip_decenc(states, &fillAes4Rx4Keys0)
|
||||
soft_aesroundtrip_decenc(states, &fillAes4Rx4Keys1)
|
||||
soft_aesroundtrip_decenc(states, &fillAes4Rx4Keys2)
|
||||
soft_aesroundtrip_decenc(states, &fillAes4Rx4Keys3)
|
||||
|
||||
copy(output[outptr:], state[:])
|
||||
}
|
||||
}
|
18
vm.go
18
vm.go
|
@ -45,6 +45,8 @@ type REG struct {
|
|||
type VM struct {
|
||||
ScratchPad ScratchPad
|
||||
|
||||
AES aes.AES
|
||||
|
||||
Dataset Dataset
|
||||
|
||||
program ByteCode
|
||||
|
@ -55,6 +57,15 @@ func NewVM(dataset Dataset) *VM {
|
|||
vm := &VM{
|
||||
Dataset: dataset,
|
||||
}
|
||||
|
||||
if dataset.Flags()&RANDOMX_FLAG_HARD_AES > 0 {
|
||||
vm.AES = aes.NewHardAES()
|
||||
}
|
||||
// fallback
|
||||
if vm.AES == nil {
|
||||
vm.AES = aes.NewSoftAES()
|
||||
}
|
||||
|
||||
if dataset.Cache().HasJIT() {
|
||||
vm.jitProgram = mapProgram(nil, int(RandomXCodeSize))
|
||||
if dataset.Flags()&RANDOMX_FLAG_SECURE == 0 {
|
||||
|
@ -74,7 +85,7 @@ func (vm *VM) run(inputHash [64]byte, roundingMode uint8) (reg RegisterFile) {
|
|||
|
||||
// buffer first 128 bytes are entropy below rest are program bytes
|
||||
var buffer [16*8 + RANDOMX_PROGRAM_SIZE*8]byte
|
||||
aes.FillAes4Rx4(inputHash, buffer[:])
|
||||
vm.AES.FillAes4Rx4(inputHash, buffer[:])
|
||||
|
||||
entropy := (*[16]uint64)(unsafe.Pointer(&buffer))
|
||||
|
||||
|
@ -202,7 +213,8 @@ func (vm *VM) run(inputHash [64]byte, roundingMode uint8) (reg RegisterFile) {
|
|||
}
|
||||
|
||||
func (vm *VM) initScratchpad(seed *[64]byte) {
|
||||
vm.ScratchPad.Init(seed)
|
||||
clear(vm.ScratchPad[:])
|
||||
vm.AES.FillAes1Rx4(seed, vm.ScratchPad[:])
|
||||
}
|
||||
|
||||
func (vm *VM) runLoops(tempHash [64]byte) RegisterFile {
|
||||
|
@ -243,7 +255,7 @@ func (vm *VM) CalculateHash(input []byte, output *[32]byte) {
|
|||
reg := vm.runLoops(tempHash)
|
||||
|
||||
// now hash the scratch pad as it will act as register A
|
||||
aes.HashAes1Rx4(vm.ScratchPad[:], &tempHash)
|
||||
vm.AES.HashAes1Rx4(vm.ScratchPad[:], &tempHash)
|
||||
|
||||
regMem := reg.Memory()
|
||||
// write hash onto register A
|
||||
|
|
|
@ -30,7 +30,6 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
package randomx
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v3/internal/aes"
|
||||
"unsafe"
|
||||
)
|
||||
import "encoding/binary"
|
||||
|
@ -359,15 +358,11 @@ func CompileProgramToByteCode(prog []byte, bc *ByteCode) {
|
|||
|
||||
type ScratchPad [ScratchpadSize]byte
|
||||
|
||||
func (pad *ScratchPad) Init(seed *[64]byte) {
|
||||
// calculate and fill scratchpad
|
||||
clear(pad[:])
|
||||
aes.FillAes1Rx4(seed, pad[:])
|
||||
}
|
||||
func (pad *ScratchPad) Store64(addr uint32, val uint64) {
|
||||
*(*uint64)(unsafe.Pointer(&pad[addr])) = val
|
||||
//binary.LittleEndian.PutUint64(pad[addr:], val)
|
||||
}
|
||||
|
||||
func (pad *ScratchPad) Load64(addr uint32) uint64 {
|
||||
return *(*uint64)(unsafe.Pointer(&pad[addr]))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue