Added partial hash and fill AES for First/Next/Last hashing modes in VM
This commit is contained in:
parent
acfff4a4ad
commit
9826b7beb4
|
@ -23,7 +23,7 @@ func NewHardAES() AES {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (h hardAES) HashAes1Rx4(input []byte, output *[64]byte) {
|
||||
func (aes hardAES) HashAes1Rx4(input []byte, output *[64]byte) {
|
||||
if len(input)%len(output) != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ func (h hardAES) HashAes1Rx4(input []byte, output *[64]byte) {
|
|||
asm.HashAes1Rx4(&keys.AesHash1R_State, &keys.AesHash1R_XKeys, output, unsafe.SliceData(input), uint64(len(input)))
|
||||
}
|
||||
|
||||
func (h hardAES) FillAes1Rx4(state *[64]byte, output []byte) {
|
||||
func (aes hardAES) FillAes1Rx4(state *[64]byte, output []byte) {
|
||||
if len(output)%len(state) != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func (h hardAES) FillAes1Rx4(state *[64]byte, output []byte) {
|
|||
runtime.KeepAlive(state)
|
||||
}
|
||||
|
||||
func (h hardAES) FillAes4Rx4(state [64]byte, output []byte) {
|
||||
func (aes hardAES) FillAes4Rx4(state [64]byte, output []byte) {
|
||||
if len(output)%len(state) != 0 {
|
||||
panic("unsupported")
|
||||
}
|
||||
|
@ -61,3 +61,9 @@ func (h hardAES) FillAes4Rx4(state [64]byte, output []byte) {
|
|||
copy(output[outptr:], state[:])
|
||||
}
|
||||
}
|
||||
|
||||
func (aes hardAES) HashAndFillAes1Rx4(scratchpad []byte, output *[64]byte, fillState *[64]byte) {
|
||||
//TODO
|
||||
aes.HashAes1Rx4(scratchpad, output)
|
||||
aes.FillAes1Rx4(fillState, scratchpad)
|
||||
}
|
||||
|
|
|
@ -28,6 +28,9 @@ type AES interface {
|
|||
// calls to this function.
|
||||
FillAes1Rx4(state *[64]byte, output []byte)
|
||||
|
||||
// HashAndFillAes1Rx4 Hashes and fills scratchpad and output in one sweep
|
||||
HashAndFillAes1Rx4(scratchpad []byte, output *[64]byte, fillState *[64]byte)
|
||||
|
||||
// FillAes4Rx4 used to generate final program
|
||||
//
|
||||
// 'state' is copied when calling
|
||||
|
|
|
@ -67,3 +67,9 @@ func (aes softAES) FillAes4Rx4(state [64]byte, output []byte) {
|
|||
copy(output[outptr:], state[:])
|
||||
}
|
||||
}
|
||||
|
||||
func (aes softAES) HashAndFillAes1Rx4(scratchpad []byte, output *[64]byte, fillState *[64]byte) {
|
||||
//TODO
|
||||
aes.HashAes1Rx4(scratchpad, output)
|
||||
aes.FillAes1Rx4(fillState, scratchpad)
|
||||
}
|
||||
|
|
|
@ -143,6 +143,60 @@ func Test_RandomXLight(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_RandomXBatch(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, n := range []string{"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")
|
||||
}
|
||||
|
||||
c := NewCache(tFlags)
|
||||
if c == nil {
|
||||
t.Fatal("nil cache")
|
||||
}
|
||||
defer func() {
|
||||
err := c.Close()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}()
|
||||
tests := Tests[1:4]
|
||||
|
||||
c.Init(tests[0].key)
|
||||
vm, err := NewVM(tFlags, c, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
err := vm.Close()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
var outputHash [3][RANDOMX_HASH_SIZE]byte
|
||||
|
||||
vm.CalculateHashFirst(tests[0].input)
|
||||
vm.CalculateHashNext(tests[1].input, &outputHash[0])
|
||||
vm.CalculateHashNext(tests[2].input, &outputHash[1])
|
||||
vm.CalculateHashLast(&outputHash[2])
|
||||
|
||||
for i, test := range tests {
|
||||
outputHex := hex.EncodeToString(outputHash[i][:])
|
||||
|
||||
if outputHex != test.expected {
|
||||
t.Errorf("key=%v, input=%v", test.key, test.input)
|
||||
t.Errorf("expected=%s, actual=%s", test.expected, outputHex)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_RandomXFull(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping full mode with -short")
|
||||
|
|
40
vm.go
40
vm.go
|
@ -327,6 +327,46 @@ func (vm *VM) CalculateHash(input []byte, output *[RANDOMX_HASH_SIZE]byte) {
|
|||
*output = blake2b.Sum256(regMem[:])
|
||||
}
|
||||
|
||||
// CalculateHashFirst will begin a hash calculation.
|
||||
func (vm *VM) CalculateHashFirst(input []byte) {
|
||||
vm.hashState = blake2b.Sum512(input)
|
||||
|
||||
vm.initScratchpad(&vm.hashState)
|
||||
}
|
||||
|
||||
// CalculateHashNext will output the hash value of the previous input and begin the calculation of the next hash.
|
||||
func (vm *VM) CalculateHashNext(nextInput []byte, output *[RANDOMX_HASH_SIZE]byte) {
|
||||
vm.runLoops()
|
||||
|
||||
// now hash the scratch pad as it will act as register A
|
||||
vm.AES.HashAes1Rx4(vm.pad[:], &vm.hashState)
|
||||
|
||||
// Finish current hash and fill the scratchpad for the next hash at the same time
|
||||
regMem := vm.registerFile.Memory()
|
||||
vm.hashState = blake2b.Sum512(nextInput)
|
||||
// write hash onto register A
|
||||
vm.AES.HashAndFillAes1Rx4(vm.pad[:], (*[64]byte)(unsafe.Pointer(unsafe.SliceData(regMem[RegisterFileSize-RegistersCountFloat*2*8:]))), &vm.hashState)
|
||||
runtime.KeepAlive(regMem)
|
||||
|
||||
// write R, F, E, A registers
|
||||
*output = blake2b.Sum256(regMem[:])
|
||||
}
|
||||
|
||||
// CalculateHashLast will output the hash value of the previous input.
|
||||
func (vm *VM) CalculateHashLast(output *[RANDOMX_HASH_SIZE]byte) {
|
||||
vm.runLoops()
|
||||
|
||||
// now hash the scratch pad as it will act as register A
|
||||
vm.AES.HashAes1Rx4(vm.pad[:], &vm.hashState)
|
||||
|
||||
regMem := vm.registerFile.Memory()
|
||||
// write hash onto register A
|
||||
copy(regMem[RegisterFileSize-RegistersCountFloat*2*8:], vm.hashState[:])
|
||||
|
||||
// write R, F, E, A registers
|
||||
*output = blake2b.Sum256(regMem[:])
|
||||
}
|
||||
|
||||
// Close Releases all memory occupied by the structure.
|
||||
func (vm *VM) Close() error {
|
||||
if vm.jitProgram != nil {
|
||||
|
|
Loading…
Reference in a new issue