-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement pointer dereferencing in TypeScript
- Loading branch information
Showing
35 changed files
with
4,144 additions
and
646 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
dist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# @ethdebug/pointers | ||
|
||
_This NPM package contains a reference implementation for dereferencing | ||
**ethdebug/format** [pointers](https://ethdebug.github.io/format/spec/pointer/overview)._ | ||
|
||
:warning: This package is currently unpublished until ethdebug/format is more | ||
complete. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** @type {import('ts-jest').JestConfigWithTsJest} */ | ||
module.exports = { | ||
preset: "ts-jest", | ||
testEnvironment: "node", | ||
extensionsToTreatAsEsm: [".ts"], | ||
moduleFileExtensions: ["ts", "js"], | ||
moduleNameMapper: { | ||
'^(\\.{1,2}/.*)\\.js$': '$1', | ||
}, | ||
modulePathIgnorePatterns: ["<rootDir>/dist/"], | ||
transform: { | ||
// '^.+\\.[tj]sx?$' to process js/ts with `ts-jest` | ||
// '^.+\\.m?[tj]sx?$' to process js/ts/mjs/mts with `ts-jest` | ||
'^.+\\.tsx?$': [ | ||
'ts-jest', | ||
{ | ||
useESM: true, | ||
}, | ||
], | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "@ethdebug/pointers", | ||
"version": "0.1.0-0", | ||
"description": "Reference implementation for ethdebug/format pointers", | ||
"main": "dist/src/index.js", | ||
"type": "module", | ||
"license": "MIT", | ||
"scripts": { | ||
"prepare": "tsc", | ||
"watch": "yarn prepare --watch", | ||
"test": "node --experimental-vm-modules $(yarn bin jest)" | ||
}, | ||
"devDependencies": { | ||
"@ethdebug/format": "^0.1.0-0", | ||
"@jest/globals": "^29.7.0", | ||
"chalk": "^5.3.0", | ||
"cli-highlight": "^2.1.11", | ||
"ganache": "7.9.x", | ||
"jest": "^29.7.0", | ||
"solc": "^0.8.26", | ||
"ts-jest": "^29.1.1", | ||
"ts-node": "^10.9.2", | ||
"typescript": "^5.3.3" | ||
}, | ||
"dependencies": { | ||
"ethereum-cryptography": "^2.1.3" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import type { Machine } from "./machine.js"; | ||
import type { Pointer } from "./pointer.js"; | ||
import type { Data } from "./data.js"; | ||
|
||
export interface Cursor { | ||
view(state: Machine.State): Promise<Cursor.View>; | ||
} | ||
|
||
export namespace Cursor { | ||
export interface View { | ||
read(region: Cursor.Region): Promise<Data>; | ||
regions: Regions | ||
} | ||
|
||
export type Regions = | ||
& Cursor.Region[] | ||
& { [name: string]: Cursor.Region; } | ||
& { | ||
named(name: string): Cursor.Region[]; | ||
lookup: { [name: string]: Cursor.Region }; | ||
}; | ||
|
||
export type Region<R extends Pointer.Region = Pointer.Region> = { | ||
[K in keyof R]: K extends "slot" | "offset" | "length" | ||
? R[K] extends Pointer.Expression | ||
? Data | ||
: R[K] extends Pointer.Expression | undefined | ||
? Data | undefined | ||
: R[K] | ||
: R[K]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
import { expect, describe, it } from "@jest/globals"; | ||
|
||
import { Data } from "./data.js"; | ||
|
||
describe("Data", () => { | ||
describe(".prototype.asUint()", () => { | ||
it("correctly converts to integers (big endian)", () => { | ||
const data = new Data([0x01, 0x00]); | ||
|
||
expect(`${data.asUint()}`).toBe("256"); | ||
}); | ||
}); | ||
|
||
describe(".fromUint()", () => { | ||
it("correctly creates Data instances from bigints", () => { | ||
const data1 = Data.fromUint(0n); | ||
expect(data1).toEqual(new Data([])); | ||
|
||
const data2 = Data.fromUint(255n); | ||
expect(data2).toEqual(new Data([0xff])); | ||
|
||
const data3 = Data.fromUint(256n); | ||
expect(data3).toEqual(new Data([0x01, 0x00])); | ||
|
||
const data4 = Data.fromUint(1234567890n); | ||
expect(data4).toEqual(new Data([0x49, 0x96, 0x02, 0xd2])); | ||
}); | ||
}); | ||
|
||
describe(".fromNumber()", () => { | ||
it("correctly creates Data instances from numbers", () => { | ||
const data1 = Data.fromNumber(0); | ||
expect(data1).toEqual(Data.zero()); | ||
|
||
const data2 = Data.fromNumber(255); | ||
expect(data2).toEqual(new Data([0xff])); | ||
|
||
const data3 = Data.fromNumber(256); | ||
expect(data3).toEqual(new Data([0x01, 0x00])); | ||
}); | ||
}); | ||
|
||
describe(".fromHex()", () => { | ||
it("correctly creates Data instances from hex strings", () => { | ||
const data1 = Data.fromHex("0x00"); | ||
expect(data1).toEqual(new Data([0x00])); | ||
|
||
const data2 = Data.fromHex("0xff"); | ||
expect(data2).toEqual(new Data([0xff])); | ||
|
||
const data3 = Data.fromHex("0x0100"); | ||
expect(data3).toEqual(new Data([0x01, 0x00])); | ||
|
||
const data4 = Data.fromHex("0x499602d2"); | ||
expect(data4).toEqual(new Data([0x49, 0x96, 0x02, 0xd2])); | ||
}); | ||
|
||
it("throws an error for invalid hex string format", () => { | ||
expect(() => Data.fromHex("ff")).toThrow("Invalid hex string format. Expected \"0x\" prefix."); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("Word", () => { | ||
describe(".prototype.asUint", () => { | ||
it("correctly converts to integers (big endian)", () => { | ||
const word = new Data.Word([ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, | ||
]); | ||
|
||
expect(`${word.asUint()}`).toBe("256"); | ||
}); | ||
}); | ||
|
||
describe(".fromUint()", () => { | ||
it("correctly creates Word instances from BigInt values", () => { | ||
const word1 = Data.Word.fromUint(0n); | ||
expect(word1).toEqual(Data.Word.zero()); | ||
|
||
const word2 = Data.Word.fromUint(255n); | ||
expect(word2).toEqual(new Data.Word([ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, | ||
])); | ||
|
||
const word3 = Data.Word.fromUint(256n); | ||
expect(word3).toEqual(new Data.Word([ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, | ||
])); | ||
|
||
const word4 = Data.Word.fromUint(1234567890n); | ||
expect(word4).toEqual(new Data.Word([ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x49, 0x96, 0x02, 0xd2, | ||
])); | ||
}); | ||
}); | ||
|
||
describe(".fromNumber()", () => { | ||
it("correctly creates Word instances from unsigned integers", () => { | ||
const word1 = Data.Word.fromNumber(0); | ||
expect(word1).toEqual(Data.Word.zero()); | ||
|
||
const word2 = Data.Word.fromNumber(255); | ||
expect(word2).toEqual(new Data.Word([ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, | ||
])); | ||
|
||
const word3 = Data.Word.fromNumber(256); | ||
expect(word3).toEqual(new Data.Word([ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, | ||
])); | ||
|
||
}); | ||
}); | ||
|
||
describe(".fromHex()", () => { | ||
it("correctly creates Word instances from hex strings", () => { | ||
const word1 = Data.Word.fromHex( | ||
"0x0000000000000000000000000000000000000000000000000000000000000000" | ||
); | ||
expect(word1).toEqual(Data.Word.zero()); | ||
|
||
const word2 = Data.Word.fromHex( | ||
"0x00000000000000000000000000000000000000000000000000000000000000ff" | ||
); | ||
expect(word2).toEqual(new Data.Word([ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, | ||
])); | ||
|
||
const word3 = Data.Word.fromHex("0x0000000000000000000000000000000000000000000000000000000000000100"); | ||
expect(word3).toEqual(new Data.Word([ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, | ||
])); | ||
}); | ||
}); | ||
}); | ||
|
Oops, something went wrong.