forked from ensdomains/evmgateway
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathlimits.test.ts
executable file
·133 lines (123 loc) · 4.62 KB
/
limits.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import { GatewayProgram, GatewayRequest } from '../../src/vm.js';
import { Foundry } from '@adraffy/blocksmith';
import { keccak256 } from 'ethers/crypto';
import { EthProver } from '../../src/eth/EthProver.js';
import { afterAll, test, expect } from 'bun:test';
import { describe } from '../bun-describe-fix.js';
import { toPaddedHex } from '../../src/utils.js';
describe('limits', async () => {
const foundry = await Foundry.launch({ infoLog: false });
afterAll(foundry.shutdown);
const MAX_BYTES = 257;
const contract = await foundry.deploy(`
contract X {
bytes pass = new bytes(${MAX_BYTES});
bytes fail = new bytes(${MAX_BYTES + 1});
}
`);
async function exec(prover: EthProver, req: GatewayRequest) {
const state = await prover.evalRequest(req);
const [proof, values] = await Promise.all([
prover.prove(state.needs),
state.resolveOutputs(),
]);
return { state, proof, values };
}
test('max stack', async () => {
const prover = await EthProver.latest(foundry.provider);
prover.maxStackSize = 10;
const req = new GatewayRequest();
for (let i = 0; i < prover.maxStackSize; i++) {
req.push(0);
}
await exec(prover, req);
req.push(0); // one more
expect(exec(prover, req)).rejects.toThrow('stack overflow');
});
test('max targets', async () => {
const prover = await EthProver.latest(foundry.provider);
prover.maxUniqueTargets = 10;
const req = new GatewayRequest();
for (let i = 0; i < prover.maxUniqueTargets; i++) {
req.setTarget(toPaddedHex(i, 20));
}
await exec(prover, req);
req.setTarget('0x51050ec063d393217B436747617aD1C2285Aeeee'); // one more
expect(exec(prover, req)).rejects.toThrow('too many targets');
});
test('max provable bytes', async () => {
const prover = await EthProver.latest(foundry.provider);
prover.maxUniqueProofs = 2 + Math.ceil(MAX_BYTES / 32); // account + length + slots
prover.maxProvableBytes = MAX_BYTES;
const passReq = new GatewayRequest()
.setTarget(contract.target)
.setSlot(0)
.readBytes();
const failReq = new GatewayRequest()
.setTarget(contract.target)
.setSlot(1)
.readBytes();
await exec(prover, passReq);
expect(exec(prover, failReq)).rejects.toThrow(/^too many bytes:/);
});
test('max supplied bytes', async () => {
const prover = await EthProver.latest(foundry.provider);
prover.maxUniqueProofs = 2; // account + hashed
prover.maxSuppliedBytes = MAX_BYTES;
const passReq = new GatewayRequest()
.setTarget(contract.target)
.push(keccak256(new Uint8Array(MAX_BYTES)))
.setSlot(0)
.readHashedBytes();
const failReq = new GatewayRequest()
.setTarget(contract.target)
.push(keccak256(new Uint8Array(MAX_BYTES + 1)))
.setSlot(1)
.readHashedBytes();
await exec(prover, passReq);
expect(exec(prover, failReq)).rejects.toThrow(/^too many bytes:/);
});
test('max alloc bytes: single', async () => {
const prover = await EthProver.latest(foundry.provider);
prover.maxAllocBytes = 64;
const req = new GatewayRequest();
req.push(1).push(2).concat();
await exec(prover, req);
prover.maxAllocBytes--;
expect(exec(prover, req)).rejects.toThrow('too much allocation');
});
test('max alloc bytes: total', async () => {
const prover = await EthProver.latest(foundry.provider);
const N = 100;
prover.maxAllocBytes = N * N;
const req = new GatewayRequest();
req.push(0);
for (let i = 0; i < N; i++) req.slice(0, N);
await exec(prover, req);
prover.maxAllocBytes--;
expect(exec(prover, req)).rejects.toThrow('too much allocation');
});
test('max proofs', async () => {
const prover = await EthProver.latest(foundry.provider);
prover.maxUniqueProofs = 10;
const req = new GatewayRequest();
req.setTarget(contract.target); // account is 1 proof, so we skip 1
for (let i = 1; i < prover.maxUniqueProofs; i++) {
req.setSlot(i).read().pop(); // pop prevents stack overflow
}
await exec(prover, req);
req.setSlot(0).read(); // one more
expect(exec(prover, req)).rejects.toThrow(/^too many proofs:/);
});
test('max eval depth', async () => {
const prover = await EthProver.latest(foundry.provider);
const N = (prover.maxEvalDepth = 10);
function nest(n: number) {
let p = new GatewayProgram().push(1).setOutput(0);
while (n-- > 1) p = new GatewayProgram().pushProgram(p).eval();
return new GatewayRequest(1).pushProgram(p).eval();
}
await exec(prover, nest(N));
expect(exec(prover, nest(N + 1))).rejects.toThrow('max eval depth');
});
});