From 3ccd982c3eff963f31b13a30e43a44e08d5d5eca Mon Sep 17 00:00:00 2001 From: Leonidas Date: Wed, 22 Jan 2025 13:10:06 +0200 Subject: [PATCH 1/2] Add query host function --- .../polkavm/host_call/accumulate_functions.go | 37 +++- .../host_call/accumulate_functions_test.go | 172 ++++++++++++++++++ 2 files changed, 208 insertions(+), 1 deletion(-) diff --git a/internal/polkavm/host_call/accumulate_functions.go b/internal/polkavm/host_call/accumulate_functions.go index 5cd271a..f76bb3d 100644 --- a/internal/polkavm/host_call/accumulate_functions.go +++ b/internal/polkavm/host_call/accumulate_functions.go @@ -322,7 +322,42 @@ func Query(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair) ( } gas -= QueryCost - // TODO: implement method + o, z := regs[A0], regs[A1] + + // let h = μo..o+32 if Zo..o+32 ⊂ Vμ + h := make([]byte, 32) + if err := mem.Read(uint32(o), h); err != nil { + // otherwise ∇ => OOB + return gas, withCode(regs, OOB), mem, ctxPair, nil + } + + // let a = (xs)l[h, z] if (h, z) ∈ K((xs)l) + serviceAccount := ctxPair.RegularCtx.ServiceAccount() + key := service.PreImageMetaKey{ + Hash: crypto.Hash(h), + Length: service.PreimageLength(z), + } + a, exists := serviceAccount.PreimageMeta[key] + if !exists { + // a = ∇ => (NONE, 0) + regs[A1] = 0 + return gas, withCode(regs, NONE), mem, ctxPair, nil + } + + switch len(a) { + case 0: + // a = [] => (0, 0) + regs[A0], regs[A1] = 0, 0 + case 1: + // a = [x] => (1 + 2^32 * x, 0) + regs[A0], regs[A1] = 1+(uint64(a[0])<<32), 0 + case 2: + // a = [x, y] => (2 + 2^32 * x, y) + regs[A0], regs[A1] = 2+(uint64(a[0])<<32), uint64(a[1]) + case 3: + // a = [x, y, z] => (3 + 2^32 * x, y + 2^32 * z) + regs[A0], regs[A1] = 3+(uint64(a[0])<<32), uint64(a[1])+(uint64(a[2])<<32) + } return gas, regs, mem, ctxPair, nil } diff --git a/internal/polkavm/host_call/accumulate_functions_test.go b/internal/polkavm/host_call/accumulate_functions_test.go index e727964..ab53019 100644 --- a/internal/polkavm/host_call/accumulate_functions_test.go +++ b/internal/polkavm/host_call/accumulate_functions_test.go @@ -347,6 +347,178 @@ func TestAccumulate(t *testing.T) { }, }, }, + { + name: "query_empty_timeslots", + fn: fnStd(Query), + initialGas: 100, + initialRegs: deltaRegs{ + A1: 123, + }, + alloc: alloc{ + A0: hash2bytes(randomHash), + }, + X: AccumulateContext{ + ServiceId: 999, + AccumulationState: state.AccumulationState{ + ServiceState: service.ServiceState{ + 999: { + PreimageMeta: map[service.PreImageMetaKey]service.PreimageHistoricalTimeslots{ + { + Hash: randomHash, + Length: 123, + }: {}, + }, + }, + }, + }, + }, + expectedDeltaRegs: deltaRegs{ + A0: 0, + A1: 0, + }, + expectedGas: 88, + expectedX: AccumulateContext{ + ServiceId: 999, + AccumulationState: state.AccumulationState{ + ServiceState: service.ServiceState{ + 999: { + PreimageMeta: map[service.PreImageMetaKey]service.PreimageHistoricalTimeslots{ + {Hash: randomHash, Length: 123}: {}, + }, + }, + }, + }, + }, + }, + { + name: "query_1timeslot", + fn: fnStd(Query), + initialGas: 100, + initialRegs: deltaRegs{ + A1: 123, + }, + alloc: alloc{ + A0: hash2bytes(randomHash), + }, + X: AccumulateContext{ + ServiceId: 999, + AccumulationState: state.AccumulationState{ + ServiceState: service.ServiceState{ + 999: { + PreimageMeta: map[service.PreImageMetaKey]service.PreimageHistoricalTimeslots{ + { + Hash: randomHash, + Length: 123, + }: {11}, + }, + }, + }, + }, + }, + expectedDeltaRegs: deltaRegs{ + A0: 1 + (uint64(11) << 32), + A1: 0, + }, + expectedGas: 88, + expectedX: AccumulateContext{ + ServiceId: 999, + AccumulationState: state.AccumulationState{ + ServiceState: service.ServiceState{ + 999: { + PreimageMeta: map[service.PreImageMetaKey]service.PreimageHistoricalTimeslots{ + {Hash: randomHash, Length: 123}: {11}, + }, + }, + }, + }, + }, + }, + { + name: "query_2timeslots", + fn: fnStd(Query), + initialGas: 100, + initialRegs: deltaRegs{ + A1: 123, + }, + alloc: alloc{ + A0: hash2bytes(randomHash), + }, + X: AccumulateContext{ + ServiceId: 999, + AccumulationState: state.AccumulationState{ + ServiceState: service.ServiceState{ + 999: { + PreimageMeta: map[service.PreImageMetaKey]service.PreimageHistoricalTimeslots{ + { + Hash: randomHash, + Length: 123, + }: {11, 12}, + }, + }, + }, + }, + }, + expectedDeltaRegs: deltaRegs{ + A0: 2 + (uint64(11) << 32), + A1: uint64(12), + }, + expectedGas: 88, + expectedX: AccumulateContext{ + ServiceId: 999, + AccumulationState: state.AccumulationState{ + ServiceState: service.ServiceState{ + 999: { + PreimageMeta: map[service.PreImageMetaKey]service.PreimageHistoricalTimeslots{ + {Hash: randomHash, Length: 123}: {11, 12}, + }, + }, + }, + }, + }, + }, + { + name: "query_3timeslots", + fn: fnStd(Query), + initialGas: 100, + initialRegs: deltaRegs{ + A1: 123, + }, + alloc: alloc{ + A0: hash2bytes(randomHash), + }, + X: AccumulateContext{ + ServiceId: 999, + AccumulationState: state.AccumulationState{ + ServiceState: service.ServiceState{ + 999: { + PreimageMeta: map[service.PreImageMetaKey]service.PreimageHistoricalTimeslots{ + { + Hash: randomHash, + Length: 123, + }: {11, 12, 13}, + }, + }, + }, + }, + }, + expectedDeltaRegs: deltaRegs{ + A0: 3 + (uint64(11) << 32), + A1: uint64(12) + (uint64(13) << 32), + }, + expectedGas: 88, + expectedX: AccumulateContext{ + ServiceId: 999, + AccumulationState: state.AccumulationState{ + ServiceState: service.ServiceState{ + 999: { + PreimageMeta: map[service.PreImageMetaKey]service.PreimageHistoricalTimeslots{ + {Hash: randomHash, Length: 123}: {11, 12, 13}, + }, + }, + }, + }, + }, + }, { name: "solicit_out_of_gas", fn: fnTms(Solicit), From b91eaae971986f1e7cea247a82e5514e9009601a Mon Sep 17 00:00:00 2001 From: Leonidas Date: Thu, 23 Jan 2025 08:16:20 +0200 Subject: [PATCH 2/2] use more descriptive variable names --- internal/polkavm/host_call/accumulate_functions.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/polkavm/host_call/accumulate_functions.go b/internal/polkavm/host_call/accumulate_functions.go index f76bb3d..da8de79 100644 --- a/internal/polkavm/host_call/accumulate_functions.go +++ b/internal/polkavm/host_call/accumulate_functions.go @@ -322,11 +322,11 @@ func Query(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair) ( } gas -= QueryCost - o, z := regs[A0], regs[A1] + addr, preimageMetaKeyLength := regs[A0], regs[A1] // let h = μo..o+32 if Zo..o+32 ⊂ Vμ h := make([]byte, 32) - if err := mem.Read(uint32(o), h); err != nil { + if err := mem.Read(uint32(addr), h); err != nil { // otherwise ∇ => OOB return gas, withCode(regs, OOB), mem, ctxPair, nil } @@ -335,7 +335,7 @@ func Query(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair) ( serviceAccount := ctxPair.RegularCtx.ServiceAccount() key := service.PreImageMetaKey{ Hash: crypto.Hash(h), - Length: service.PreimageLength(z), + Length: service.PreimageLength(preimageMetaKeyLength), } a, exists := serviceAccount.PreimageMeta[key] if !exists {