Added partial hash and fill AES for First/Next/Last hashing modes in VM

This commit is contained in:
DataHoarder 2024-05-02 11:41:00 +02:00
parent acfff4a4ad
commit 9826b7beb4
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
5 changed files with 112 additions and 3 deletions

View file

@ -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)
}

View file

@ -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

View file

@ -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)
}

View file

@ -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
View file

@ -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 {