@typeberry/lib 0.5.2-ff62cc9 → 0.5.3-355fdf7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/core/crypto/bandersnatch.d.ts +2 -1
- package/packages/core/crypto/bandersnatch.d.ts.map +1 -1
- package/packages/core/crypto/bandersnatch.js +9 -2
- package/packages/core/crypto/key-derivation.test.js +8 -7
- package/packages/core/networking/package.json +1 -1
- package/packages/core/pvm-host-calls/bin.js +6 -6
- package/packages/core/pvm-host-calls/ecalli-io-tracker.d.ts +32 -0
- package/packages/core/pvm-host-calls/ecalli-io-tracker.d.ts.map +1 -0
- package/packages/core/pvm-host-calls/ecalli-io-tracker.js +14 -0
- package/packages/core/pvm-host-calls/ecalli-trace-logger.d.ts +139 -0
- package/packages/core/pvm-host-calls/ecalli-trace-logger.d.ts.map +1 -0
- package/packages/core/pvm-host-calls/ecalli-trace-logger.js +209 -0
- package/packages/core/pvm-host-calls/ecalli-trace-logger.test.d.ts +2 -0
- package/packages/core/pvm-host-calls/ecalli-trace-logger.test.d.ts.map +1 -0
- package/packages/core/pvm-host-calls/ecalli-trace-logger.test.js +231 -0
- package/packages/core/pvm-host-calls/host-call-memory.d.ts +2 -0
- package/packages/core/pvm-host-calls/host-call-memory.d.ts.map +1 -1
- package/packages/core/pvm-host-calls/host-call-memory.js +12 -2
- package/packages/core/pvm-host-calls/host-call-registers.d.ts +6 -0
- package/packages/core/pvm-host-calls/host-call-registers.d.ts.map +1 -1
- package/packages/core/pvm-host-calls/host-call-registers.js +24 -0
- package/packages/core/pvm-host-calls/host-calls-executor.d.ts +31 -0
- package/packages/core/pvm-host-calls/host-calls-executor.d.ts.map +1 -0
- package/packages/core/pvm-host-calls/host-calls-executor.js +137 -0
- package/packages/core/pvm-host-calls/host-calls.d.ts +20 -26
- package/packages/core/pvm-host-calls/host-calls.d.ts.map +1 -1
- package/packages/core/pvm-host-calls/host-calls.js +40 -112
- package/packages/core/pvm-host-calls/index.d.ts +7 -6
- package/packages/core/pvm-host-calls/index.d.ts.map +1 -1
- package/packages/core/pvm-host-calls/index.js +7 -6
- package/packages/core/pvm-host-calls/{interpreter-instance-manager.d.ts → pvm-instance-manager.d.ts} +3 -3
- package/packages/core/pvm-host-calls/pvm-instance-manager.d.ts.map +1 -0
- package/packages/core/pvm-host-calls/{interpreter-instance-manager.js → pvm-instance-manager.js} +2 -2
- package/packages/core/telemetry/package.json +1 -1
- package/packages/jam/node/main-importer.d.ts.map +1 -1
- package/packages/jam/node/main-importer.js +3 -1
- package/packages/jam/node/package.json +1 -1
- package/packages/jam/safrole/bandersnatch-vrf.test.js +3 -3
- package/packages/jam/safrole/bandersnatch-wasm.js +6 -6
- package/packages/jam/safrole/safrole-seal.test.js +4 -10
- package/packages/jam/transition/accumulate/pvm-executor.d.ts.map +1 -1
- package/packages/jam/transition/accumulate/pvm-executor.js +2 -2
- package/packages/workers/block-authorship/package.json +1 -1
- package/packages/workers/importer/package.json +1 -1
- package/packages/core/pvm-host-calls/host-calls-manager.d.ts +0 -23
- package/packages/core/pvm-host-calls/host-calls-manager.d.ts.map +0 -1
- package/packages/core/pvm-host-calls/host-calls-manager.js +0 -44
- package/packages/core/pvm-host-calls/interpreter-instance-manager.d.ts.map +0 -1
|
@@ -1,119 +1,47 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
status;
|
|
9
|
-
memorySlice;
|
|
10
|
-
constructor(consumedGas, status, memorySlice) {
|
|
11
|
-
this.consumedGas = consumedGas;
|
|
12
|
-
this.status = status;
|
|
13
|
-
this.memorySlice = memorySlice;
|
|
14
|
-
check `
|
|
15
|
-
${(status === null && memorySlice !== null) || (status !== null && memorySlice === null)}
|
|
16
|
-
'status' and 'memorySlice' must not both be null or both be non-null — exactly one must be provided
|
|
17
|
-
`;
|
|
18
|
-
}
|
|
19
|
-
static fromStatus(consumedGas, status) {
|
|
20
|
-
return new ReturnValue(consumedGas, status, null);
|
|
21
|
-
}
|
|
22
|
-
static fromMemorySlice(consumedGas, memorySlice) {
|
|
23
|
-
return new ReturnValue(consumedGas, null, memorySlice);
|
|
24
|
-
}
|
|
25
|
-
hasMemorySlice() {
|
|
26
|
-
return this.memorySlice instanceof Uint8Array && this.status === null;
|
|
27
|
-
}
|
|
28
|
-
hasStatus() {
|
|
29
|
-
return !this.hasMemorySlice();
|
|
30
|
-
}
|
|
31
|
-
}
|
|
1
|
+
import { Level, Logger } from "#@typeberry/logger";
|
|
2
|
+
import { tryAsU32 } from "#@typeberry/numbers";
|
|
3
|
+
import { tryAsSmallGas } from "#@typeberry/pvm-interface";
|
|
4
|
+
import { check } from "#@typeberry/utils";
|
|
5
|
+
import { tryAsHostCallIndex, } from "./host-call-handler.js";
|
|
6
|
+
const logger = Logger.new(import.meta.filename, "host-calls-pvm");
|
|
7
|
+
/** Container for all available host calls. */
|
|
32
8
|
export class HostCalls {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
constructor(
|
|
36
|
-
this.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const gasConsumed = pvmInstance.gas.used();
|
|
41
|
-
if (status === Status.OOG) {
|
|
42
|
-
return ReturnValue.fromStatus(gasConsumed, status);
|
|
43
|
-
}
|
|
44
|
-
if (status === Status.HALT) {
|
|
45
|
-
const regs = new HostCallRegisters(pvmInstance.registers.getAllEncoded());
|
|
46
|
-
const memory = new HostCallMemory(pvmInstance.memory);
|
|
47
|
-
const address = regs.get(7);
|
|
48
|
-
// NOTE we are taking the the lower U32 part of the register, hence it's safe.
|
|
49
|
-
const length = Number(regs.get(8) & 0xffffffffn);
|
|
50
|
-
const result = safeAllocUint8Array(length);
|
|
51
|
-
const loadResult = memory.loadInto(result, address);
|
|
52
|
-
if (loadResult.isError) {
|
|
53
|
-
return ReturnValue.fromMemorySlice(gasConsumed, new Uint8Array());
|
|
54
|
-
}
|
|
55
|
-
return ReturnValue.fromMemorySlice(gasConsumed, result);
|
|
9
|
+
hostCalls = new Map();
|
|
10
|
+
missing;
|
|
11
|
+
constructor({ missing, handlers = [], }) {
|
|
12
|
+
this.missing = missing;
|
|
13
|
+
for (const handler of handlers) {
|
|
14
|
+
check `${this.hostCalls.get(handler.index) === undefined} Overwriting host call handler at index ${handler.index}`;
|
|
15
|
+
this.hostCalls.set(handler.index, handler);
|
|
56
16
|
}
|
|
57
|
-
return ReturnValue.fromStatus(gasConsumed, Status.PANIC);
|
|
58
17
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
let status = pvmInstance.getStatus();
|
|
63
|
-
if (status !== Status.HOST) {
|
|
64
|
-
return this.getReturnValue(status, pvmInstance);
|
|
65
|
-
}
|
|
66
|
-
check `
|
|
67
|
-
${pvmInstance.getExitParam() !== null}
|
|
68
|
-
"We know that the exit param is not null, because the status is 'Status.HOST'
|
|
69
|
-
`;
|
|
70
|
-
const hostCallIndex = pvmInstance.getExitParam() ?? -1;
|
|
71
|
-
const gas = pvmInstance.gas;
|
|
72
|
-
const regs = new HostCallRegisters(pvmInstance.registers.getAllEncoded());
|
|
73
|
-
const memory = new HostCallMemory(pvmInstance.memory);
|
|
74
|
-
const index = tryAsHostCallIndex(hostCallIndex);
|
|
75
|
-
const hostCall = this.hostCalls.get(index);
|
|
76
|
-
const gasBefore = gas.get();
|
|
77
|
-
// NOTE: `basicGasCost(regs)` function is for compatibility reasons: pre GP 0.7.2
|
|
78
|
-
const basicGasCost = typeof hostCall.basicGasCost === "number" ? hostCall.basicGasCost : hostCall.basicGasCost(regs);
|
|
79
|
-
const underflow = gas.sub(basicGasCost);
|
|
80
|
-
const pcLog = `[PC: ${pvmInstance.getPC()}]`;
|
|
81
|
-
if (underflow) {
|
|
82
|
-
this.hostCalls.traceHostCall(`${pcLog} OOG`, index, hostCall, regs, gas.get());
|
|
83
|
-
return ReturnValue.fromStatus(gas.used(), Status.OOG);
|
|
84
|
-
}
|
|
85
|
-
this.hostCalls.traceHostCall(`${pcLog} Invoking`, index, hostCall, regs, gasBefore);
|
|
86
|
-
const result = await hostCall.execute(gas, regs, memory);
|
|
87
|
-
this.hostCalls.traceHostCall(result === undefined ? `${pcLog} Result` : `${pcLog} Status(${PvmExecution[result]})`, index, hostCall, regs, gas.get());
|
|
88
|
-
pvmInstance.registers.setAllEncoded(regs.getEncoded());
|
|
89
|
-
if (result === PvmExecution.Halt) {
|
|
90
|
-
status = Status.HALT;
|
|
91
|
-
return this.getReturnValue(status, pvmInstance);
|
|
92
|
-
}
|
|
93
|
-
if (result === PvmExecution.Panic) {
|
|
94
|
-
status = Status.PANIC;
|
|
95
|
-
return this.getReturnValue(status, pvmInstance);
|
|
96
|
-
}
|
|
97
|
-
if (result === PvmExecution.OOG) {
|
|
98
|
-
status = Status.OOG;
|
|
99
|
-
return this.getReturnValue(status, pvmInstance);
|
|
100
|
-
}
|
|
101
|
-
if (result === undefined) {
|
|
102
|
-
pvmInstance.runProgram();
|
|
103
|
-
status = pvmInstance.getStatus();
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
assertNever(result);
|
|
107
|
-
}
|
|
18
|
+
/** Get a host call by index. */
|
|
19
|
+
get(hostCallIndex) {
|
|
20
|
+
return this.hostCalls.get(hostCallIndex) ?? this.missing;
|
|
108
21
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
try {
|
|
113
|
-
return await this.execute(pvmInstance);
|
|
114
|
-
}
|
|
115
|
-
finally {
|
|
116
|
-
this.pvmInstanceManager.releaseInstance(pvmInstance);
|
|
22
|
+
traceHostCall(context, hostCallIndex, hostCallHandler, registers, gas) {
|
|
23
|
+
if (logger.getLevel() > Level.INSANE) {
|
|
24
|
+
return;
|
|
117
25
|
}
|
|
26
|
+
const { currentServiceId } = hostCallHandler;
|
|
27
|
+
const requested = hostCallIndex !== hostCallHandler.index ? ` (${hostCallIndex})` : "";
|
|
28
|
+
const name = `${hostCallHandler.constructor.name}:${hostCallHandler.index}`;
|
|
29
|
+
const registerValues = hostCallHandler.tracedRegisters
|
|
30
|
+
.map((idx) => [idx.toString().padStart(2, "0"), registers.get(idx)])
|
|
31
|
+
.filter((v) => v[1] !== 0n)
|
|
32
|
+
.map(([idx, value]) => {
|
|
33
|
+
return `r${idx}=${value} (0x${value.toString(16)})`;
|
|
34
|
+
})
|
|
35
|
+
.join(", ");
|
|
36
|
+
logger.insane `[${currentServiceId}] ${context} ${name}${requested}. Gas: ${gas}. Regs: ${registerValues}.`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export class NoopMissing {
|
|
40
|
+
index = tryAsHostCallIndex(2 ** 32 - 1);
|
|
41
|
+
basicGasCost = tryAsSmallGas(0);
|
|
42
|
+
currentServiceId = tryAsU32(0);
|
|
43
|
+
tracedRegisters = [];
|
|
44
|
+
async execute() {
|
|
45
|
+
return;
|
|
118
46
|
}
|
|
119
47
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
1
|
+
export * from "./ecalli-trace-logger.js";
|
|
2
|
+
export * from "./host-call-handler.js";
|
|
3
|
+
export * from "./host-call-memory.js";
|
|
4
|
+
export * from "./host-call-registers.js";
|
|
5
|
+
export * from "./host-calls.js";
|
|
6
|
+
export * from "./host-calls-executor.js";
|
|
7
|
+
export * from "./pvm-instance-manager.js";
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/core/pvm-host-calls/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/core/pvm-host-calls/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
1
|
+
export * from "./ecalli-trace-logger.js";
|
|
2
|
+
export * from "./host-call-handler.js";
|
|
3
|
+
export * from "./host-call-memory.js";
|
|
4
|
+
export * from "./host-call-registers.js";
|
|
5
|
+
export * from "./host-calls.js";
|
|
6
|
+
export * from "./host-calls-executor.js";
|
|
7
|
+
export * from "./pvm-instance-manager.js";
|
package/packages/core/pvm-host-calls/{interpreter-instance-manager.d.ts → pvm-instance-manager.d.ts}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { PvmBackend } from "#@typeberry/config";
|
|
2
2
|
import type { IPvmInterpreter } from "#@typeberry/pvm-interface";
|
|
3
|
-
export declare class
|
|
3
|
+
export declare class PvmInstanceManager {
|
|
4
4
|
private readonly instances;
|
|
5
5
|
private waitingQueue;
|
|
6
6
|
private constructor();
|
|
7
|
-
static new(interpreter: PvmBackend): Promise<
|
|
7
|
+
static new(interpreter: PvmBackend): Promise<PvmInstanceManager>;
|
|
8
8
|
getInstance(): Promise<IPvmInterpreter>;
|
|
9
9
|
releaseInstance(pvm: IPvmInterpreter): void;
|
|
10
10
|
}
|
|
11
|
-
//# sourceMappingURL=
|
|
11
|
+
//# sourceMappingURL=pvm-instance-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pvm-instance-manager.d.ts","sourceRoot":"","sources":["../../../../../packages/core/pvm-host-calls/pvm-instance-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAQhE,qBAAa,kBAAkB;IAGT,OAAO,CAAC,QAAQ,CAAC,SAAS;IAF9C,OAAO,CAAC,YAAY,CAAmB;IAEvC,OAAO;WAEM,GAAG,CAAC,WAAW,EAAE,UAAU,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAmBhE,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC;IAU7C,eAAe,CAAC,GAAG,EAAE,eAAe;CAOrC"}
|
package/packages/core/pvm-host-calls/{interpreter-instance-manager.js → pvm-instance-manager.js}
RENAMED
|
@@ -3,7 +3,7 @@ import { Interpreter } from "#@typeberry/pvm-interpreter";
|
|
|
3
3
|
import { AnanasInterpreter } from "#@typeberry/pvm-interpreter-ananas";
|
|
4
4
|
import { assertNever } from "#@typeberry/utils";
|
|
5
5
|
// TODO [MaSo] Delete this & also make host calls independent from intepreters.
|
|
6
|
-
export class
|
|
6
|
+
export class PvmInstanceManager {
|
|
7
7
|
instances;
|
|
8
8
|
waitingQueue = [];
|
|
9
9
|
constructor(instances) {
|
|
@@ -23,7 +23,7 @@ export class InterpreterInstanceManager {
|
|
|
23
23
|
default:
|
|
24
24
|
assertNever(interpreter);
|
|
25
25
|
}
|
|
26
|
-
return new
|
|
26
|
+
return new PvmInstanceManager(instances);
|
|
27
27
|
}
|
|
28
28
|
async getInstance() {
|
|
29
29
|
const instance = this.instances.pop();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main-importer.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-importer.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"main-importer.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-importer.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,CA+ElB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Bytes } from "#@typeberry/bytes";
|
|
2
2
|
import { PvmBackend } from "#@typeberry/config";
|
|
3
|
-
import { initWasm } from "#@typeberry/crypto";
|
|
3
|
+
import { bandersnatch, initWasm } from "#@typeberry/crypto";
|
|
4
4
|
import { Blake2b, HASH_SIZE } from "#@typeberry/hash";
|
|
5
5
|
import { createImporter } from "#@typeberry/importer";
|
|
6
6
|
import { CURRENT_SUITE, CURRENT_VERSION, Result, resultToString } from "#@typeberry/utils";
|
|
@@ -10,9 +10,11 @@ import packageJson from "./package.json" with { type: "json" };
|
|
|
10
10
|
const zeroHash = Bytes.zero(HASH_SIZE).asOpaque();
|
|
11
11
|
export async function mainImporter(config, withRelPath, options = {}) {
|
|
12
12
|
await initWasm();
|
|
13
|
+
const bandesnatchNative = bandersnatch.checkNativeBindings();
|
|
13
14
|
logger.info `🫐 Typeberry ${packageJson.version}. GP: ${CURRENT_VERSION} (${CURRENT_SUITE})`;
|
|
14
15
|
logger.info `🎸 Starting importer: ${config.nodeName}.`;
|
|
15
16
|
logger.info `🖥️ PVM Backend: ${PvmBackend[config.pvmBackend]}.`;
|
|
17
|
+
logger.info `🐇 Bandersnatch ${bandesnatchNative.isOk ? "native 🚀" : `using wasm: ${bandesnatchNative.error}`}`;
|
|
16
18
|
const chainSpec = getChainSpec(config.node.flavor);
|
|
17
19
|
const blake2b = await Blake2b.createHasher();
|
|
18
20
|
const nodeName = config.nodeName;
|
|
@@ -27,7 +27,7 @@ describe("Bandersnatch verification", () => {
|
|
|
27
27
|
const result = await bandersnatchVrf.getRingCommitment(await bandersnatchWasm, bandersnatchKeys);
|
|
28
28
|
const expectedCommitment = Bytes.parseBytes("0x8387a131593447e4e1c3d4e220c322e42d33207fa77cd0fedb39fc3491479ca47a2d82295252e278fa3eec78185982ed82ae0c8fd691335e703d663fb5be02b3def15380789320636b2479beab5a03ccb3f0909ffea59d859fcdc7e187e45a8c92e630ae2b14e758ab0960e372172203f4c9a41777dadd529971d7ab9d23ab29fe0e9c85ec450505dde7f5ac038274cf", BANDERSNATCH_RING_ROOT_BYTES);
|
|
29
29
|
assert.strictEqual(result.isOk, true);
|
|
30
|
-
assert.
|
|
30
|
+
assert.strictEqual(result.ok.toString(), expectedCommitment.toString());
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
33
|
describe("verifyTickets", () => {
|
|
@@ -72,7 +72,7 @@ describe("Bandersnatch verification", () => {
|
|
|
72
72
|
].map((x) => Bytes.parseBytes(x, HASH_SIZE));
|
|
73
73
|
const result = await bandersnatchVrf.verifyTickets(await bandersnatchWasm, bandersnatchKeys.length, commitment, tickets, entropy);
|
|
74
74
|
assert.strictEqual(result.every((x) => x.isValid), true);
|
|
75
|
-
assert.deepStrictEqual(result.map((x) => x.entropyHash), expectedIds);
|
|
75
|
+
assert.deepStrictEqual(result.map((x) => x.entropyHash.toString()), expectedIds.map((x) => x.toString()));
|
|
76
76
|
});
|
|
77
77
|
it("should detect that one signature is incorrect", async () => {
|
|
78
78
|
const tickets = [
|
|
@@ -97,7 +97,7 @@ describe("Bandersnatch verification", () => {
|
|
|
97
97
|
].map((x) => Bytes.parseBytes(x, HASH_SIZE));
|
|
98
98
|
const result = await bandersnatchVrf.verifyTickets(await bandersnatchWasm, bandersnatchKeys.length, commitment, tickets, entropy);
|
|
99
99
|
assert.deepStrictEqual(result.map((x) => x.isValid), [false, true, true]);
|
|
100
|
-
assert.deepStrictEqual(result.map((x) => x.entropyHash), expectedIds);
|
|
100
|
+
assert.deepStrictEqual(result.map((x) => x.entropyHash.toString()), expectedIds.map((x) => x.toString()));
|
|
101
101
|
});
|
|
102
102
|
});
|
|
103
103
|
describe("verifySeal", () => {
|
|
@@ -6,21 +6,21 @@ export class BandernsatchWasm {
|
|
|
6
6
|
return new BandernsatchWasm();
|
|
7
7
|
}
|
|
8
8
|
async verifySeal(authorKey, signature, payload, auxData) {
|
|
9
|
-
return bandersnatchWasm.
|
|
9
|
+
return bandersnatchWasm.verifySeal(authorKey, signature, payload, auxData);
|
|
10
10
|
}
|
|
11
11
|
async verifyHeaderSeals(authorKey, headerSeal, headerSealPayload, unsealedHeader, entropySeal, entropyPayloadPrefix) {
|
|
12
|
-
return bandersnatchWasm.
|
|
12
|
+
return bandersnatchWasm.verifyHeaderSeals(authorKey, headerSeal, headerSealPayload, unsealedHeader, entropySeal, entropyPayloadPrefix);
|
|
13
13
|
}
|
|
14
14
|
async getRingCommitment(keys) {
|
|
15
|
-
return bandersnatchWasm.
|
|
15
|
+
return bandersnatchWasm.ringCommitment(keys);
|
|
16
16
|
}
|
|
17
17
|
async batchVerifyTicket(ringSize, commitment, ticketsData, contextLength) {
|
|
18
|
-
return bandersnatchWasm.
|
|
18
|
+
return bandersnatchWasm.batchVerifyTickets(ringSize, commitment, ticketsData, contextLength);
|
|
19
19
|
}
|
|
20
20
|
async generateSeal(authorKey, input, auxData) {
|
|
21
|
-
return bandersnatchWasm.
|
|
21
|
+
return bandersnatchWasm.generateSeal(authorKey, input, auxData);
|
|
22
22
|
}
|
|
23
23
|
async getVrfOutputHash(authorKey, input) {
|
|
24
|
-
return bandersnatchWasm.
|
|
24
|
+
return bandersnatchWasm.vrfOutputHash(authorKey, input);
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -35,11 +35,8 @@ describe("Safrole Seal verification", () => {
|
|
|
35
35
|
sealingKeySeries: SEALING_KEYS,
|
|
36
36
|
currentEntropy: Bytes.parseBytes("0x405c80c1f6a2d5a0f8dbc56996f04230221100d9500244648f02a795d7850eac", HASH_SIZE).asOpaque(),
|
|
37
37
|
});
|
|
38
|
-
assert.
|
|
39
|
-
|
|
40
|
-
isOk: true,
|
|
41
|
-
ok: Bytes.parseBytes("0xc13af3d0cbdb7174590f34518e3beb05708935ceaee242e7ba11a94ca87bd007", HASH_SIZE).asOpaque(),
|
|
42
|
-
});
|
|
38
|
+
assert.strictEqual(result.isOk, true);
|
|
39
|
+
assert.strictEqual(result.ok.toString(), "0xc13af3d0cbdb7174590f34518e3beb05708935ceaee242e7ba11a94ca87bd007");
|
|
43
40
|
});
|
|
44
41
|
it("should verify a valid ticket seal and entropySource", async () => {
|
|
45
42
|
// based on test-vectors/w3f-davxy_070/traces/safrole/00000002.json
|
|
@@ -63,11 +60,8 @@ describe("Safrole Seal verification", () => {
|
|
|
63
60
|
sealingKeySeries: SEALING_KEYS,
|
|
64
61
|
currentEntropy: Bytes.parseBytes("0x405c80c1f6a2d5a0f8dbc56996f04230221100d9500244648f02a795d7850eac", HASH_SIZE).asOpaque(),
|
|
65
62
|
});
|
|
66
|
-
assert.
|
|
67
|
-
|
|
68
|
-
isOk: true,
|
|
69
|
-
ok: Bytes.parseBytes("0xc13af3d0cbdb7174590f34518e3beb05708935ceaee242e7ba11a94ca87bd007", HASH_SIZE).asOpaque(),
|
|
70
|
-
});
|
|
63
|
+
assert.strictEqual(result.isOk, true);
|
|
64
|
+
assert.strictEqual(result.ok.toString(), "0xc13af3d0cbdb7174590f34518e3beb05708935ceaee242e7ba11a94ca87bd007");
|
|
71
65
|
});
|
|
72
66
|
});
|
|
73
67
|
const TEST_VALIDATOR_KEYS = tryAsPerValidator([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pvm-executor.d.ts","sourceRoot":"","sources":["../../../../../../packages/jam/transition/accumulate/pvm-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAc,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0DAA0D,CAAC;AAM7F,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAkBpD,KAAK,+BAA+B,GAAG;IACrC,YAAY,EAAE,YAAY,CAAC;IAC3B,kBAAkB,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAChD,oBAAoB,EAAE,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;CACpH,CAAC;AAEF,KAAK,+BAA+B,GAAG;IACrC,YAAY,EAAE,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAC3G,kBAAkB,EAAE,OAAO,CAAC,mBAAmB,CAAC;CACjD,CAAC;AASF;;GAEG;AACH,qBAAa,WAAW;IAKpB,OAAO,CAAC,WAAW;IAEnB,OAAO,CAAC,UAAU;IANpB,OAAO,CAAC,QAAQ,CAAC,GAAG,
|
|
1
|
+
{"version":3,"file":"pvm-executor.d.ts","sourceRoot":"","sources":["../../../../../../packages/jam/transition/accumulate/pvm-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAc,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0DAA0D,CAAC;AAM7F,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAkBpD,KAAK,+BAA+B,GAAG;IACrC,YAAY,EAAE,YAAY,CAAC;IAC3B,kBAAkB,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAChD,oBAAoB,EAAE,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;CACpH,CAAC;AAEF,KAAK,+BAA+B,GAAG;IACrC,YAAY,EAAE,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAC3G,kBAAkB,EAAE,OAAO,CAAC,mBAAmB,CAAC;CACjD,CAAC;AASF;;GAEG;AACH,qBAAa,WAAW;IAKpB,OAAO,CAAC,WAAW;IAEnB,OAAO,CAAC,UAAU;IANpB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,SAAS,CAAY;IAE7B,OAAO;mBAac,cAAc;IAInC,8CAA8C;IAC9C,OAAO,CAAC,MAAM,CAAC,0BAA0B;IAsBzC,6CAA6C;IAC7C,OAAO,CAAC,MAAM,CAAC,0BAA0B;IAazC;;;;;;OAMG;IACG,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG;;;;;;;;;;;;;IAInC,yEAAyE;WAC5D,wBAAwB,CACnC,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,SAAS,EACtB,aAAa,EAAE,+BAA+B,EAC9C,SAAS,EAAE,SAAS,EACpB,GAAG,EAAE,UAAU;IAOjB,0EAA0E;WAC7D,wBAAwB,CACnC,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,SAAS,EACtB,aAAa,EAAE,+BAA+B,EAC9C,GAAG,EAAE,UAAU;CAMlB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { accumulate, general } from "#@typeberry/jam-host-calls";
|
|
2
2
|
import { tryAsProgramCounter, } from "#@typeberry/jam-host-calls/externalities/refine-externalities.js";
|
|
3
|
-
import { HostCalls,
|
|
3
|
+
import { HostCalls, HostCallsExecutor, PvmInstanceManager } from "#@typeberry/pvm-host-calls";
|
|
4
4
|
const ACCUMULATE_HOST_CALL_CLASSES = [
|
|
5
5
|
accumulate.Bless,
|
|
6
6
|
accumulate.Assign,
|
|
@@ -38,7 +38,7 @@ export class PvmExecutor {
|
|
|
38
38
|
missing: new general.Missing(),
|
|
39
39
|
handlers: hostCallHandlers,
|
|
40
40
|
});
|
|
41
|
-
this.pvm = new
|
|
41
|
+
this.pvm = new HostCallsExecutor(pvmInstanceManager, this.hostCalls);
|
|
42
42
|
}
|
|
43
43
|
static async prepareBackend(pvm) {
|
|
44
44
|
return PvmInstanceManager.new(pvm);
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { type Gas } from "#@typeberry/pvm-interface";
|
|
2
|
-
import { type HostCallHandler, type HostCallIndex, type PvmExecution } from "./host-call-handler.js";
|
|
3
|
-
import type { HostCallRegisters } from "./host-call-registers.js";
|
|
4
|
-
/** Container for all available host calls. */
|
|
5
|
-
export declare class HostCallsManager {
|
|
6
|
-
private readonly hostCalls;
|
|
7
|
-
private readonly missing;
|
|
8
|
-
constructor({ missing, handlers, }: {
|
|
9
|
-
missing: HostCallHandler;
|
|
10
|
-
handlers?: HostCallHandler[];
|
|
11
|
-
});
|
|
12
|
-
/** Get a host call by index. */
|
|
13
|
-
get(hostCallIndex: HostCallIndex): HostCallHandler;
|
|
14
|
-
traceHostCall(context: string, hostCallIndex: HostCallIndex, hostCallHandler: HostCallHandler, registers: HostCallRegisters, gas: Gas): void;
|
|
15
|
-
}
|
|
16
|
-
export declare class NoopMissing implements HostCallHandler {
|
|
17
|
-
index: number & import("@typeberry/numbers").WithBytesRepresentation<4> & import("@typeberry/utils").WithOpaque<"HostCallIndex[U32]">;
|
|
18
|
-
basicGasCost: number & import("@typeberry/numbers").WithBytesRepresentation<4> & import("@typeberry/utils").WithOpaque<"SmallGas[U32]">;
|
|
19
|
-
currentServiceId: import("@typeberry/numbers").U32;
|
|
20
|
-
tracedRegisters: never[];
|
|
21
|
-
execute(): Promise<undefined | PvmExecution>;
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=host-calls-manager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"host-calls-manager.d.ts","sourceRoot":"","sources":["../../../../../packages/core/pvm-host-calls/host-calls-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,GAAG,EAAiB,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,YAAY,EAElB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAIlE,8CAA8C;AAC9C,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6C;IACvE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAEb,EACV,OAAO,EACP,QAAa,GACd,EAAE;QACD,OAAO,EAAE,eAAe,CAAC;QACzB,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;KAC9B;IASD,gCAAgC;IAChC,GAAG,CAAC,aAAa,EAAE,aAAa,GAAG,eAAe;IAIlD,aAAa,CACX,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,aAAa,EAC5B,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,iBAAiB,EAC5B,GAAG,EAAE,GAAG;CAcX;AAED,qBAAa,WAAY,YAAW,eAAe;IACjD,KAAK,iIAAmC;IACxC,YAAY,4HAAoB;IAChC,gBAAgB,mCAAe;IAC/B,eAAe,UAAM;IAEf,OAAO,IAAI,OAAO,CAAC,SAAS,GAAG,YAAY,CAAC;CAGnD"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Logger } from "#@typeberry/logger";
|
|
2
|
-
import { tryAsU32 } from "#@typeberry/numbers";
|
|
3
|
-
import { tryAsSmallGas } from "#@typeberry/pvm-interface";
|
|
4
|
-
import { check } from "#@typeberry/utils";
|
|
5
|
-
import { tryAsHostCallIndex, } from "./host-call-handler.js";
|
|
6
|
-
const logger = Logger.new(import.meta.filename, "host-calls-pvm");
|
|
7
|
-
/** Container for all available host calls. */
|
|
8
|
-
export class HostCallsManager {
|
|
9
|
-
hostCalls = new Map();
|
|
10
|
-
missing;
|
|
11
|
-
constructor({ missing, handlers = [], }) {
|
|
12
|
-
this.missing = missing;
|
|
13
|
-
for (const handler of handlers) {
|
|
14
|
-
check `${this.hostCalls.get(handler.index) === undefined} Overwriting host call handler at index ${handler.index}`;
|
|
15
|
-
this.hostCalls.set(handler.index, handler);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
/** Get a host call by index. */
|
|
19
|
-
get(hostCallIndex) {
|
|
20
|
-
return this.hostCalls.get(hostCallIndex) ?? this.missing;
|
|
21
|
-
}
|
|
22
|
-
traceHostCall(context, hostCallIndex, hostCallHandler, registers, gas) {
|
|
23
|
-
const { currentServiceId } = hostCallHandler;
|
|
24
|
-
const requested = hostCallIndex !== hostCallHandler.index ? ` (${hostCallIndex})` : "";
|
|
25
|
-
const name = `${hostCallHandler.constructor.name}:${hostCallHandler.index}`;
|
|
26
|
-
const registerValues = hostCallHandler.tracedRegisters
|
|
27
|
-
.map((idx) => [idx.toString().padStart(2, "0"), registers.get(idx)])
|
|
28
|
-
.filter((v) => v[1] !== 0n)
|
|
29
|
-
.map(([idx, value]) => {
|
|
30
|
-
return `r${idx}=${value} (0x${value.toString(16)})`;
|
|
31
|
-
})
|
|
32
|
-
.join(", ");
|
|
33
|
-
logger.insane `[${currentServiceId}] ${context} ${name}${requested}. Gas: ${gas}. Regs: ${registerValues}.`;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
export class NoopMissing {
|
|
37
|
-
index = tryAsHostCallIndex(2 ** 32 - 1);
|
|
38
|
-
basicGasCost = tryAsSmallGas(0);
|
|
39
|
-
currentServiceId = tryAsU32(0);
|
|
40
|
-
tracedRegisters = [];
|
|
41
|
-
async execute() {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"interpreter-instance-manager.d.ts","sourceRoot":"","sources":["../../../../../packages/core/pvm-host-calls/interpreter-instance-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAQhE,qBAAa,0BAA0B;IAGjB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAF9C,OAAO,CAAC,YAAY,CAAmB;IAEvC,OAAO;WAEM,GAAG,CAAC,WAAW,EAAE,UAAU,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAmBxE,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC;IAU7C,eAAe,CAAC,GAAG,EAAE,eAAe;CAOrC"}
|