diff --git a/assembly/cache.ts b/assembly/cache.ts new file mode 100644 index 0000000..59b134f --- /dev/null +++ b/assembly/cache.ts @@ -0,0 +1,2 @@ +export declare function load(ptr: u32, offset: u32, len: u32): void; +export declare function save(ptr: u32, offset: u32, len: u32): void; diff --git a/assembly/hello-world/index.ts b/assembly/hello-world/index.ts index 6823245..98258cb 100644 --- a/assembly/hello-world/index.ts +++ b/assembly/hello-world/index.ts @@ -1,8 +1,9 @@ import * as env from '../env' import * as bignum from '../bignum' +import * as cache from '../cache' /* - * Increments preStateRoot by one + * Increments preStateRoot by the cached value of previous block data */ export function main(): void { var preStateRootPtr: u32 = __heap_base @@ -11,9 +12,13 @@ export function main(): void { var postStateRootPtr: u32 = __heap_base + 32 var numPtr: u32 = __heap_base + 64 - store(numPtr, 1, 31) + cache.load(numPtr, 0, 32) bignum.add256(preStateRootPtr, numPtr, postStateRootPtr) + var blockDataPtr: u32 = __heap_base + 96 + env.eth2_blockDataCopy(blockDataPtr, 0, 32) + cache.save(blockDataPtr, 0, 32) + env.eth2_savePostStateRoot(postStateRootPtr) } diff --git a/src/browser.js b/src/browser.js index 674f117..b83f99e 100644 --- a/src/browser.js +++ b/src/browser.js @@ -1,5 +1,5 @@ const { safeLoad } = require('js-yaml') -const { TestCase, parseYaml, getImports, setMemory, getRes } = require('../dist/lib') +const { TestCase, parseYaml, getImports, setMemory, getRes, CACHE_SIZE } = require('../dist/lib') async function main() { let yamlPath = 'test.yaml' @@ -10,12 +10,17 @@ async function main() { const wasmResponse = await fetch(testCase.script) const wasmBuffer = await wasmResponse.arrayBuffer() let preStateRoot = testCase.preStateRoot + let readableCache = Buffer.alloc(CACHE_SIZE) + let writableCache = Buffer.alloc(CACHE_SIZE) for (const block of testCase.blocks) { - const compiled = await WebAssembly.instantiate(wasmBuffer, getImports({ preStateRoot, blockData: block })) + const compiled = await WebAssembly.instantiate(wasmBuffer, getImports({ preStateRoot, blockData: block, readableCache, writableCache })) const instance = compiled.instance setMemory(instance.exports.memory) instance.exports.main() preStateRoot = getRes() + + readableCache = writableCache + writableCache = Buffer.alloc(CACHE_SIZE) } if (!testCase.postStateRoot.equals(getRes())) { console.error('Assertion failed, post state root doesn\'t match') diff --git a/src/cli.ts b/src/cli.ts index c769038..2fe44ef 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,7 +1,7 @@ import * as assert from 'assert' import * as fs from 'fs' import { safeLoad } from 'js-yaml' -import { TestCase, parseYaml, getImports, setMemory, getRes } from './lib' +import { TestCase, parseYaml, getImports, setMemory, getRes, CACHE_SIZE } from './lib' function main() { let yamlPath @@ -19,14 +19,21 @@ function main() { const wasmFile = fs.readFileSync(testCase.script) const wasmModule = new WebAssembly.Module(wasmFile) let preStateRoot = testCase.preStateRoot + let readableCache = Buffer.alloc(CACHE_SIZE) + let writableCache = Buffer.alloc(CACHE_SIZE) for (const block of testCase.blocks) { - const instance = new WebAssembly.Instance(wasmModule, getImports({ preStateRoot, blockData: block })) + const instance = new WebAssembly.Instance(wasmModule, getImports({ preStateRoot, blockData: block, readableCache, writableCache })) setMemory(instance.exports.memory) + let t = process.hrtime() instance.exports.main() t = process.hrtime(t) console.log('benchmark took %d seconds and %d nanoseconds (%d ms)', t[0], t[1], t[1] / 1000000) + preStateRoot = getRes() + + readableCache = writableCache + writableCache = Buffer.alloc(CACHE_SIZE) } assert(testCase.postStateRoot.equals(getRes()), `expected ${testCase.postStateRoot.toString('hex')}, received ${getRes().toString('hex')}`) } diff --git a/src/lib.ts b/src/lib.ts index 9b0b085..e720c68 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -4,6 +4,9 @@ import { safeLoad } from 'js-yaml' import BN = require('bn.js') import { TWO_POW256 } from 'ethereumjs-util' +// Cache size in bytes +export const CACHE_SIZE = 256 * 1024 + let mem: WebAssembly.Memory let res: Buffer @@ -37,6 +40,8 @@ export interface TestCase { export interface EnvData { preStateRoot: Buffer blockData: Buffer + readableCache: Buffer + writableCache: Buffer } export const getImports = (env: EnvData) => { @@ -58,6 +63,16 @@ export const getImports = (env: EnvData) => { debug_endTimer: () => console.log('end timer'), abort: () => { throw ('Wasm aborted') } }, + cache: { + load: (ptr: number, offset: number, len: number) => { + const c = env.readableCache.slice(offset, offset + len) + memset(mem, ptr, c) + }, + save: (ptr: number, offset: number, len: number) => { + const c = memget(mem, ptr, len) + env.writableCache.write(c.toString('hex'), offset, len, 'hex') + } + }, bignum: { add256: (aOffset: number, bOffset: number, cOffset: number) => { const a = new BN(memget(mem, aOffset, 32)) diff --git a/test.yaml b/test.yaml index a491ad2..be04c54 100644 --- a/test.yaml +++ b/test.yaml @@ -6,9 +6,11 @@ shard_pre_state: - "0000000000000000000000000000000000000000000000000000000000000001" shard_blocks: - env: 0 - data: "" + data: "0000000000000000000000000000000000000000000000000000000000000005" - env: 0 - data: "" + data: "0000000000000000000000000000000000000000000000000000000000000007" + - env: 0 + data: "000000000000000000000000000000000000000000000000000000000000000b" shard_post_state: exec_env_states: - - "0000000000000000000000000000000000000000000000000000000000000003" + - "000000000000000000000000000000000000000000000000000000000000000d"