Skip to content

Instantly share code, notes, and snippets.

@holgerd77
Created September 20, 2024 08:27
Show Gist options
  • Save holgerd77/2c032488196b4afee5d976dc85ee70eb to your computer and use it in GitHub Desktop.
Save holgerd77/2c032488196b4afee5d976dc85ee70eb to your computer and use it in GitHub Desktop.
Unminifed JS bundle of the EthereumJS EVM with all dependencies
const FORMAT = 239;
const MAGIC = 0;
const VERSION = 1;
const MAX_HEADER_SIZE = 49152;
const KIND_TYPE = 1;
const KIND_CODE = 2;
const KIND_CONTAINER = 3;
const KIND_DATA = 4;
const TERMINATOR = 0;
const TYPE_MIN = 4;
const TYPE_MAX = 4096;
const TYPE_DIVISOR = 4;
const CODE_MIN = 1;
const CODE_SIZE_MIN = 1;
const CONTAINER_MIN = 1;
const CONTAINER_MAX = 256;
const CONTAINER_SIZE_MIN = 1;
const INPUTS_MAX = 127;
const OUTPUTS_MAX = 128;
const MAX_STACK_HEIGHT = 1023;
var EOFError = /* @__PURE__ */ ((EOFError2) => {
EOFError2["OutOfBounds"] = "Trying to read out of bounds";
EOFError2["VerifyUint"] = "Uint does not match expected value ";
EOFError2["VerifyBytes"] = "Bytes do not match expected value";
EOFError2["FORMAT"] = "err: invalid format";
EOFError2["MAGIC"] = "err: invalid magic";
EOFError2["VERSION"] = `err: invalid eof version`;
EOFError2["KIND_TYPE"] = `err: expected kind types`;
EOFError2["KIND_CODE"] = `err: expected kind code`;
EOFError2["KIND_DATA"] = `err: expected kind data`;
EOFError2["TERMINATOR"] = `err: expected terminator`;
EOFError2["TypeSize"] = `missing type size`;
EOFError2["InvalidTypeSize"] = `err: type section size invalid`;
EOFError2["CodeSize"] = `missing code size`;
EOFError2["CodeSectionSize"] = `code section should be at least one byte`;
EOFError2["InvalidCodeSize"] = `code size does not match type size`;
EOFError2["DataSize"] = `missing data size`;
EOFError2["ContainerSize"] = "missing container size";
EOFError2["ContainerSectionSize"] = "container section should at least contain one section and at most 255 sections";
EOFError2["TypeSections"] = `err: mismatch of code sections count and type signatures`;
EOFError2["Inputs"] = "expected inputs";
EOFError2["Outputs"] = "expected outputs";
EOFError2["MaxInputs"] = "inputs exceeds 127, the maximum, got: ";
EOFError2["MaxOutputs"] = "outputs exceeds 127, the maximum, got: ";
EOFError2["Code0Inputs"] = "first code section should have 0 inputs";
EOFError2["Code0Outputs"] = "first code section should have 0x80 (terminating section) outputs";
EOFError2["MaxStackHeight"] = `expected maxStackHeight`;
EOFError2["MaxStackHeightLimit"] = `stack height limit of 1024 exceeded: `;
EOFError2["MinCodeSections"] = `should have at least 1 code section`;
EOFError2["MaxCodeSections"] = `can have at most 1024 code sections`;
EOFError2["CodeSection"] = `expected a code section`;
EOFError2["DataSection"] = `Expected data section`;
EOFError2["ContainerSection"] = "expected a container section";
EOFError2["ContainerSectionMin"] = "container section should be at least 1 byte";
EOFError2["InvalidEOFCreateTarget"] = "EOFCREATE targets an undefined container";
EOFError2["InvalidRETURNContractTarget"] = "RETURNCONTRACT targets an undefined container";
EOFError2["ContainerDoubleType"] = "Container is targeted by both EOFCREATE and RETURNCONTRACT";
EOFError2["UnreachableContainerSections"] = "Unreachable containers (by both EOFCREATE and RETURNCONTRACT)";
EOFError2["ContainerTypeError"] = "Container contains opcodes which this mode (deployment mode / init code / runtime mode) cannot have";
EOFError2["DanglingBytes"] = "got dangling bytes in body";
EOFError2["InvalidOpcode"] = "invalid opcode";
EOFError2["InvalidTerminator"] = "invalid terminating opcode";
EOFError2["OpcodeIntermediatesOOB"] = "invalid opcode: intermediates out-of-bounds";
EOFError2["InvalidRJUMP"] = "invalid rjump* target";
EOFError2["InvalidCallTarget"] = "invalid callf/jumpf target";
EOFError2["InvalidCALLFReturning"] = "invalid callf: calls to non-returning function";
EOFError2["InvalidStackHeight"] = "invalid stack height";
EOFError2["InvalidJUMPF"] = "invalid jumpf target (output count)";
EOFError2["InvalidReturningSection"] = "invalid returning code section: section is not returning";
EOFError2["RJUMPVTableSize0"] = "invalid RJUMPV: table size 0";
EOFError2["UnreachableCodeSections"] = "unreachable code sections";
EOFError2["UnreachableCode"] = "unreachable code (by forward jumps)";
EOFError2["DataLoadNOutOfBounds"] = "DATALOADN reading out of bounds";
EOFError2["MaxStackHeightViolation"] = "Max stack height does not match the reported max stack height";
EOFError2["StackUnderflow"] = "Stack underflow";
EOFError2["StackOverflow"] = "Stack overflow";
EOFError2["UnstableStack"] = "Unstable stack (can reach stack under/overflow by jumps)";
EOFError2["RetfNoReturn"] = "Trying to return to undefined function";
EOFError2["ReturnStackOverflow"] = "Return stack overflow";
EOFError2["InvalidExtcallTarget"] = "invalid extcall target: address > 20 bytes";
EOFError2["InvalidReturnContractDataSize"] = "invalid RETURNCONTRACT: data size lower than expected";
EOFError2["InvalidEofFormat"] = "invalid EOF format";
return EOFError2;
})(EOFError || {});
function validationError(type, ...args) {
switch (type) {
case "Trying to read out of bounds": {
const pos = args[0];
if (pos === 0 || pos === 2 || pos === 3 || pos === 6) {
throw new Error(args[1]);
}
throw new Error(`Trying to read out of bounds `);
}
case "Bytes do not match expected value": {
const pos = args[0];
if (pos === 0 || pos === 2 || pos === 3 || pos === 6) {
throw new Error(args[1]);
}
throw new Error(`Bytes do not match expected value at pos: ${args[0]}: ${args[1]}`);
}
case "Uint does not match expected value ": {
const pos = args[0];
if (pos === 0 || pos === 2 || pos === 3 || pos === 6 || pos === 18) {
throw new Error(args[1]);
}
throw new Error(`Uint does not match expected value at pos: ${args[0]}: ${args[1]}`);
}
case "missing type size": {
throw new Error("missing type size" + args[0]);
}
case "err: mismatch of code sections count and type signatures": {
throw new Error(`${"err: mismatch of code sections count and type signatures"} (types ${args[0]} code ${args[1]})`);
}
case "err: type section size invalid": {
throw new Error(
"err: type section size invalid"
/* InvalidTypeSize */
);
}
case "code size does not match type size": {
throw new Error("code size does not match type size" + args[0]);
}
case "expected inputs": {
throw new Error(`${"expected inputs"} - typeSection ${args[0]}`);
}
case "expected outputs": {
throw new Error(`${"expected outputs"} - typeSection ${args[0]}`);
}
case "first code section should have 0 inputs": {
throw new Error(`first code section should have 0 inputs`);
}
case "first code section should have 0x80 (terminating section) outputs": {
throw new Error(`first code section should have 0 outputs`);
}
case "inputs exceeds 127, the maximum, got: ": {
throw new Error(`inputs exceeds 127, the maximum, got: ${args[1]} - code section ${args[0]}`);
}
case "outputs exceeds 127, the maximum, got: ": {
throw new Error(`outputs exceeds 127, the maximum, got: ${args[1]} - code section ${args[0]}`);
}
case "expected a code section": {
throw new Error(`expected code: codeSection ${args[0]}: `);
}
case "Expected data section": {
throw new Error(
"Expected data section"
/* DataSection */
);
}
case "expected maxStackHeight": {
throw new Error(`${"expected maxStackHeight"} - typeSection ${args[0]}: `);
}
case "stack height limit of 1024 exceeded: ": {
throw new Error(`${"stack height limit of 1024 exceeded: "}, got: ${args[1]} - typeSection ${args[0]}`);
}
case "got dangling bytes in body": {
throw new Error(
"got dangling bytes in body"
/* DanglingBytes */
);
}
default: {
throw new Error(type);
}
}
}
const stackDelta = {
0: { inputs: 0, outputs: 0, name: "STOP", intermediates: 0, terminating: true },
1: { inputs: 2, outputs: 1, name: "ADD", intermediates: 0 },
2: { inputs: 2, outputs: 1, name: "MUL", intermediates: 0 },
3: { inputs: 2, outputs: 1, name: "SUB", intermediates: 0 },
4: { inputs: 2, outputs: 1, name: "DIV", intermediates: 0 },
5: { inputs: 2, outputs: 1, name: "SDIV", intermediates: 0 },
6: { inputs: 2, outputs: 1, name: "MOD", intermediates: 0 },
7: { inputs: 2, outputs: 1, name: "SMOD", intermediates: 0 },
8: { inputs: 3, outputs: 1, name: "ADDMOD", intermediates: 0 },
9: { inputs: 3, outputs: 1, name: "MULMOD", intermediates: 0 },
10: { inputs: 2, outputs: 1, name: "EXP", intermediates: 0 },
11: { inputs: 2, outputs: 1, name: "SIGNEXTEND", intermediates: 0 },
16: { inputs: 2, outputs: 1, name: "LT", intermediates: 0 },
17: { inputs: 2, outputs: 1, name: "GT", intermediates: 0 },
18: { inputs: 2, outputs: 1, name: "SLT", intermediates: 0 },
19: { inputs: 2, outputs: 1, name: "SGT", intermediates: 0 },
20: { inputs: 2, outputs: 1, name: "EQ", intermediates: 0 },
21: { inputs: 1, outputs: 1, name: "ISZERO", intermediates: 0 },
22: { inputs: 2, outputs: 1, name: "AND", intermediates: 0 },
23: { inputs: 2, outputs: 1, name: "OR", intermediates: 0 },
24: { inputs: 2, outputs: 1, name: "XOR", intermediates: 0 },
25: { inputs: 1, outputs: 1, name: "NOT", intermediates: 0 },
26: { inputs: 2, outputs: 1, name: "BYTE", intermediates: 0 },
27: { inputs: 2, outputs: 1, name: "SHL", intermediates: 0 },
28: { inputs: 2, outputs: 1, name: "SHR", intermediates: 0 },
29: { inputs: 2, outputs: 1, name: "SAR", intermediates: 0 },
32: { inputs: 2, outputs: 1, name: "SHA3", intermediates: 0 },
48: { inputs: 0, outputs: 1, name: "ADDRESS", intermediates: 0 },
49: { inputs: 1, outputs: 1, name: "BALANCE", intermediates: 0 },
50: { inputs: 0, outputs: 1, name: "ORIGIN", intermediates: 0 },
51: { inputs: 0, outputs: 1, name: "CALLER", intermediates: 0 },
52: { inputs: 0, outputs: 1, name: "CALLVALUE", intermediates: 0 },
53: { inputs: 1, outputs: 1, name: "CALLDATALOAD", intermediates: 0 },
54: { inputs: 0, outputs: 1, name: "CALLDATASIZE", intermediates: 0 },
55: { inputs: 3, outputs: 0, name: "CALLDATACOPY", intermediates: 0 },
58: { inputs: 0, outputs: 1, name: "GASPRICE", intermediates: 0 },
61: { inputs: 0, outputs: 1, name: "RETURNDATASIZE", intermediates: 0 },
62: { inputs: 3, outputs: 0, name: "RETURNDATACOPY", intermediates: 0 },
64: { inputs: 1, outputs: 1, name: "BLOCKHASH", intermediates: 0 },
65: { inputs: 0, outputs: 1, name: "COINBASE", intermediates: 0 },
66: { inputs: 0, outputs: 1, name: "TIMESTAMP", intermediates: 0 },
67: { inputs: 0, outputs: 1, name: "NUMBER", intermediates: 0 },
68: { inputs: 0, outputs: 1, name: "PREVRANDAO", intermediates: 0 },
69: { inputs: 0, outputs: 1, name: "GASLIMIT", intermediates: 0 },
70: { inputs: 0, outputs: 1, name: "CHAINID", intermediates: 0 },
71: { inputs: 0, outputs: 1, name: "SELFBALANCE", intermediates: 0 },
72: { inputs: 0, outputs: 1, name: "BASEFEE", intermediates: 0 },
73: { inputs: 1, outputs: 1, name: "BLOBAHASH", intermediates: 0 },
74: { inputs: 0, outputs: 1, name: "BLOBBASEFEE", intermediates: 0 },
80: { inputs: 1, outputs: 0, name: "POP", intermediates: 0 },
81: { inputs: 1, outputs: 1, name: "MLOAD", intermediates: 0 },
82: { inputs: 2, outputs: 0, name: "MSTORE", intermediates: 0 },
83: { inputs: 2, outputs: 0, name: "MSTORE8", intermediates: 0 },
84: { inputs: 1, outputs: 1, name: "SLOAD", intermediates: 0 },
85: { inputs: 2, outputs: 0, name: "SSTORE", intermediates: 0 },
89: { inputs: 0, outputs: 1, name: "MSIZE", intermediates: 0 },
91: { inputs: 0, outputs: 0, name: "NOOP", intermediates: 0 },
92: { inputs: 1, outputs: 1, name: "TLOAD", intermediates: 0 },
93: { inputs: 2, outputs: 0, name: "TSTORE", intermediates: 0 },
94: { inputs: 3, outputs: 0, name: "MCOPY", intermediates: 0 },
95: { inputs: 0, outputs: 1, name: "PUSH0", intermediates: 0 },
96: { inputs: 0, outputs: 1, name: "PUSH1", intermediates: 1 },
97: { inputs: 0, outputs: 1, name: "PUSH2", intermediates: 2 },
98: { inputs: 0, outputs: 1, name: "PUSH3", intermediates: 3 },
99: { inputs: 0, outputs: 1, name: "PUSH4", intermediates: 4 },
100: { inputs: 0, outputs: 1, name: "PUSH5", intermediates: 5 },
101: { inputs: 0, outputs: 1, name: "PUSH6", intermediates: 6 },
102: { inputs: 0, outputs: 1, name: "PUSH7", intermediates: 7 },
103: { inputs: 0, outputs: 1, name: "PUSH8", intermediates: 8 },
104: { inputs: 0, outputs: 1, name: "PUSH9", intermediates: 9 },
105: { inputs: 0, outputs: 1, name: "PUSH10", intermediates: 10 },
106: { inputs: 0, outputs: 1, name: "PUSH11", intermediates: 11 },
107: { inputs: 0, outputs: 1, name: "PUSH12", intermediates: 12 },
108: { inputs: 0, outputs: 1, name: "PUSH13", intermediates: 13 },
109: { inputs: 0, outputs: 1, name: "PUSH14", intermediates: 14 },
110: { inputs: 0, outputs: 1, name: "PUSH15", intermediates: 15 },
111: { inputs: 0, outputs: 1, name: "PUSH16", intermediates: 16 },
112: { inputs: 0, outputs: 1, name: "PUSH17", intermediates: 17 },
113: { inputs: 0, outputs: 1, name: "PUSH18", intermediates: 18 },
114: { inputs: 0, outputs: 1, name: "PUSH19", intermediates: 19 },
115: { inputs: 0, outputs: 1, name: "PUSH20", intermediates: 20 },
116: { inputs: 0, outputs: 1, name: "PUSH21", intermediates: 21 },
117: { inputs: 0, outputs: 1, name: "PUSH22", intermediates: 22 },
118: { inputs: 0, outputs: 1, name: "PUSH23", intermediates: 23 },
119: { inputs: 0, outputs: 1, name: "PUSH24", intermediates: 24 },
120: { inputs: 0, outputs: 1, name: "PUSH25", intermediates: 25 },
121: { inputs: 0, outputs: 1, name: "PUSH26", intermediates: 26 },
122: { inputs: 0, outputs: 1, name: "PUSH27", intermediates: 27 },
123: { inputs: 0, outputs: 1, name: "PUSH28", intermediates: 28 },
124: { inputs: 0, outputs: 1, name: "PUSH29", intermediates: 29 },
125: { inputs: 0, outputs: 1, name: "PUSH30", intermediates: 30 },
126: { inputs: 0, outputs: 1, name: "PUSH31", intermediates: 31 },
127: { inputs: 0, outputs: 1, name: "PUSH32", intermediates: 32 },
128: { inputs: 1, outputs: 2, name: "DUP1", intermediates: 0 },
129: { inputs: 2, outputs: 3, name: "DUP2", intermediates: 0 },
130: { inputs: 3, outputs: 4, name: "DUP3", intermediates: 0 },
131: { inputs: 4, outputs: 5, name: "DUP4", intermediates: 0 },
132: { inputs: 5, outputs: 6, name: "DUP5", intermediates: 0 },
133: { inputs: 6, outputs: 7, name: "DUP6", intermediates: 0 },
134: { inputs: 7, outputs: 8, name: "DUP7", intermediates: 0 },
135: { inputs: 8, outputs: 9, name: "DUP8", intermediates: 0 },
136: { inputs: 9, outputs: 10, name: "DUP9", intermediates: 0 },
137: { inputs: 10, outputs: 11, name: "DUP10", intermediates: 0 },
138: { inputs: 11, outputs: 12, name: "DUP11", intermediates: 0 },
139: { inputs: 12, outputs: 13, name: "DUP12", intermediates: 0 },
140: { inputs: 13, outputs: 14, name: "DUP13", intermediates: 0 },
141: { inputs: 14, outputs: 15, name: "DUP14", intermediates: 0 },
142: { inputs: 15, outputs: 16, name: "DUP15", intermediates: 0 },
143: { inputs: 16, outputs: 17, name: "DUP16", intermediates: 0 },
144: { inputs: 2, outputs: 2, name: "SWAP1", intermediates: 0 },
145: { inputs: 3, outputs: 3, name: "SWAP2", intermediates: 0 },
146: { inputs: 4, outputs: 4, name: "SWAP3", intermediates: 0 },
147: { inputs: 5, outputs: 5, name: "SWAP4", intermediates: 0 },
148: { inputs: 6, outputs: 6, name: "SWAP5", intermediates: 0 },
149: { inputs: 7, outputs: 7, name: "SWAP6", intermediates: 0 },
150: { inputs: 8, outputs: 8, name: "SWAP7", intermediates: 0 },
151: { inputs: 9, outputs: 9, name: "SWAP8", intermediates: 0 },
152: { inputs: 10, outputs: 10, name: "SWAP9", intermediates: 0 },
153: { inputs: 11, outputs: 11, name: "SWAP10", intermediates: 0 },
154: { inputs: 12, outputs: 12, name: "SWAP11", intermediates: 0 },
155: { inputs: 13, outputs: 13, name: "SWAP12", intermediates: 0 },
156: { inputs: 14, outputs: 14, name: "SWAP13", intermediates: 0 },
157: { inputs: 15, outputs: 15, name: "SWAP14", intermediates: 0 },
158: { inputs: 16, outputs: 16, name: "SWAP15", intermediates: 0 },
159: { inputs: 17, outputs: 17, name: "SWAP16", intermediates: 0 },
160: { inputs: 2, outputs: 0, name: "LOG0", intermediates: 0 },
161: { inputs: 3, outputs: 0, name: "LOG1", intermediates: 0 },
162: { inputs: 4, outputs: 0, name: "LOG2", intermediates: 0 },
163: { inputs: 5, outputs: 0, name: "LOG3", intermediates: 0 },
164: { inputs: 6, outputs: 0, name: "LOG4", intermediates: 0 },
208: { inputs: 1, outputs: 1, name: "DATALOAD", intermediates: 0 },
209: { inputs: 0, outputs: 1, name: "DATALOADN", intermediates: 2 },
210: { inputs: 0, outputs: 1, name: "DATASIZE", intermediates: 0 },
211: { inputs: 3, outputs: 0, name: "DATACOPY", intermediates: 0 },
224: { inputs: 0, outputs: 0, name: "RJUMP", intermediates: 2 },
225: { inputs: 1, outputs: 0, name: "RJUMPI", intermediates: 2 },
// NOTE: for RJUMPV the intermediate byte is set to 0, this has to do with the validation algorithm specifics
// This has to do with the dynamic intermediate size of RJUMPV, which depends upon the table size byte right after RJUMPV
226: { inputs: 1, outputs: 0, name: "RJUMPV", intermediates: 0 },
// CALLF special case for stack validation algorithm: the inputs and outputs MUST stay 0
// (this is currently the case also in EVM)
227: { inputs: 0, outputs: 0, name: "CALLF", intermediates: 2 },
228: { inputs: 0, outputs: 0, name: "RETF", intermediates: 0, terminating: true },
229: { inputs: 0, outputs: 0, name: "JUMPF", intermediates: 2, terminating: true },
230: { inputs: 0, outputs: 1, name: "DUPN", intermediates: 1 },
231: { inputs: 0, outputs: 0, name: "SWAPN", intermediates: 1 },
232: { inputs: 0, outputs: 0, name: "EXCHANGE", intermediates: 1 },
236: { inputs: 4, outputs: 1, name: "EOFCREATE", intermediates: 1 },
238: { inputs: 2, outputs: 0, name: "RETURNCONTRACT", intermediates: 1, terminating: true },
243: { inputs: 2, outputs: 0, name: "RETURN", intermediates: 0, terminating: true },
247: { inputs: 1, outputs: 1, name: "RETURNDATALOAD", intermediates: 0 },
248: { inputs: 4, outputs: 1, name: "EXTCALL", intermediates: 0 },
249: { inputs: 3, outputs: 1, name: "EXTDELEGATECALL", intermediates: 0 },
251: { inputs: 3, outputs: 1, name: "EXTSTATICCALL", intermediates: 0 },
253: { inputs: 2, outputs: 0, name: "REVERT", intermediates: 0, terminating: true },
254: { inputs: 0, outputs: 0, name: "INVALID", intermediates: 0, terminating: true }
};
var ContainerSectionType = /* @__PURE__ */ ((ContainerSectionType2) => {
ContainerSectionType2[ContainerSectionType2["InitCode"] = 0] = "InitCode";
ContainerSectionType2[ContainerSectionType2["DeploymentCode"] = 1] = "DeploymentCode";
ContainerSectionType2[ContainerSectionType2["RuntimeCode"] = 2] = "RuntimeCode";
return ContainerSectionType2;
})(ContainerSectionType || {});
function verifyCode(container, evm, mode = 2) {
return validateOpcodes(container, evm, mode);
}
function readInt16(code, start) {
return new DataView(code.buffer).getInt16(start);
}
function readUint16(code, start) {
return new DataView(code.buffer).getUint16(start);
}
function validateOpcodes(container, evm, mode = 2) {
const intermediateBytes = /* @__PURE__ */ new Set();
const jumpLocations = /* @__PURE__ */ new Set();
const containerTypeMap = /* @__PURE__ */ new Map();
function addJump(location) {
if (intermediateBytes.has(location)) {
validationError(EOFError.InvalidRJUMP);
}
jumpLocations.add(location);
}
function addIntermediate(location) {
if (jumpLocations.has(location)) {
validationError(EOFError.InvalidRJUMP);
}
intermediateBytes.add(location);
}
const opcodes2 = evm.getActiveOpcodes();
const opcodeNumbers = /* @__PURE__ */ new Set();
for (const [key] of opcodes2) {
opcodeNumbers.add(key);
}
opcodeNumbers.add(254);
opcodeNumbers.delete(56);
opcodeNumbers.delete(57);
opcodeNumbers.delete(90);
opcodeNumbers.delete(59);
opcodeNumbers.delete(60);
opcodeNumbers.delete(63);
opcodeNumbers.delete(242);
opcodeNumbers.delete(255);
opcodeNumbers.delete(86);
opcodeNumbers.delete(87);
opcodeNumbers.delete(88);
opcodeNumbers.delete(240);
opcodeNumbers.delete(245);
const terminatingOpcodes = /* @__PURE__ */ new Set();
terminatingOpcodes.add(0);
terminatingOpcodes.add(243);
terminatingOpcodes.add(253);
terminatingOpcodes.add(254);
terminatingOpcodes.add(238);
terminatingOpcodes.add(228);
terminatingOpcodes.add(229);
terminatingOpcodes.add(224);
for (const opcode of terminatingOpcodes) {
if (!opcodeNumbers.has(opcode)) {
terminatingOpcodes.delete(opcode);
}
}
const validJumps = /* @__PURE__ */ new Set();
const reachableSections = {};
let codeSection = -1;
for (const code of container.body.codeSections) {
codeSection++;
reachableSections[codeSection] = /* @__PURE__ */ new Set();
const returningFunction = container.body.typeSections[codeSection].outputs === 128;
const reachableOpcodes = /* @__PURE__ */ new Set();
reachableOpcodes.add(0);
let ptr = 0;
let lastOpcode = 0;
const inputs = container.body.typeSections[codeSection].inputs;
let maxStackHeight = inputs;
const stackHeightMin = [inputs];
const stackHeightMax = [inputs];
while (ptr < code.length) {
const successorSet = /* @__PURE__ */ new Set();
if (!reachableOpcodes.has(ptr)) {
validationError(EOFError.UnreachableCode);
}
if (stackHeightMin[ptr] === void 0 || stackHeightMax[ptr] === void 0) {
validationError(EOFError.UnreachableCode);
}
validJumps.add(ptr);
const opcode = code[ptr];
const minStackCurrent = stackHeightMin[ptr];
const maxStackCurrent = stackHeightMax[ptr];
const opcodeInputs = stackDelta[opcode].inputs;
const opcodeOutputs = stackDelta[opcode].outputs;
if (minStackCurrent - opcodeInputs < 0) {
validationError(EOFError.StackUnderflow);
}
const delta = opcodeOutputs - opcodeInputs;
let minStackNext = minStackCurrent + delta;
let maxStackNext = maxStackCurrent + delta;
if (maxStackNext > 1023) {
validationError(EOFError.StackOverflow);
}
if (returningFunction && opcode === 228) {
validationError(EOFError.InvalidReturningSection);
}
lastOpcode = opcode;
if (!opcodeNumbers.has(opcode)) {
validationError(EOFError.InvalidOpcode);
}
if (opcode === 224 || opcode === 225) {
const target = readInt16(code, ptr + 1) + ptr + 3;
if (target < 0 || target >= code.length) {
validationError(EOFError.InvalidRJUMP);
}
successorSet.add(target);
addJump(target);
reachableOpcodes.add(target);
if (opcode === 224) {
if (!reachableOpcodes.has(ptr + 3) && ptr + 3 < code.length) {
validationError(EOFError.UnreachableCode);
}
}
} else if (opcode === 226) {
const tableSize = code[ptr + 1] + 1;
if (tableSize === void 0) {
validationError(EOFError.OpcodeIntermediatesOOB);
} else if (tableSize === 0) {
validationError(EOFError.RJUMPVTableSize0);
}
if (ptr + tableSize * 2 + 2 >= code.length) {
validationError(EOFError.OpcodeIntermediatesOOB);
}
const newPc = ptr + 2 + tableSize * 2;
for (let i = 0; i < tableSize; i++) {
const newPtr = ptr + 2 + i * 2;
addIntermediate(newPtr);
addIntermediate(newPtr + 1);
const target = readInt16(code, newPtr) + newPc;
if (target < 0 || target >= code.length) {
validationError(EOFError.OpcodeIntermediatesOOB);
}
successorSet.add(target);
addJump(target);
reachableOpcodes.add(target);
}
addIntermediate(ptr + 1);
ptr += 2 * tableSize + 1;
} else if (opcode === 227 || opcode === 229) {
const target = readUint16(code, ptr + 1);
reachableSections[codeSection].add(target);
if (target >= container.header.codeSizes.length) {
validationError(EOFError.InvalidCallTarget);
}
if (opcode === 227) {
const targetOutputs = container.body.typeSections[target].outputs;
const targetInputs = container.body.typeSections[target].inputs;
if (targetOutputs === 128) {
validationError(EOFError.InvalidCALLFReturning);
}
if (minStackCurrent < targetInputs) {
validationError(EOFError.StackUnderflow);
}
if (maxStackCurrent + container.body.typeSections[target].maxStackHeight - targetInputs > 1024) {
validationError(EOFError.StackOverflow);
}
minStackNext += targetOutputs - targetInputs;
maxStackNext += targetOutputs - targetInputs;
} else {
const currentOutputs = container.body.typeSections[codeSection].outputs;
const targetOutputs = container.body.typeSections[target].outputs;
const targetInputs = container.body.typeSections[target].inputs;
const targetNonReturning = targetOutputs === 128;
if (targetOutputs > currentOutputs && !targetNonReturning) {
validationError(EOFError.InvalidJUMPF);
}
if (returningFunction && targetOutputs <= 127) {
validationError(EOFError.InvalidReturningSection);
}
if (targetNonReturning) {
if (minStackCurrent < targetInputs) {
validationError(EOFError.StackUnderflow);
}
} else {
const expectedStack = currentOutputs + targetInputs - targetOutputs;
if (!(minStackCurrent === maxStackCurrent && maxStackCurrent === expectedStack)) {
validationError(EOFError.InvalidStackHeight);
}
}
if (maxStackCurrent + container.body.typeSections[target].maxStackHeight - targetInputs > 1024) {
validationError(EOFError.StackOverflow);
}
}
} else if (opcode === 228) {
const outputs = container.body.typeSections[codeSection].outputs;
if (!(minStackCurrent === maxStackCurrent && maxStackCurrent === outputs)) {
validationError(EOFError.InvalidStackHeight);
}
} else if (opcode === 230) {
const toDup = code[ptr + 1];
if (toDup + 1 > minStackCurrent) {
validationError(EOFError.StackUnderflow);
}
} else if (opcode === 231) {
const toSwap = code[ptr + 1];
if (toSwap + 1 > minStackCurrent) {
validationError(EOFError.StackUnderflow);
}
} else if (opcode === 232) {
const exchangeRaw = code[ptr + 1];
const n = (exchangeRaw >> 4) + 1;
const m = (exchangeRaw & 15) + 1;
if (n + m + 1 > minStackCurrent) {
validationError(EOFError.StackUnderflow);
}
} else if (opcode === 236) {
const target = code[ptr + 1];
if (target >= container.header.containerSizes.length) {
validationError(EOFError.InvalidEOFCreateTarget);
}
if (containerTypeMap.has(target)) {
if (containerTypeMap.get(target) !== 0) {
validationError(EOFError.ContainerDoubleType);
}
}
containerTypeMap.set(
target,
0
/* InitCode */
);
} else if (opcode === 238) {
if (mode !== 0) {
validationError(EOFError.ContainerTypeError);
}
const target = code[ptr + 1];
if (target >= container.header.containerSizes.length) {
validationError(EOFError.InvalidRETURNContractTarget);
}
if (containerTypeMap.has(target)) {
if (containerTypeMap.get(target) !== 1) {
validationError(EOFError.ContainerDoubleType);
}
}
containerTypeMap.set(
target,
1
/* DeploymentCode */
);
} else if (opcode === 209) {
const dataTarget = readUint16(code, ptr + 1);
const endOfSlice = dataTarget + 32;
if (container.header.dataSize < endOfSlice) {
validationError(EOFError.DataLoadNOutOfBounds);
}
} else if (opcode === 0 || opcode === 243) {
if (mode === 0) {
validationError(EOFError.ContainerTypeError);
}
}
const intermediates = stackDelta[opcode].intermediates;
if (intermediates > 0) {
for (let i = 1; i <= intermediates; i++) {
addIntermediate(ptr + i);
}
ptr += intermediates;
}
if (ptr >= code.length) {
validationError(EOFError.OpcodeIntermediatesOOB);
}
ptr++;
if (stackDelta[opcode].terminating === void 0) {
reachableOpcodes.add(ptr);
if (opcode !== 224) {
successorSet.add(ptr);
}
}
for (const successor of successorSet) {
if (successor < ptr) {
if (stackHeightMin[successor] !== minStackNext || stackHeightMax[successor] !== maxStackNext) {
validationError(EOFError.UnstableStack);
}
}
if (stackHeightMax[successor] === void 0) {
stackHeightMin[successor] = minStackNext;
stackHeightMax[successor] = maxStackNext;
} else {
stackHeightMin[successor] = Math.min(stackHeightMin[successor], minStackNext);
stackHeightMax[successor] = Math.max(stackHeightMax[successor], maxStackNext);
}
}
maxStackHeight = Math.max(maxStackNext, maxStackHeight);
}
if (!terminatingOpcodes.has(lastOpcode)) {
validationError(EOFError.InvalidTerminator);
}
if (container.body.typeSections[codeSection].maxStackHeight !== maxStackHeight) {
validationError(EOFError.MaxStackHeightViolation);
}
if (maxStackHeight > 1023) {
validationError(EOFError.MaxStackHeightLimit);
}
}
const sectionAccumulator = /* @__PURE__ */ new Set();
sectionAccumulator.add(0);
const toCheck = [0];
while (toCheck.length > 0) {
const checkArray = reachableSections[toCheck.pop()];
for (const checkSection of checkArray) {
if (!sectionAccumulator.has(checkSection)) {
sectionAccumulator.add(checkSection);
toCheck.push(checkSection);
}
}
}
if (sectionAccumulator.size !== container.header.codeSizes.length) {
validationError(EOFError.UnreachableCodeSections);
}
if (containerTypeMap.size !== container.header.containerSizes.length) {
validationError(EOFError.UnreachableContainerSections);
}
return containerTypeMap;
}
var EOFContainerMode = /* @__PURE__ */ ((EOFContainerMode2) => {
EOFContainerMode2[EOFContainerMode2["Default"] = 0] = "Default";
EOFContainerMode2[EOFContainerMode2["Initmode"] = 1] = "Initmode";
EOFContainerMode2[EOFContainerMode2["TxInitmode"] = 2] = "TxInitmode";
return EOFContainerMode2;
})(EOFContainerMode || {});
class StreamReader {
// Current pointer to where the stream is being read
constructor(stream) {
this.data = stream;
this.ptr = 0;
}
/**
* Read `amount` bytes from the stream. Throws when trying to read out of bounds with an optional error string.
* This also updates the internal pointer
* @param amount Bytes to read
* @param errorStr Optional error string to throw when trying to read out-of-bounds
* @returns The byte array with length `amount`
*/
readBytes(amount, errorStr) {
const end = this.ptr + amount;
if (end > this.data.length) {
validationError(EOFError.OutOfBounds, this.ptr, errorStr);
}
const ptr = this.ptr;
this.ptr += amount;
return this.data.slice(ptr, end);
}
/**
* Reads an Uint8. Also updates the pointer.
* @param errorStr Optional error string
* @returns The uint8
*/
readUint(errorStr) {
if (this.ptr >= this.data.length) {
validationError(EOFError.OutOfBounds, this.ptr, errorStr);
}
return this.data[this.ptr++];
}
/**
* Verify that the current uint8 pointed to by the pointer is the expected uint8
* Also updates the pointer
* @param expect The uint to expect
* @param errorStr Optional error string when the read uint is not the expected uint
*/
verifyUint(expect, errorStr) {
if (this.readUint() !== expect) {
validationError(EOFError.VerifyUint, this.ptr - 1, errorStr);
}
}
/**
* Same as readUint, except this reads an uint16
* @param errorStr
* @returns
*/
readUint16(errorStr) {
const end = this.ptr + 2;
if (end > this.data.length) {
validationError(EOFError.OutOfBounds, this.ptr, errorStr);
}
const ptr = this.ptr;
this.ptr += 2;
return new DataView(this.data.buffer).getUint16(ptr);
}
/**
* Get the current pointer of the stream
* @returns The pointer
*/
getPtr() {
return this.ptr;
}
// Get the remainder bytes of the current stream
readRemainder() {
return this.data.slice(this.ptr);
}
// Returns `true` if the stream is fully read, or false if there are dangling bytes
isAtEnd() {
return this.ptr === this.data.length;
}
}
class EOFHeader {
// Internal array to track at which byte of the container the code starts (per section)
/**
* Create an EOF header. Performs various validation checks inside the constructor
* @param input either a raw header or a complete container
*/
constructor(input) {
if (input.length > MAX_HEADER_SIZE) {
throw new Error("err: container size more than maximum valid size");
}
const stream = new StreamReader(input);
stream.verifyUint(FORMAT, EOFError.FORMAT);
stream.verifyUint(MAGIC, EOFError.MAGIC);
stream.verifyUint(VERSION, EOFError.VERSION);
if (input.length < 15) {
throw new Error("err: container size less than minimum valid size");
}
stream.verifyUint(KIND_TYPE, EOFError.KIND_TYPE);
const typeSize = stream.readUint16(EOFError.TypeSize);
if (typeSize < TYPE_MIN) {
validationError(EOFError.InvalidTypeSize, typeSize);
}
if (typeSize % TYPE_DIVISOR !== 0) {
validationError(EOFError.InvalidTypeSize, typeSize);
}
if (typeSize > TYPE_MAX) {
throw new Error(`err: number of code sections must not exceed 1024 (got ${typeSize})`);
}
stream.verifyUint(KIND_CODE, EOFError.KIND_CODE);
const codeSize = stream.readUint16(EOFError.CodeSize);
if (codeSize < CODE_MIN) {
validationError(EOFError.MinCodeSections);
}
if (codeSize !== typeSize / TYPE_DIVISOR) {
validationError(EOFError.TypeSections, typeSize / TYPE_DIVISOR, codeSize);
}
const codeSizes = [];
for (let i = 0; i < codeSize; i++) {
const codeSectionSize = stream.readUint16(EOFError.CodeSection);
if (codeSectionSize < CODE_SIZE_MIN) {
validationError(EOFError.CodeSectionSize);
}
codeSizes.push(codeSectionSize);
}
let nextSection = stream.readUint();
const containerSizes = [];
if (nextSection === KIND_CONTAINER) {
const containerSectionSize = stream.readUint16(EOFError.ContainerSize);
if (containerSectionSize < CONTAINER_MIN) {
validationError(EOFError.ContainerSectionSize);
}
if (containerSectionSize > CONTAINER_MAX) {
validationError(EOFError.ContainerSectionSize);
}
for (let i = 0; i < containerSectionSize; i++) {
const containerSize = stream.readUint16(EOFError.ContainerSection);
if (containerSize < CONTAINER_SIZE_MIN) {
validationError(EOFError.ContainerSectionMin);
}
containerSizes.push(containerSize);
}
nextSection = stream.readUint();
}
if (nextSection !== KIND_DATA) {
validationError(EOFError.KIND_DATA);
}
this.dataSizePtr = stream.getPtr();
const dataSize = stream.readUint16(EOFError.DataSize);
stream.verifyUint(TERMINATOR, EOFError.TERMINATOR);
this.typeSize = typeSize;
this.codeSizes = codeSizes;
this.containerSizes = containerSizes;
this.dataSize = dataSize;
this.buffer = input.slice(0, stream.getPtr());
const relativeOffset = this.buffer.length + this.typeSize;
this.codeStartPos = [relativeOffset];
}
sections() {
return [this.typeSize, this.codeSizes, this.containerSizes, this.dataSize];
}
sectionSizes() {
return [1, this.codeSizes.length, this.containerSizes.length, 1];
}
// Returns the code position in the container for the requested section
// Setting the Program Counter in the EVM to a number of this array would start executing the bytecode of the indexed section
getCodePosition(section) {
if (this.codeStartPos[section]) {
return this.codeStartPos[section];
}
const start = this.codeStartPos.length;
let offset = this.codeStartPos[start - 1];
for (let i = start; i <= section; i++) {
offset += this.codeSizes[i - 1];
this.codeStartPos[i] = offset;
}
return offset;
}
}
class EOFBody {
// Only available in TxInitmode. The `txCallData` are the dangling bytes after parsing the container,
// and these are used for the CALLDATA in the EVM when trying to create a contract via a transaction, and the deployment code is an EOF container
constructor(buf, header, eofMode = 0, dataSectionAllowedSmaller = false) {
const stream = new StreamReader(buf);
const typeSections = [];
for (let i = 0; i < header.typeSize / 4; i++) {
const inputs = stream.readUint(EOFError.Inputs);
const outputs = stream.readUint(EOFError.Outputs);
const maxStackHeight = stream.readUint16(EOFError.MaxStackHeight);
if (i === 0) {
if (inputs !== 0) {
validationError(EOFError.Code0Inputs);
}
if (outputs !== 128) {
validationError(EOFError.Code0Outputs);
}
}
if (inputs > INPUTS_MAX) {
validationError(EOFError.MaxInputs, i, inputs);
}
if (outputs > OUTPUTS_MAX) {
validationError(EOFError.MaxOutputs, i, outputs);
}
if (maxStackHeight > MAX_STACK_HEIGHT) {
validationError(EOFError.MaxStackHeightLimit, i, maxStackHeight);
}
typeSections.push({
inputs,
outputs,
maxStackHeight
});
}
const codeStartPtr = stream.getPtr();
const codes = [];
for (const [i, codeSize] of header.codeSizes.entries()) {
try {
const code = stream.readBytes(codeSize);
codes.push(code);
} catch {
validationError(EOFError.CodeSection, i);
}
}
const entireCodeSection = buf.slice(codeStartPtr, stream.getPtr());
const containers = [];
for (const [i, containerSize] of header.containerSizes.entries()) {
try {
const container = stream.readBytes(containerSize);
containers.push(container);
} catch {
validationError(EOFError.ContainerSection, i);
}
}
let dataSection;
if (eofMode !== 1 && !dataSectionAllowedSmaller) {
dataSection = stream.readBytes(header.dataSize, EOFError.DataSection);
if (eofMode === 0) {
if (!stream.isAtEnd()) {
validationError(EOFError.DanglingBytes);
}
} else {
this.txCallData = stream.readRemainder();
}
} else {
dataSection = stream.readRemainder();
}
this.typeSections = typeSections;
this.codeSections = codes;
this.containerSections = containers;
this.entireCode = entireCodeSection;
this.dataSection = dataSection;
this.buffer = buf;
}
sections() {
return [this.typeSections, this.codeSections, this.dataSection];
}
size() {
return {
typeSize: this.typeSections.length,
codeSize: this.codeSections.length,
dataSize: this.dataSection.length
};
}
sectionSizes() {
return [
this.typeSections.map(() => 4),
this.codeSections.map((b) => b.length),
this.dataSection.length
];
}
}
class EOFContainer {
/**
*
* @param buf Entire container buffer
* @param eofMode Container mode to validate the container on
* @param dataSectionAllowedSmaller `true` if the data section is allowed to be smaller than the data section size in the header
*/
constructor(buf, eofMode = 0, dataSectionAllowedSmaller = false) {
this.eofMode = eofMode;
this.header = new EOFHeader(buf);
this.body = new EOFBody(
buf.slice(this.header.buffer.length),
this.header,
eofMode,
dataSectionAllowedSmaller
);
this.buffer = buf;
}
}
function validateEOF(input, evm, containerMode = ContainerSectionType.RuntimeCode, eofMode = 0) {
const container = new EOFContainer(
input,
eofMode,
containerMode === ContainerSectionType.DeploymentCode
);
const containerMap = verifyCode(container, evm, containerMode);
for (let i = 0; i < container.body.containerSections.length; i++) {
const subContainer = container.body.containerSections[i];
const mode = containerMap.get(i);
validateEOF(subContainer, evm, mode);
}
return container;
}
const Mainnet = {
name: "mainnet",
chainId: 1,
defaultHardfork: "cancun",
consensus: {
type: "pow",
algorithm: "ethash",
ethash: {}
},
comment: "The Ethereum main chain",
url: "https://ethstats.net/",
genesis: {
gasLimit: 5e3,
difficulty: 17179869184,
nonce: "0x0000000000000042",
extraData: "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"
},
depositContractAddress: "0x00000000219ab540356cBB839Cbe05303d7705Fa",
hardforks: [
{
name: "chainstart",
block: 0,
forkHash: "0xfc64ec04"
},
{
name: "homestead",
block: 115e4,
forkHash: "0x97c2c34c"
},
{
name: "dao",
block: 192e4,
forkHash: "0x91d1f948"
},
{
name: "tangerineWhistle",
block: 2463e3,
forkHash: "0x7a64da13"
},
{
name: "spuriousDragon",
block: 2675e3,
forkHash: "0x3edd5b10"
},
{
name: "byzantium",
block: 437e4,
forkHash: "0xa00bc324"
},
{
name: "constantinople",
block: 728e4,
forkHash: "0x668db0af"
},
{
name: "petersburg",
block: 728e4,
forkHash: "0x668db0af"
},
{
name: "istanbul",
block: 9069e3,
forkHash: "0x879d6e30"
},
{
name: "muirGlacier",
block: 92e5,
forkHash: "0xe029e991"
},
{
name: "berlin",
block: 12244e3,
forkHash: "0x0eb440f6"
},
{
name: "london",
block: 12965e3,
forkHash: "0xb715077d"
},
{
name: "arrowGlacier",
block: 13773e3,
forkHash: "0x20c327fc"
},
{
name: "grayGlacier",
block: 1505e4,
forkHash: "0xf0afd0e3"
},
{
// The forkHash will remain same as mergeForkIdTransition is post merge
// terminal block: https://etherscan.io/block/15537393
name: "paris",
block: 15537394,
forkHash: "0xf0afd0e3"
},
{
name: "mergeForkIdTransition",
block: null,
forkHash: null
},
{
name: "shanghai",
block: null,
timestamp: "1681338455",
forkHash: "0xdce96c2d"
},
{
name: "cancun",
block: null,
timestamp: "1710338135",
forkHash: "0x9f3d2254"
},
{
name: "prague",
block: null
}
],
bootstrapNodes: [
{
ip: "18.138.108.67",
port: 30303,
id: "d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666",
location: "ap-southeast-1-001",
comment: "bootnode-aws-ap-southeast-1-001"
},
{
ip: "3.209.45.79",
port: 30303,
id: "22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de",
location: "us-east-1-001",
comment: "bootnode-aws-us-east-1-001"
},
{
ip: "65.108.70.101",
port: 30303,
id: "2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc",
location: "eu-west-1-001",
comment: "bootnode-hetzner-hel"
},
{
ip: "157.90.35.166",
port: 30303,
id: "4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052",
location: "eu-central-1-001",
comment: "bootnode-hetzner-fsn"
}
],
dnsNetworks: [
"enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net"
]
};
function number(n) {
if (!Number.isSafeInteger(n) || n < 0)
throw new Error(`positive integer expected, not ${n}`);
}
function bool(b) {
if (typeof b !== "boolean")
throw new Error(`boolean expected, not ${b}`);
}
function isBytes$1(a) {
return a instanceof Uint8Array || a != null && typeof a === "object" && a.constructor.name === "Uint8Array";
}
function bytes(b, ...lengths) {
if (!isBytes$1(b))
throw new Error("Uint8Array expected");
if (lengths.length > 0 && !lengths.includes(b.length))
throw new Error(`Uint8Array expected of length ${lengths}, not of length=${b.length}`);
}
function hash(h) {
if (typeof h !== "function" || typeof h.create !== "function")
throw new Error("Hash should be wrapped by utils.wrapConstructor");
number(h.outputLen);
number(h.blockLen);
}
function exists(instance, checkFinished = true) {
if (instance.destroyed)
throw new Error("Hash instance has been destroyed");
if (checkFinished && instance.finished)
throw new Error("Hash#digest() has already been called");
}
function output(out, instance) {
bytes(out);
const min = instance.outputLen;
if (out.length < min) {
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
}
}
const assert = { number, bool, bytes, hash, exists, output };
const crypto = typeof globalThis === "object" && "crypto" in globalThis ? globalThis.crypto : void 0;
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
const rotr = (word, shift) => word << 32 - shift | word >>> shift;
const rotl = (word, shift) => word << shift | word >>> 32 - shift >>> 0;
const isLE = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68;
const byteSwap = (word) => word << 24 & 4278190080 | word << 8 & 16711680 | word >>> 8 & 65280 | word >>> 24 & 255;
function byteSwap32(arr) {
for (let i = 0; i < arr.length; i++) {
arr[i] = byteSwap(arr[i]);
}
}
const hexes$1 = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
function bytesToHex$3(bytes$1) {
bytes(bytes$1);
let hex = "";
for (let i = 0; i < bytes$1.length; i++) {
hex += hexes$1[bytes$1[i]];
}
return hex;
}
const asciis$1 = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 };
function asciiToBase16$1(char) {
if (char >= asciis$1._0 && char <= asciis$1._9)
return char - asciis$1._0;
if (char >= asciis$1._A && char <= asciis$1._F)
return char - (asciis$1._A - 10);
if (char >= asciis$1._a && char <= asciis$1._f)
return char - (asciis$1._a - 10);
return;
}
function hexToBytes$4(hex) {
if (typeof hex !== "string")
throw new Error("hex string expected, got " + typeof hex);
const hl = hex.length;
const al = hl / 2;
if (hl % 2)
throw new Error("padded hex string expected, got unpadded hex of length " + hl);
const array = new Uint8Array(al);
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
const n1 = asciiToBase16$1(hex.charCodeAt(hi));
const n2 = asciiToBase16$1(hex.charCodeAt(hi + 1));
if (n1 === void 0 || n2 === void 0) {
const char = hex[hi] + hex[hi + 1];
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
}
array[ai] = n1 * 16 + n2;
}
return array;
}
function utf8ToBytes$2(str) {
if (typeof str !== "string")
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
return new Uint8Array(new TextEncoder().encode(str));
}
function toBytes$2(data) {
if (typeof data === "string")
data = utf8ToBytes$2(data);
bytes(data);
return data;
}
function concatBytes$3(...arrays) {
let sum = 0;
for (let i = 0; i < arrays.length; i++) {
const a = arrays[i];
bytes(a);
sum += a.length;
}
const res = new Uint8Array(sum);
for (let i = 0, pad = 0; i < arrays.length; i++) {
const a = arrays[i];
res.set(a, pad);
pad += a.length;
}
return res;
}
class Hash {
// Safe version that clones internal state
clone() {
return this._cloneInto();
}
}
function wrapConstructor(hashCons) {
const hashC = (msg) => hashCons().update(toBytes$2(msg)).digest();
const tmp = hashCons();
hashC.outputLen = tmp.outputLen;
hashC.blockLen = tmp.blockLen;
hashC.create = () => hashCons();
return hashC;
}
function randomBytes(bytesLength = 32) {
if (crypto && typeof crypto.getRandomValues === "function") {
return crypto.getRandomValues(new Uint8Array(bytesLength));
}
if (crypto && typeof crypto.randomBytes === "function") {
return crypto.randomBytes(bytesLength);
}
throw new Error("crypto.getRandomValues must be defined");
}
function setBigUint64(view, byteOffset, value, isLE2) {
if (typeof view.setBigUint64 === "function")
return view.setBigUint64(byteOffset, value, isLE2);
const _32n2 = BigInt(32);
const _u32_max = BigInt(4294967295);
const wh = Number(value >> _32n2 & _u32_max);
const wl = Number(value & _u32_max);
const h = isLE2 ? 4 : 0;
const l = isLE2 ? 0 : 4;
view.setUint32(byteOffset + h, wh, isLE2);
view.setUint32(byteOffset + l, wl, isLE2);
}
const Chi = (a, b, c) => a & b ^ ~a & c;
const Maj = (a, b, c) => a & b ^ a & c ^ b & c;
class HashMD extends Hash {
constructor(blockLen, outputLen, padOffset, isLE2) {
super();
this.blockLen = blockLen;
this.outputLen = outputLen;
this.padOffset = padOffset;
this.isLE = isLE2;
this.finished = false;
this.length = 0;
this.pos = 0;
this.destroyed = false;
this.buffer = new Uint8Array(blockLen);
this.view = createView(this.buffer);
}
update(data) {
exists(this);
const { view, buffer, blockLen } = this;
data = toBytes$2(data);
const len = data.length;
for (let pos = 0; pos < len; ) {
const take = Math.min(blockLen - this.pos, len - pos);
if (take === blockLen) {
const dataView = createView(data);
for (; blockLen <= len - pos; pos += blockLen)
this.process(dataView, pos);
continue;
}
buffer.set(data.subarray(pos, pos + take), this.pos);
this.pos += take;
pos += take;
if (this.pos === blockLen) {
this.process(view, 0);
this.pos = 0;
}
}
this.length += data.length;
this.roundClean();
return this;
}
digestInto(out) {
exists(this);
output(out, this);
this.finished = true;
const { buffer, view, blockLen, isLE: isLE2 } = this;
let { pos } = this;
buffer[pos++] = 128;
this.buffer.subarray(pos).fill(0);
if (this.padOffset > blockLen - pos) {
this.process(view, 0);
pos = 0;
}
for (let i = pos; i < blockLen; i++)
buffer[i] = 0;
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE2);
this.process(view, 0);
const oview = createView(out);
const len = this.outputLen;
if (len % 4)
throw new Error("_sha2: outputLen should be aligned to 32bit");
const outLen = len / 4;
const state = this.get();
if (outLen > state.length)
throw new Error("_sha2: outputLen bigger than state");
for (let i = 0; i < outLen; i++)
oview.setUint32(4 * i, state[i], isLE2);
}
digest() {
const { buffer, outputLen } = this;
this.digestInto(buffer);
const res = buffer.slice(0, outputLen);
this.destroy();
return res;
}
_cloneInto(to) {
to || (to = new this.constructor());
to.set(...this.get());
const { blockLen, buffer, length, finished, destroyed, pos } = this;
to.length = length;
to.pos = pos;
to.finished = finished;
to.destroyed = destroyed;
if (length % blockLen)
to.buffer.set(buffer);
return to;
}
}
const SHA256_K = /* @__PURE__ */ new Uint32Array([
1116352408,
1899447441,
3049323471,
3921009573,
961987163,
1508970993,
2453635748,
2870763221,
3624381080,
310598401,
607225278,
1426881987,
1925078388,
2162078206,
2614888103,
3248222580,
3835390401,
4022224774,
264347078,
604807628,
770255983,
1249150122,
1555081692,
1996064986,
2554220882,
2821834349,
2952996808,
3210313671,
3336571891,
3584528711,
113926993,
338241895,
666307205,
773529912,
1294757372,
1396182291,
1695183700,
1986661051,
2177026350,
2456956037,
2730485921,
2820302411,
3259730800,
3345764771,
3516065817,
3600352804,
4094571909,
275423344,
430227734,
506948616,
659060556,
883997877,
958139571,
1322822218,
1537002063,
1747873779,
1955562222,
2024104815,
2227730452,
2361852424,
2428436474,
2756734187,
3204031479,
3329325298
]);
const SHA256_IV = /* @__PURE__ */ new Uint32Array([
1779033703,
3144134277,
1013904242,
2773480762,
1359893119,
2600822924,
528734635,
1541459225
]);
const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
class SHA256 extends HashMD {
constructor() {
super(64, 32, 8, false);
this.A = SHA256_IV[0] | 0;
this.B = SHA256_IV[1] | 0;
this.C = SHA256_IV[2] | 0;
this.D = SHA256_IV[3] | 0;
this.E = SHA256_IV[4] | 0;
this.F = SHA256_IV[5] | 0;
this.G = SHA256_IV[6] | 0;
this.H = SHA256_IV[7] | 0;
}
get() {
const { A, B, C, D, E, F: F2, G, H } = this;
return [A, B, C, D, E, F2, G, H];
}
// prettier-ignore
set(A, B, C, D, E, F2, G, H) {
this.A = A | 0;
this.B = B | 0;
this.C = C | 0;
this.D = D | 0;
this.E = E | 0;
this.F = F2 | 0;
this.G = G | 0;
this.H = H | 0;
}
process(view, offset) {
for (let i = 0; i < 16; i++, offset += 4)
SHA256_W[i] = view.getUint32(offset, false);
for (let i = 16; i < 64; i++) {
const W15 = SHA256_W[i - 15];
const W2 = SHA256_W[i - 2];
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
}
let { A, B, C, D, E, F: F2, G, H } = this;
for (let i = 0; i < 64; i++) {
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
const T1 = H + sigma1 + Chi(E, F2, G) + SHA256_K[i] + SHA256_W[i] | 0;
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
const T2 = sigma0 + Maj(A, B, C) | 0;
H = G;
G = F2;
F2 = E;
E = D + T1 | 0;
D = C;
C = B;
B = A;
A = T1 + T2 | 0;
}
A = A + this.A | 0;
B = B + this.B | 0;
C = C + this.C | 0;
D = D + this.D | 0;
E = E + this.E | 0;
F2 = F2 + this.F | 0;
G = G + this.G | 0;
H = H + this.H | 0;
this.set(A, B, C, D, E, F2, G, H);
}
roundClean() {
SHA256_W.fill(0);
}
destroy() {
this.set(0, 0, 0, 0, 0, 0, 0, 0);
this.buffer.fill(0);
}
}
const sha256$1 = /* @__PURE__ */ wrapConstructor(() => new SHA256());
class HMAC extends Hash {
constructor(hash$1, _key) {
super();
this.finished = false;
this.destroyed = false;
hash(hash$1);
const key = toBytes$2(_key);
this.iHash = hash$1.create();
if (typeof this.iHash.update !== "function")
throw new Error("Expected instance of class which extends utils.Hash");
this.blockLen = this.iHash.blockLen;
this.outputLen = this.iHash.outputLen;
const blockLen = this.blockLen;
const pad = new Uint8Array(blockLen);
pad.set(key.length > blockLen ? hash$1.create().update(key).digest() : key);
for (let i = 0; i < pad.length; i++)
pad[i] ^= 54;
this.iHash.update(pad);
this.oHash = hash$1.create();
for (let i = 0; i < pad.length; i++)
pad[i] ^= 54 ^ 92;
this.oHash.update(pad);
pad.fill(0);
}
update(buf) {
exists(this);
this.iHash.update(buf);
return this;
}
digestInto(out) {
exists(this);
bytes(out, this.outputLen);
this.finished = true;
this.iHash.digestInto(out);
this.oHash.update(out);
this.oHash.digestInto(out);
this.destroy();
}
digest() {
const out = new Uint8Array(this.oHash.outputLen);
this.digestInto(out);
return out;
}
_cloneInto(to) {
to || (to = Object.create(Object.getPrototypeOf(this), {}));
const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
to = to;
to.finished = finished;
to.destroyed = destroyed;
to.blockLen = blockLen;
to.outputLen = outputLen;
to.oHash = oHash._cloneInto(to.oHash);
to.iHash = iHash._cloneInto(to.iHash);
return to;
}
destroy() {
this.destroyed = true;
this.oHash.destroy();
this.iHash.destroy();
}
}
const hmac = (hash2, key, message) => new HMAC(hash2, key).update(message).digest();
hmac.create = (hash2, key) => new HMAC(hash2, key);
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const _0n$7 = /* @__PURE__ */ BigInt(0);
const _1n$9 = /* @__PURE__ */ BigInt(1);
const _2n$8 = /* @__PURE__ */ BigInt(2);
function isBytes(a) {
return a instanceof Uint8Array || a != null && typeof a === "object" && a.constructor.name === "Uint8Array";
}
function abytes(item) {
if (!isBytes(item))
throw new Error("Uint8Array expected");
}
function abool(title, value) {
if (typeof value !== "boolean")
throw new Error(`${title} must be valid boolean, got "${value}".`);
}
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
function bytesToHex$2(bytes2) {
abytes(bytes2);
let hex = "";
for (let i = 0; i < bytes2.length; i++) {
hex += hexes[bytes2[i]];
}
return hex;
}
function numberToHexUnpadded(num) {
const hex = num.toString(16);
return hex.length & 1 ? `0${hex}` : hex;
}
function hexToNumber(hex) {
if (typeof hex !== "string")
throw new Error("hex string expected, got " + typeof hex);
return BigInt(hex === "" ? "0" : `0x${hex}`);
}
const asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 };
function asciiToBase16(char) {
if (char >= asciis._0 && char <= asciis._9)
return char - asciis._0;
if (char >= asciis._A && char <= asciis._F)
return char - (asciis._A - 10);
if (char >= asciis._a && char <= asciis._f)
return char - (asciis._a - 10);
return;
}
function hexToBytes$3(hex) {
if (typeof hex !== "string")
throw new Error("hex string expected, got " + typeof hex);
const hl = hex.length;
const al = hl / 2;
if (hl % 2)
throw new Error("padded hex string expected, got unpadded hex of length " + hl);
const array = new Uint8Array(al);
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
const n1 = asciiToBase16(hex.charCodeAt(hi));
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
if (n1 === void 0 || n2 === void 0) {
const char = hex[hi] + hex[hi + 1];
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
}
array[ai] = n1 * 16 + n2;
}
return array;
}
function bytesToNumberBE(bytes2) {
return hexToNumber(bytesToHex$2(bytes2));
}
function bytesToNumberLE(bytes2) {
abytes(bytes2);
return hexToNumber(bytesToHex$2(Uint8Array.from(bytes2).reverse()));
}
function numberToBytesBE(n, len) {
return hexToBytes$3(n.toString(16).padStart(len * 2, "0"));
}
function numberToBytesLE(n, len) {
return numberToBytesBE(n, len).reverse();
}
function numberToVarBytesBE(n) {
return hexToBytes$3(numberToHexUnpadded(n));
}
function ensureBytes(title, hex, expectedLength) {
let res;
if (typeof hex === "string") {
try {
res = hexToBytes$3(hex);
} catch (e) {
throw new Error(`${title} must be valid hex string, got "${hex}". Cause: ${e}`);
}
} else if (isBytes(hex)) {
res = Uint8Array.from(hex);
} else {
throw new Error(`${title} must be hex string or Uint8Array`);
}
const len = res.length;
if (typeof expectedLength === "number" && len !== expectedLength)
throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);
return res;
}
function concatBytes$2(...arrays) {
let sum = 0;
for (let i = 0; i < arrays.length; i++) {
const a = arrays[i];
abytes(a);
sum += a.length;
}
const res = new Uint8Array(sum);
for (let i = 0, pad = 0; i < arrays.length; i++) {
const a = arrays[i];
res.set(a, pad);
pad += a.length;
}
return res;
}
function equalBytes(a, b) {
if (a.length !== b.length)
return false;
let diff = 0;
for (let i = 0; i < a.length; i++)
diff |= a[i] ^ b[i];
return diff === 0;
}
function utf8ToBytes$1(str) {
if (typeof str !== "string")
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
return new Uint8Array(new TextEncoder().encode(str));
}
const isPosBig = (n) => typeof n === "bigint" && _0n$7 <= n;
function inRange(n, min, max) {
return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
}
function aInRange(title, n, min, max) {
if (!inRange(n, min, max))
throw new Error(`expected valid ${title}: ${min} <= n < ${max}, got ${typeof n} ${n}`);
}
function bitLen(n) {
let len;
for (len = 0; n > _0n$7; n >>= _1n$9, len += 1)
;
return len;
}
function bitGet(n, pos) {
return n >> BigInt(pos) & _1n$9;
}
function bitSet(n, pos, value) {
return n | (value ? _1n$9 : _0n$7) << BigInt(pos);
}
const bitMask = (n) => (_2n$8 << BigInt(n - 1)) - _1n$9;
const u8n = (data) => new Uint8Array(data);
const u8fr = (arr) => Uint8Array.from(arr);
function createHmacDrbg(hashLen, qByteLen, hmacFn) {
if (typeof hashLen !== "number" || hashLen < 2)
throw new Error("hashLen must be a number");
if (typeof qByteLen !== "number" || qByteLen < 2)
throw new Error("qByteLen must be a number");
if (typeof hmacFn !== "function")
throw new Error("hmacFn must be a function");
let v = u8n(hashLen);
let k = u8n(hashLen);
let i = 0;
const reset = () => {
v.fill(1);
k.fill(0);
i = 0;
};
const h = (...b) => hmacFn(k, v, ...b);
const reseed = (seed = u8n()) => {
k = h(u8fr([0]), seed);
v = h();
if (seed.length === 0)
return;
k = h(u8fr([1]), seed);
v = h();
};
const gen2 = () => {
if (i++ >= 1e3)
throw new Error("drbg: tried 1000 values");
let len = 0;
const out = [];
while (len < qByteLen) {
v = h();
const sl = v.slice();
out.push(sl);
len += v.length;
}
return concatBytes$2(...out);
};
const genUntil = (seed, pred) => {
reset();
reseed(seed);
let res = void 0;
while (!(res = pred(gen2())))
reseed();
reset();
return res;
};
return genUntil;
}
const validatorFns = {
bigint: (val) => typeof val === "bigint",
function: (val) => typeof val === "function",
boolean: (val) => typeof val === "boolean",
string: (val) => typeof val === "string",
stringOrUint8Array: (val) => typeof val === "string" || isBytes(val),
isSafeInteger: (val) => Number.isSafeInteger(val),
array: (val) => Array.isArray(val),
field: (val, object) => object.Fp.isValid(val),
hash: (val) => typeof val === "function" && Number.isSafeInteger(val.outputLen)
};
function validateObject(object, validators, optValidators = {}) {
const checkField = (fieldName, type, isOptional) => {
const checkVal = validatorFns[type];
if (typeof checkVal !== "function")
throw new Error(`Invalid validator "${type}", expected function`);
const val = object[fieldName];
if (isOptional && val === void 0)
return;
if (!checkVal(val, object)) {
throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);
}
};
for (const [fieldName, type] of Object.entries(validators))
checkField(fieldName, type, false);
for (const [fieldName, type] of Object.entries(optValidators))
checkField(fieldName, type, true);
return object;
}
const notImplemented = () => {
throw new Error("not implemented");
};
function memoized(fn) {
const map = /* @__PURE__ */ new WeakMap();
return (arg, ...args) => {
const val = map.get(arg);
if (val !== void 0)
return val;
const computed = fn(arg, ...args);
map.set(arg, computed);
return computed;
};
}
const ut = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
aInRange,
abool,
abytes,
bitGet,
bitLen,
bitMask,
bitSet,
bytesToHex: bytesToHex$2,
bytesToNumberBE,
bytesToNumberLE,
concatBytes: concatBytes$2,
createHmacDrbg,
ensureBytes,
equalBytes,
hexToBytes: hexToBytes$3,
hexToNumber,
inRange,
isBytes,
memoized,
notImplemented,
numberToBytesBE,
numberToBytesLE,
numberToHexUnpadded,
numberToVarBytesBE,
utf8ToBytes: utf8ToBytes$1,
validateObject
}, Symbol.toStringTag, { value: "Module" }));
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const _0n$6 = BigInt(0), _1n$8 = BigInt(1), _2n$7 = BigInt(2), _3n$5 = BigInt(3);
const _4n$2 = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);
BigInt(9);
BigInt(16);
function mod$1(a, b) {
const result = a % b;
return result >= _0n$6 ? result : b + result;
}
function pow(num, power, modulo) {
if (modulo <= _0n$6 || power < _0n$6)
throw new Error("Expected power/modulo > 0");
if (modulo === _1n$8)
return _0n$6;
let res = _1n$8;
while (power > _0n$6) {
if (power & _1n$8)
res = res * num % modulo;
num = num * num % modulo;
power >>= _1n$8;
}
return res;
}
function pow2(x, power, modulo) {
let res = x;
while (power-- > _0n$6) {
res *= res;
res %= modulo;
}
return res;
}
function invert(number2, modulo) {
if (number2 === _0n$6 || modulo <= _0n$6) {
throw new Error(`invert: expected positive integers, got n=${number2} mod=${modulo}`);
}
let a = mod$1(number2, modulo);
let b = modulo;
let x = _0n$6, u = _1n$8;
while (a !== _0n$6) {
const q = b / a;
const r = b % a;
const m = x - u * q;
b = a, a = r, x = u, u = m;
}
const gcd = b;
if (gcd !== _1n$8)
throw new Error("invert: does not exist");
return mod$1(x, modulo);
}
function tonelliShanks(P) {
const legendreC = (P - _1n$8) / _2n$7;
let Q, S, Z;
for (Q = P - _1n$8, S = 0; Q % _2n$7 === _0n$6; Q /= _2n$7, S++)
;
for (Z = _2n$7; Z < P && pow(Z, legendreC, P) !== P - _1n$8; Z++)
;
if (S === 1) {
const p1div4 = (P + _1n$8) / _4n$2;
return function tonelliFast(Fp3, n) {
const root = Fp3.pow(n, p1div4);
if (!Fp3.eql(Fp3.sqr(root), n))
throw new Error("Cannot find square root");
return root;
};
}
const Q1div2 = (Q + _1n$8) / _2n$7;
return function tonelliSlow(Fp3, n) {
if (Fp3.pow(n, legendreC) === Fp3.neg(Fp3.ONE))
throw new Error("Cannot find square root");
let r = S;
let g = Fp3.pow(Fp3.mul(Fp3.ONE, Z), Q);
let x = Fp3.pow(n, Q1div2);
let b = Fp3.pow(n, Q);
while (!Fp3.eql(b, Fp3.ONE)) {
if (Fp3.eql(b, Fp3.ZERO))
return Fp3.ZERO;
let m = 1;
for (let t2 = Fp3.sqr(b); m < r; m++) {
if (Fp3.eql(t2, Fp3.ONE))
break;
t2 = Fp3.sqr(t2);
}
const ge = Fp3.pow(g, _1n$8 << BigInt(r - m - 1));
g = Fp3.sqr(ge);
x = Fp3.mul(x, ge);
b = Fp3.mul(b, g);
r = m;
}
return x;
};
}
function FpSqrt(P) {
if (P % _4n$2 === _3n$5) {
const p1div4 = (P + _1n$8) / _4n$2;
return function sqrt3mod4(Fp3, n) {
const root = Fp3.pow(n, p1div4);
if (!Fp3.eql(Fp3.sqr(root), n))
throw new Error("Cannot find square root");
return root;
};
}
if (P % _8n === _5n) {
const c1 = (P - _5n) / _8n;
return function sqrt5mod8(Fp3, n) {
const n2 = Fp3.mul(n, _2n$7);
const v = Fp3.pow(n2, c1);
const nv = Fp3.mul(n, v);
const i = Fp3.mul(Fp3.mul(nv, _2n$7), v);
const root = Fp3.mul(nv, Fp3.sub(i, Fp3.ONE));
if (!Fp3.eql(Fp3.sqr(root), n))
throw new Error("Cannot find square root");
return root;
};
}
return tonelliShanks(P);
}
const FIELD_FIELDS = [
"create",
"isValid",
"is0",
"neg",
"inv",
"sqrt",
"sqr",
"eql",
"add",
"sub",
"mul",
"pow",
"div",
"addN",
"subN",
"mulN",
"sqrN"
];
function validateField(field) {
const initial = {
ORDER: "bigint",
MASK: "bigint",
BYTES: "isSafeInteger",
BITS: "isSafeInteger"
};
const opts = FIELD_FIELDS.reduce((map, val) => {
map[val] = "function";
return map;
}, initial);
return validateObject(field, opts);
}
function FpPow(f2, num, power) {
if (power < _0n$6)
throw new Error("Expected power > 0");
if (power === _0n$6)
return f2.ONE;
if (power === _1n$8)
return num;
let p = f2.ONE;
let d = num;
while (power > _0n$6) {
if (power & _1n$8)
p = f2.mul(p, d);
d = f2.sqr(d);
power >>= _1n$8;
}
return p;
}
function FpInvertBatch(f2, nums) {
const tmp = new Array(nums.length);
const lastMultiplied = nums.reduce((acc, num, i) => {
if (f2.is0(num))
return acc;
tmp[i] = acc;
return f2.mul(acc, num);
}, f2.ONE);
const inverted = f2.inv(lastMultiplied);
nums.reduceRight((acc, num, i) => {
if (f2.is0(num))
return acc;
tmp[i] = f2.mul(acc, tmp[i]);
return f2.mul(acc, num);
}, inverted);
return tmp;
}
function FpLegendre(order) {
const legendreConst = (order - _1n$8) / _2n$7;
return (f2, x) => f2.pow(x, legendreConst);
}
function nLength(n, nBitLength) {
const _nBitLength = nBitLength !== void 0 ? nBitLength : n.toString(2).length;
const nByteLength = Math.ceil(_nBitLength / 8);
return { nBitLength: _nBitLength, nByteLength };
}
function Field(ORDER, bitLen2, isLE2 = false, redef = {}) {
if (ORDER <= _0n$6)
throw new Error(`Expected Field ORDER > 0, got ${ORDER}`);
const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen2);
if (BYTES > 2048)
throw new Error("Field lengths over 2048 bytes are not supported");
const sqrtP = FpSqrt(ORDER);
const f2 = Object.freeze({
ORDER,
BITS,
BYTES,
MASK: bitMask(BITS),
ZERO: _0n$6,
ONE: _1n$8,
create: (num) => mod$1(num, ORDER),
isValid: (num) => {
if (typeof num !== "bigint")
throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);
return _0n$6 <= num && num < ORDER;
},
is0: (num) => num === _0n$6,
isOdd: (num) => (num & _1n$8) === _1n$8,
neg: (num) => mod$1(-num, ORDER),
eql: (lhs, rhs) => lhs === rhs,
sqr: (num) => mod$1(num * num, ORDER),
add: (lhs, rhs) => mod$1(lhs + rhs, ORDER),
sub: (lhs, rhs) => mod$1(lhs - rhs, ORDER),
mul: (lhs, rhs) => mod$1(lhs * rhs, ORDER),
pow: (num, power) => FpPow(f2, num, power),
div: (lhs, rhs) => mod$1(lhs * invert(rhs, ORDER), ORDER),
// Same as above, but doesn't normalize
sqrN: (num) => num * num,
addN: (lhs, rhs) => lhs + rhs,
subN: (lhs, rhs) => lhs - rhs,
mulN: (lhs, rhs) => lhs * rhs,
inv: (num) => invert(num, ORDER),
sqrt: redef.sqrt || ((n) => sqrtP(f2, n)),
invertBatch: (lst) => FpInvertBatch(f2, lst),
// TODO: do we really need constant cmov?
// We don't have const-time bigints anyway, so probably will be not very useful
cmov: (a, b, c) => c ? b : a,
toBytes: (num) => isLE2 ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES),
fromBytes: (bytes2) => {
if (bytes2.length !== BYTES)
throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes2.length}`);
return isLE2 ? bytesToNumberLE(bytes2) : bytesToNumberBE(bytes2);
}
});
return Object.freeze(f2);
}
function getFieldBytesLength(fieldOrder) {
if (typeof fieldOrder !== "bigint")
throw new Error("field order must be bigint");
const bitLength = fieldOrder.toString(2).length;
return Math.ceil(bitLength / 8);
}
function getMinHashLength(fieldOrder) {
const length = getFieldBytesLength(fieldOrder);
return length + Math.ceil(length / 2);
}
function mapHashToField(key, fieldOrder, isLE2 = false) {
const len = key.length;
const fieldLen = getFieldBytesLength(fieldOrder);
const minLen = getMinHashLength(fieldOrder);
if (len < 16 || len < minLen || len > 1024)
throw new Error(`expected ${minLen}-1024 bytes of input, got ${len}`);
const num = isLE2 ? bytesToNumberBE(key) : bytesToNumberLE(key);
const reduced = mod$1(num, fieldOrder - _1n$8) + _1n$8;
return isLE2 ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
}
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const _0n$5 = BigInt(0);
const _1n$7 = BigInt(1);
const pointPrecomputes = /* @__PURE__ */ new WeakMap();
const pointWindowSizes = /* @__PURE__ */ new WeakMap();
function wNAF(c, bits) {
const constTimeNegate = (condition, item) => {
const neg = item.negate();
return condition ? neg : item;
};
const validateW = (W) => {
if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
throw new Error(`Wrong window size=${W}, should be [1..${bits}]`);
};
const opts = (W) => {
validateW(W);
const windows = Math.ceil(bits / W) + 1;
const windowSize = 2 ** (W - 1);
return { windows, windowSize };
};
return {
constTimeNegate,
// non-const time multiplication ladder
unsafeLadder(elm, n) {
let p = c.ZERO;
let d = elm;
while (n > _0n$5) {
if (n & _1n$7)
p = p.add(d);
d = d.double();
n >>= _1n$7;
}
return p;
},
/**
* Creates a wNAF precomputation window. Used for caching.
* Default window size is set by `utils.precompute()` and is equal to 8.
* Number of precomputed points depends on the curve size:
* 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
* - 𝑊 is the window size
* - 𝑛 is the bitlength of the curve order.
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
* @returns precomputed point tables flattened to a single array
*/
precomputeWindow(elm, W) {
const { windows, windowSize } = opts(W);
const points = [];
let p = elm;
let base = p;
for (let window2 = 0; window2 < windows; window2++) {
base = p;
points.push(base);
for (let i = 1; i < windowSize; i++) {
base = base.add(p);
points.push(base);
}
p = base.double();
}
return points;
},
/**
* Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
* @param W window size
* @param precomputes precomputed tables
* @param n scalar (we don't check here, but should be less than curve order)
* @returns real and fake (for const-time) points
*/
wNAF(W, precomputes, n) {
const { windows, windowSize } = opts(W);
let p = c.ZERO;
let f2 = c.BASE;
const mask = BigInt(2 ** W - 1);
const maxNumber = 2 ** W;
const shiftBy = BigInt(W);
for (let window2 = 0; window2 < windows; window2++) {
const offset = window2 * windowSize;
let wbits = Number(n & mask);
n >>= shiftBy;
if (wbits > windowSize) {
wbits -= maxNumber;
n += _1n$7;
}
const offset1 = offset;
const offset2 = offset + Math.abs(wbits) - 1;
const cond1 = window2 % 2 !== 0;
const cond2 = wbits < 0;
if (wbits === 0) {
f2 = f2.add(constTimeNegate(cond1, precomputes[offset1]));
} else {
p = p.add(constTimeNegate(cond2, precomputes[offset2]));
}
}
return { p, f: f2 };
},
wNAFCached(P, n, transform) {
const W = pointWindowSizes.get(P) || 1;
let comp = pointPrecomputes.get(P);
if (!comp) {
comp = this.precomputeWindow(P, W);
if (W !== 1)
pointPrecomputes.set(P, transform(comp));
}
return this.wNAF(W, comp, n);
},
// We calculate precomputes for elliptic curve point multiplication
// using windowed method. This specifies window size and
// stores precomputed values. Usually only base point would be precomputed.
setWindowSize(P, W) {
validateW(W);
pointWindowSizes.set(P, W);
pointPrecomputes.delete(P);
}
};
}
function pippenger(c, field, points, scalars) {
if (!Array.isArray(points) || !Array.isArray(scalars) || scalars.length !== points.length)
throw new Error("arrays of points and scalars must have equal length");
scalars.forEach((s, i) => {
if (!field.isValid(s))
throw new Error(`wrong scalar at index ${i}`);
});
points.forEach((p, i) => {
if (!(p instanceof c))
throw new Error(`wrong point at index ${i}`);
});
const wbits = bitLen(BigInt(points.length));
const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1;
const MASK = (1 << windowSize) - 1;
const buckets = new Array(MASK + 1).fill(c.ZERO);
const lastBits = Math.floor((field.BITS - 1) / windowSize) * windowSize;
let sum = c.ZERO;
for (let i = lastBits; i >= 0; i -= windowSize) {
buckets.fill(c.ZERO);
for (let j = 0; j < scalars.length; j++) {
const scalar = scalars[j];
const wbits2 = Number(scalar >> BigInt(i) & BigInt(MASK));
buckets[wbits2] = buckets[wbits2].add(points[j]);
}
let resI = c.ZERO;
for (let j = buckets.length - 1, sumI = c.ZERO; j > 0; j--) {
sumI = sumI.add(buckets[j]);
resI = resI.add(sumI);
}
sum = sum.add(resI);
if (i !== 0)
for (let j = 0; j < windowSize; j++)
sum = sum.double();
}
return sum;
}
function validateBasic(curve) {
validateField(curve.Fp);
validateObject(curve, {
n: "bigint",
h: "bigint",
Gx: "field",
Gy: "field"
}, {
nBitLength: "isSafeInteger",
nByteLength: "isSafeInteger"
});
return Object.freeze({
...nLength(curve.n, curve.nBitLength),
...curve,
...{ p: curve.Fp.ORDER }
});
}
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
function validateSigVerOpts(opts) {
if (opts.lowS !== void 0)
abool("lowS", opts.lowS);
if (opts.prehash !== void 0)
abool("prehash", opts.prehash);
}
function validatePointOpts(curve) {
const opts = validateBasic(curve);
validateObject(opts, {
a: "field",
b: "field"
}, {
allowedPrivateKeyLengths: "array",
wrapPrivateKey: "boolean",
isTorsionFree: "function",
clearCofactor: "function",
allowInfinityPoint: "boolean",
fromBytes: "function",
toBytes: "function"
});
const { endo, Fp: Fp3, a } = opts;
if (endo) {
if (!Fp3.eql(a, Fp3.ZERO)) {
throw new Error("Endomorphism can only be defined for Koblitz curves that have a=0");
}
if (typeof endo !== "object" || typeof endo.beta !== "bigint" || typeof endo.splitScalar !== "function") {
throw new Error("Expected endomorphism with beta: bigint and splitScalar: function");
}
}
return Object.freeze({ ...opts });
}
const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
const DER = {
// asn.1 DER encoding utils
Err: class DERErr extends Error {
constructor(m = "") {
super(m);
}
},
// Basic building block is TLV (Tag-Length-Value)
_tlv: {
encode: (tag, data) => {
const { Err: E } = DER;
if (tag < 0 || tag > 256)
throw new E("tlv.encode: wrong tag");
if (data.length & 1)
throw new E("tlv.encode: unpadded data");
const dataLen = data.length / 2;
const len = numberToHexUnpadded(dataLen);
if (len.length / 2 & 128)
throw new E("tlv.encode: long form length too big");
const lenLen = dataLen > 127 ? numberToHexUnpadded(len.length / 2 | 128) : "";
return `${numberToHexUnpadded(tag)}${lenLen}${len}${data}`;
},
// v - value, l - left bytes (unparsed)
decode(tag, data) {
const { Err: E } = DER;
let pos = 0;
if (tag < 0 || tag > 256)
throw new E("tlv.encode: wrong tag");
if (data.length < 2 || data[pos++] !== tag)
throw new E("tlv.decode: wrong tlv");
const first = data[pos++];
const isLong = !!(first & 128);
let length = 0;
if (!isLong)
length = first;
else {
const lenLen = first & 127;
if (!lenLen)
throw new E("tlv.decode(long): indefinite length not supported");
if (lenLen > 4)
throw new E("tlv.decode(long): byte length is too big");
const lengthBytes = data.subarray(pos, pos + lenLen);
if (lengthBytes.length !== lenLen)
throw new E("tlv.decode: length bytes not complete");
if (lengthBytes[0] === 0)
throw new E("tlv.decode(long): zero leftmost byte");
for (const b of lengthBytes)
length = length << 8 | b;
pos += lenLen;
if (length < 128)
throw new E("tlv.decode(long): not minimal encoding");
}
const v = data.subarray(pos, pos + length);
if (v.length !== length)
throw new E("tlv.decode: wrong value length");
return { v, l: data.subarray(pos + length) };
}
},
// https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
// since we always use positive integers here. It must always be empty:
// - add zero byte if exists
// - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
_int: {
encode(num) {
const { Err: E } = DER;
if (num < _0n$4)
throw new E("integer: negative integers are not allowed");
let hex = numberToHexUnpadded(num);
if (Number.parseInt(hex[0], 16) & 8)
hex = "00" + hex;
if (hex.length & 1)
throw new E("unexpected assertion");
return hex;
},
decode(data) {
const { Err: E } = DER;
if (data[0] & 128)
throw new E("Invalid signature integer: negative");
if (data[0] === 0 && !(data[1] & 128))
throw new E("Invalid signature integer: unnecessary leading zero");
return b2n(data);
}
},
toSig(hex) {
const { Err: E, _int: int, _tlv: tlv } = DER;
const data = typeof hex === "string" ? h2b(hex) : hex;
abytes(data);
const { v: seqBytes, l: seqLeftBytes } = tlv.decode(48, data);
if (seqLeftBytes.length)
throw new E("Invalid signature: left bytes after parsing");
const { v: rBytes, l: rLeftBytes } = tlv.decode(2, seqBytes);
const { v: sBytes, l: sLeftBytes } = tlv.decode(2, rLeftBytes);
if (sLeftBytes.length)
throw new E("Invalid signature: left bytes after parsing");
return { r: int.decode(rBytes), s: int.decode(sBytes) };
},
hexFromSig(sig) {
const { _tlv: tlv, _int: int } = DER;
const seq = `${tlv.encode(2, int.encode(sig.r))}${tlv.encode(2, int.encode(sig.s))}`;
return tlv.encode(48, seq);
}
};
const _0n$4 = BigInt(0), _1n$6 = BigInt(1), _2n$6 = BigInt(2), _3n$4 = BigInt(3), _4n$1 = BigInt(4);
function weierstrassPoints(opts) {
const CURVE = validatePointOpts(opts);
const { Fp: Fp3 } = CURVE;
const Fn = Field(CURVE.n, CURVE.nBitLength);
const toBytes2 = CURVE.toBytes || ((_c, point, _isCompressed) => {
const a = point.toAffine();
return concatBytes$2(Uint8Array.from([4]), Fp3.toBytes(a.x), Fp3.toBytes(a.y));
});
const fromBytes = CURVE.fromBytes || ((bytes2) => {
const tail = bytes2.subarray(1);
const x = Fp3.fromBytes(tail.subarray(0, Fp3.BYTES));
const y = Fp3.fromBytes(tail.subarray(Fp3.BYTES, 2 * Fp3.BYTES));
return { x, y };
});
function weierstrassEquation(x) {
const { a, b } = CURVE;
const x2 = Fp3.sqr(x);
const x3 = Fp3.mul(x2, x);
return Fp3.add(Fp3.add(x3, Fp3.mul(x, a)), b);
}
if (!Fp3.eql(Fp3.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
throw new Error("bad generator point: equation left != right");
function isWithinCurveOrder(num) {
return inRange(num, _1n$6, CURVE.n);
}
function normPrivateKeyToScalar(key) {
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N2 } = CURVE;
if (lengths && typeof key !== "bigint") {
if (isBytes(key))
key = bytesToHex$2(key);
if (typeof key !== "string" || !lengths.includes(key.length))
throw new Error("Invalid key");
key = key.padStart(nByteLength * 2, "0");
}
let num;
try {
num = typeof key === "bigint" ? key : bytesToNumberBE(ensureBytes("private key", key, nByteLength));
} catch (error) {
throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
}
if (wrapPrivateKey)
num = mod$1(num, N2);
aInRange("private key", num, _1n$6, N2);
return num;
}
function assertPrjPoint(other) {
if (!(other instanceof Point))
throw new Error("ProjectivePoint expected");
}
const toAffineMemo = memoized((p, iz) => {
const { px: x, py: y, pz: z } = p;
if (Fp3.eql(z, Fp3.ONE))
return { x, y };
const is0 = p.is0();
if (iz == null)
iz = is0 ? Fp3.ONE : Fp3.inv(z);
const ax = Fp3.mul(x, iz);
const ay = Fp3.mul(y, iz);
const zz = Fp3.mul(z, iz);
if (is0)
return { x: Fp3.ZERO, y: Fp3.ZERO };
if (!Fp3.eql(zz, Fp3.ONE))
throw new Error("invZ was invalid");
return { x: ax, y: ay };
});
const assertValidMemo = memoized((p) => {
if (p.is0()) {
if (CURVE.allowInfinityPoint && !Fp3.is0(p.py))
return;
throw new Error("bad point: ZERO");
}
const { x, y } = p.toAffine();
if (!Fp3.isValid(x) || !Fp3.isValid(y))
throw new Error("bad point: x or y not FE");
const left = Fp3.sqr(y);
const right = weierstrassEquation(x);
if (!Fp3.eql(left, right))
throw new Error("bad point: equation left != right");
if (!p.isTorsionFree())
throw new Error("bad point: not in prime-order subgroup");
return true;
});
class Point {
constructor(px, py, pz) {
this.px = px;
this.py = py;
this.pz = pz;
if (px == null || !Fp3.isValid(px))
throw new Error("x required");
if (py == null || !Fp3.isValid(py))
throw new Error("y required");
if (pz == null || !Fp3.isValid(pz))
throw new Error("z required");
Object.freeze(this);
}
// Does not validate if the point is on-curve.
// Use fromHex instead, or call assertValidity() later.
static fromAffine(p) {
const { x, y } = p || {};
if (!p || !Fp3.isValid(x) || !Fp3.isValid(y))
throw new Error("invalid affine point");
if (p instanceof Point)
throw new Error("projective point not allowed");
const is0 = (i) => Fp3.eql(i, Fp3.ZERO);
if (is0(x) && is0(y))
return Point.ZERO;
return new Point(x, y, Fp3.ONE);
}
get x() {
return this.toAffine().x;
}
get y() {
return this.toAffine().y;
}
/**
* Takes a bunch of Projective Points but executes only one
* inversion on all of them. Inversion is very slow operation,
* so this improves performance massively.
* Optimization: converts a list of projective points to a list of identical points with Z=1.
*/
static normalizeZ(points) {
const toInv = Fp3.invertBatch(points.map((p) => p.pz));
return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
}
/**
* Converts hash string or Uint8Array to Point.
* @param hex short/long ECDSA hex
*/
static fromHex(hex) {
const P = Point.fromAffine(fromBytes(ensureBytes("pointHex", hex)));
P.assertValidity();
return P;
}
// Multiplies generator point by privateKey.
static fromPrivateKey(privateKey) {
return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
}
// Multiscalar Multiplication
static msm(points, scalars) {
return pippenger(Point, Fn, points, scalars);
}
// "Private method", don't use it directly
_setWindowSize(windowSize) {
wnaf.setWindowSize(this, windowSize);
}
// A point on curve is valid if it conforms to equation.
assertValidity() {
assertValidMemo(this);
}
hasEvenY() {
const { y } = this.toAffine();
if (Fp3.isOdd)
return !Fp3.isOdd(y);
throw new Error("Field doesn't support isOdd");
}
/**
* Compare one point to another.
*/
equals(other) {
assertPrjPoint(other);
const { px: X1, py: Y1, pz: Z1 } = this;
const { px: X2, py: Y2, pz: Z2 } = other;
const U1 = Fp3.eql(Fp3.mul(X1, Z2), Fp3.mul(X2, Z1));
const U2 = Fp3.eql(Fp3.mul(Y1, Z2), Fp3.mul(Y2, Z1));
return U1 && U2;
}
/**
* Flips point to one corresponding to (x, -y) in Affine coordinates.
*/
negate() {
return new Point(this.px, Fp3.neg(this.py), this.pz);
}
// Renes-Costello-Batina exception-free doubling formula.
// There is 30% faster Jacobian formula, but it is not complete.
// https://eprint.iacr.org/2015/1060, algorithm 3
// Cost: 8M + 3S + 3*a + 2*b3 + 15add.
double() {
const { a, b } = CURVE;
const b3 = Fp3.mul(b, _3n$4);
const { px: X1, py: Y1, pz: Z1 } = this;
let X3 = Fp3.ZERO, Y3 = Fp3.ZERO, Z3 = Fp3.ZERO;
let t0 = Fp3.mul(X1, X1);
let t1 = Fp3.mul(Y1, Y1);
let t2 = Fp3.mul(Z1, Z1);
let t3 = Fp3.mul(X1, Y1);
t3 = Fp3.add(t3, t3);
Z3 = Fp3.mul(X1, Z1);
Z3 = Fp3.add(Z3, Z3);
X3 = Fp3.mul(a, Z3);
Y3 = Fp3.mul(b3, t2);
Y3 = Fp3.add(X3, Y3);
X3 = Fp3.sub(t1, Y3);
Y3 = Fp3.add(t1, Y3);
Y3 = Fp3.mul(X3, Y3);
X3 = Fp3.mul(t3, X3);
Z3 = Fp3.mul(b3, Z3);
t2 = Fp3.mul(a, t2);
t3 = Fp3.sub(t0, t2);
t3 = Fp3.mul(a, t3);
t3 = Fp3.add(t3, Z3);
Z3 = Fp3.add(t0, t0);
t0 = Fp3.add(Z3, t0);
t0 = Fp3.add(t0, t2);
t0 = Fp3.mul(t0, t3);
Y3 = Fp3.add(Y3, t0);
t2 = Fp3.mul(Y1, Z1);
t2 = Fp3.add(t2, t2);
t0 = Fp3.mul(t2, t3);
X3 = Fp3.sub(X3, t0);
Z3 = Fp3.mul(t2, t1);
Z3 = Fp3.add(Z3, Z3);
Z3 = Fp3.add(Z3, Z3);
return new Point(X3, Y3, Z3);
}
// Renes-Costello-Batina exception-free addition formula.
// There is 30% faster Jacobian formula, but it is not complete.
// https://eprint.iacr.org/2015/1060, algorithm 1
// Cost: 12M + 0S + 3*a + 3*b3 + 23add.
add(other) {
assertPrjPoint(other);
const { px: X1, py: Y1, pz: Z1 } = this;
const { px: X2, py: Y2, pz: Z2 } = other;
let X3 = Fp3.ZERO, Y3 = Fp3.ZERO, Z3 = Fp3.ZERO;
const a = CURVE.a;
const b3 = Fp3.mul(CURVE.b, _3n$4);
let t0 = Fp3.mul(X1, X2);
let t1 = Fp3.mul(Y1, Y2);
let t2 = Fp3.mul(Z1, Z2);
let t3 = Fp3.add(X1, Y1);
let t4 = Fp3.add(X2, Y2);
t3 = Fp3.mul(t3, t4);
t4 = Fp3.add(t0, t1);
t3 = Fp3.sub(t3, t4);
t4 = Fp3.add(X1, Z1);
let t5 = Fp3.add(X2, Z2);
t4 = Fp3.mul(t4, t5);
t5 = Fp3.add(t0, t2);
t4 = Fp3.sub(t4, t5);
t5 = Fp3.add(Y1, Z1);
X3 = Fp3.add(Y2, Z2);
t5 = Fp3.mul(t5, X3);
X3 = Fp3.add(t1, t2);
t5 = Fp3.sub(t5, X3);
Z3 = Fp3.mul(a, t4);
X3 = Fp3.mul(b3, t2);
Z3 = Fp3.add(X3, Z3);
X3 = Fp3.sub(t1, Z3);
Z3 = Fp3.add(t1, Z3);
Y3 = Fp3.mul(X3, Z3);
t1 = Fp3.add(t0, t0);
t1 = Fp3.add(t1, t0);
t2 = Fp3.mul(a, t2);
t4 = Fp3.mul(b3, t4);
t1 = Fp3.add(t1, t2);
t2 = Fp3.sub(t0, t2);
t2 = Fp3.mul(a, t2);
t4 = Fp3.add(t4, t2);
t0 = Fp3.mul(t1, t4);
Y3 = Fp3.add(Y3, t0);
t0 = Fp3.mul(t5, t4);
X3 = Fp3.mul(t3, X3);
X3 = Fp3.sub(X3, t0);
t0 = Fp3.mul(t3, t1);
Z3 = Fp3.mul(t5, Z3);
Z3 = Fp3.add(Z3, t0);
return new Point(X3, Y3, Z3);
}
subtract(other) {
return this.add(other.negate());
}
is0() {
return this.equals(Point.ZERO);
}
wNAF(n) {
return wnaf.wNAFCached(this, n, Point.normalizeZ);
}
/**
* Non-constant-time multiplication. Uses double-and-add algorithm.
* It's faster, but should only be used when you don't care about
* an exposed private key e.g. sig verification, which works over *public* keys.
*/
multiplyUnsafe(sc) {
aInRange("scalar", sc, _0n$4, CURVE.n);
const I = Point.ZERO;
if (sc === _0n$4)
return I;
if (sc === _1n$6)
return this;
const { endo } = CURVE;
if (!endo)
return wnaf.unsafeLadder(this, sc);
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
let k1p = I;
let k2p = I;
let d = this;
while (k1 > _0n$4 || k2 > _0n$4) {
if (k1 & _1n$6)
k1p = k1p.add(d);
if (k2 & _1n$6)
k2p = k2p.add(d);
d = d.double();
k1 >>= _1n$6;
k2 >>= _1n$6;
}
if (k1neg)
k1p = k1p.negate();
if (k2neg)
k2p = k2p.negate();
k2p = new Point(Fp3.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
return k1p.add(k2p);
}
/**
* Constant time multiplication.
* Uses wNAF method. Windowed method may be 10% faster,
* but takes 2x longer to generate and consumes 2x memory.
* Uses precomputes when available.
* Uses endomorphism for Koblitz curves.
* @param scalar by which the point would be multiplied
* @returns New point
*/
multiply(scalar) {
const { endo, n: N2 } = CURVE;
aInRange("scalar", scalar, _1n$6, N2);
let point, fake;
if (endo) {
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar);
let { p: k1p, f: f1p } = this.wNAF(k1);
let { p: k2p, f: f2p } = this.wNAF(k2);
k1p = wnaf.constTimeNegate(k1neg, k1p);
k2p = wnaf.constTimeNegate(k2neg, k2p);
k2p = new Point(Fp3.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
point = k1p.add(k2p);
fake = f1p.add(f2p);
} else {
const { p, f: f2 } = this.wNAF(scalar);
point = p;
fake = f2;
}
return Point.normalizeZ([point, fake])[0];
}
/**
* Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.
* Not using Strauss-Shamir trick: precomputation tables are faster.
* The trick could be useful if both P and Q are not G (not in our case).
* @returns non-zero affine point
*/
multiplyAndAddUnsafe(Q, a, b) {
const G = Point.BASE;
const mul = (P, a2) => a2 === _0n$4 || a2 === _1n$6 || !P.equals(G) ? P.multiplyUnsafe(a2) : P.multiply(a2);
const sum = mul(this, a).add(mul(Q, b));
return sum.is0() ? void 0 : sum;
}
// Converts Projective point to affine (x, y) coordinates.
// Can accept precomputed Z^-1 - for example, from invertBatch.
// (x, y, z) ∋ (x=x/z, y=y/z)
toAffine(iz) {
return toAffineMemo(this, iz);
}
isTorsionFree() {
const { h: cofactor, isTorsionFree } = CURVE;
if (cofactor === _1n$6)
return true;
if (isTorsionFree)
return isTorsionFree(Point, this);
throw new Error("isTorsionFree() has not been declared for the elliptic curve");
}
clearCofactor() {
const { h: cofactor, clearCofactor } = CURVE;
if (cofactor === _1n$6)
return this;
if (clearCofactor)
return clearCofactor(Point, this);
return this.multiplyUnsafe(CURVE.h);
}
toRawBytes(isCompressed = true) {
abool("isCompressed", isCompressed);
this.assertValidity();
return toBytes2(Point, this, isCompressed);
}
toHex(isCompressed = true) {
abool("isCompressed", isCompressed);
return bytesToHex$2(this.toRawBytes(isCompressed));
}
}
Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp3.ONE);
Point.ZERO = new Point(Fp3.ZERO, Fp3.ONE, Fp3.ZERO);
const _bits = CURVE.nBitLength;
const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
return {
CURVE,
ProjectivePoint: Point,
normPrivateKeyToScalar,
weierstrassEquation,
isWithinCurveOrder
};
}
function validateOpts(curve) {
const opts = validateBasic(curve);
validateObject(opts, {
hash: "hash",
hmac: "function",
randomBytes: "function"
}, {
bits2int: "function",
bits2int_modN: "function",
lowS: "boolean"
});
return Object.freeze({ lowS: true, ...opts });
}
function weierstrass(curveDef) {
const CURVE = validateOpts(curveDef);
const { Fp: Fp3, n: CURVE_ORDER } = CURVE;
const compressedLen = Fp3.BYTES + 1;
const uncompressedLen = 2 * Fp3.BYTES + 1;
function modN(a) {
return mod$1(a, CURVE_ORDER);
}
function invN(a) {
return invert(a, CURVE_ORDER);
}
const { ProjectivePoint: Point, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder } = weierstrassPoints({
...CURVE,
toBytes(_c, point, isCompressed) {
const a = point.toAffine();
const x = Fp3.toBytes(a.x);
const cat = concatBytes$2;
abool("isCompressed", isCompressed);
if (isCompressed) {
return cat(Uint8Array.from([point.hasEvenY() ? 2 : 3]), x);
} else {
return cat(Uint8Array.from([4]), x, Fp3.toBytes(a.y));
}
},
fromBytes(bytes2) {
const len = bytes2.length;
const head = bytes2[0];
const tail = bytes2.subarray(1);
if (len === compressedLen && (head === 2 || head === 3)) {
const x = bytesToNumberBE(tail);
if (!inRange(x, _1n$6, Fp3.ORDER))
throw new Error("Point is not on curve");
const y2 = weierstrassEquation(x);
let y;
try {
y = Fp3.sqrt(y2);
} catch (sqrtError) {
const suffix = sqrtError instanceof Error ? ": " + sqrtError.message : "";
throw new Error("Point is not on curve" + suffix);
}
const isYOdd = (y & _1n$6) === _1n$6;
const isHeadOdd = (head & 1) === 1;
if (isHeadOdd !== isYOdd)
y = Fp3.neg(y);
return { x, y };
} else if (len === uncompressedLen && head === 4) {
const x = Fp3.fromBytes(tail.subarray(0, Fp3.BYTES));
const y = Fp3.fromBytes(tail.subarray(Fp3.BYTES, 2 * Fp3.BYTES));
return { x, y };
} else {
throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);
}
}
});
const numToNByteStr = (num) => bytesToHex$2(numberToBytesBE(num, CURVE.nByteLength));
function isBiggerThanHalfOrder(number2) {
const HALF = CURVE_ORDER >> _1n$6;
return number2 > HALF;
}
function normalizeS(s) {
return isBiggerThanHalfOrder(s) ? modN(-s) : s;
}
const slcNum = (b, from, to) => bytesToNumberBE(b.slice(from, to));
class Signature {
constructor(r, s, recovery) {
this.r = r;
this.s = s;
this.recovery = recovery;
this.assertValidity();
}
// pair (bytes of r, bytes of s)
static fromCompact(hex) {
const l = CURVE.nByteLength;
hex = ensureBytes("compactSignature", hex, l * 2);
return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l));
}
// DER encoded ECDSA signature
// https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
static fromDER(hex) {
const { r, s } = DER.toSig(ensureBytes("DER", hex));
return new Signature(r, s);
}
assertValidity() {
aInRange("r", this.r, _1n$6, CURVE_ORDER);
aInRange("s", this.s, _1n$6, CURVE_ORDER);
}
addRecoveryBit(recovery) {
return new Signature(this.r, this.s, recovery);
}
recoverPublicKey(msgHash) {
const { r, s, recovery: rec } = this;
const h = bits2int_modN(ensureBytes("msgHash", msgHash));
if (rec == null || ![0, 1, 2, 3].includes(rec))
throw new Error("recovery id invalid");
const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
if (radj >= Fp3.ORDER)
throw new Error("recovery id 2 or 3 invalid");
const prefix = (rec & 1) === 0 ? "02" : "03";
const R2 = Point.fromHex(prefix + numToNByteStr(radj));
const ir = invN(radj);
const u1 = modN(-h * ir);
const u2 = modN(s * ir);
const Q = Point.BASE.multiplyAndAddUnsafe(R2, u1, u2);
if (!Q)
throw new Error("point at infinify");
Q.assertValidity();
return Q;
}
// Signatures should be low-s, to prevent malleability.
hasHighS() {
return isBiggerThanHalfOrder(this.s);
}
normalizeS() {
return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this;
}
// DER-encoded
toDERRawBytes() {
return hexToBytes$3(this.toDERHex());
}
toDERHex() {
return DER.hexFromSig({ r: this.r, s: this.s });
}
// padded bytes of r, then padded bytes of s
toCompactRawBytes() {
return hexToBytes$3(this.toCompactHex());
}
toCompactHex() {
return numToNByteStr(this.r) + numToNByteStr(this.s);
}
}
const utils = {
isValidPrivateKey(privateKey) {
try {
normPrivateKeyToScalar(privateKey);
return true;
} catch (error) {
return false;
}
},
normPrivateKeyToScalar,
/**
* Produces cryptographically secure private key from random of size
* (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
*/
randomPrivateKey: () => {
const length = getMinHashLength(CURVE.n);
return mapHashToField(CURVE.randomBytes(length), CURVE.n);
},
/**
* Creates precompute table for an arbitrary EC point. Makes point "cached".
* Allows to massively speed-up `point.multiply(scalar)`.
* @returns cached point
* @example
* const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey));
* fast.multiply(privKey); // much faster ECDH now
*/
precompute(windowSize = 8, point = Point.BASE) {
point._setWindowSize(windowSize);
point.multiply(BigInt(3));
return point;
}
};
function getPublicKey(privateKey, isCompressed = true) {
return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed);
}
function isProbPub(item) {
const arr = isBytes(item);
const str = typeof item === "string";
const len = (arr || str) && item.length;
if (arr)
return len === compressedLen || len === uncompressedLen;
if (str)
return len === 2 * compressedLen || len === 2 * uncompressedLen;
if (item instanceof Point)
return true;
return false;
}
function getSharedSecret(privateA, publicB, isCompressed = true) {
if (isProbPub(privateA))
throw new Error("first arg must be private key");
if (!isProbPub(publicB))
throw new Error("second arg must be public key");
const b = Point.fromHex(publicB);
return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);
}
const bits2int = CURVE.bits2int || function(bytes2) {
const num = bytesToNumberBE(bytes2);
const delta = bytes2.length * 8 - CURVE.nBitLength;
return delta > 0 ? num >> BigInt(delta) : num;
};
const bits2int_modN = CURVE.bits2int_modN || function(bytes2) {
return modN(bits2int(bytes2));
};
const ORDER_MASK = bitMask(CURVE.nBitLength);
function int2octets(num) {
aInRange(`num < 2^${CURVE.nBitLength}`, num, _0n$4, ORDER_MASK);
return numberToBytesBE(num, CURVE.nByteLength);
}
function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
if (["recovered", "canonical"].some((k) => k in opts))
throw new Error("sign() legacy options not supported");
const { hash: hash2, randomBytes: randomBytes2 } = CURVE;
let { lowS, prehash, extraEntropy: ent } = opts;
if (lowS == null)
lowS = true;
msgHash = ensureBytes("msgHash", msgHash);
validateSigVerOpts(opts);
if (prehash)
msgHash = ensureBytes("prehashed msgHash", hash2(msgHash));
const h1int = bits2int_modN(msgHash);
const d = normPrivateKeyToScalar(privateKey);
const seedArgs = [int2octets(d), int2octets(h1int)];
if (ent != null && ent !== false) {
const e = ent === true ? randomBytes2(Fp3.BYTES) : ent;
seedArgs.push(ensureBytes("extraEntropy", e));
}
const seed = concatBytes$2(...seedArgs);
const m = h1int;
function k2sig(kBytes) {
const k = bits2int(kBytes);
if (!isWithinCurveOrder(k))
return;
const ik = invN(k);
const q = Point.BASE.multiply(k).toAffine();
const r = modN(q.x);
if (r === _0n$4)
return;
const s = modN(ik * modN(m + r * d));
if (s === _0n$4)
return;
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n$6);
let normS = s;
if (lowS && isBiggerThanHalfOrder(s)) {
normS = normalizeS(s);
recovery ^= 1;
}
return new Signature(r, normS, recovery);
}
return { seed, k2sig };
}
const defaultSigOpts = { lowS: CURVE.lowS, prehash: false };
const defaultVerOpts = { lowS: CURVE.lowS, prehash: false };
function sign(msgHash, privKey, opts = defaultSigOpts) {
const { seed, k2sig } = prepSig(msgHash, privKey, opts);
const C = CURVE;
const drbg = createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac);
return drbg(seed, k2sig);
}
Point.BASE._setWindowSize(8);
function verify(signature, msgHash, publicKey, opts = defaultVerOpts) {
var _a;
const sg = signature;
msgHash = ensureBytes("msgHash", msgHash);
publicKey = ensureBytes("publicKey", publicKey);
if ("strict" in opts)
throw new Error("options.strict was renamed to lowS");
validateSigVerOpts(opts);
const { lowS, prehash } = opts;
let _sig = void 0;
let P;
try {
if (typeof sg === "string" || isBytes(sg)) {
try {
_sig = Signature.fromDER(sg);
} catch (derError) {
if (!(derError instanceof DER.Err))
throw derError;
_sig = Signature.fromCompact(sg);
}
} else if (typeof sg === "object" && typeof sg.r === "bigint" && typeof sg.s === "bigint") {
const { r: r2, s: s2 } = sg;
_sig = new Signature(r2, s2);
} else {
throw new Error("PARSE");
}
P = Point.fromHex(publicKey);
} catch (error) {
if (error.message === "PARSE")
throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
return false;
}
if (lowS && _sig.hasHighS())
return false;
if (prehash)
msgHash = CURVE.hash(msgHash);
const { r, s } = _sig;
const h = bits2int_modN(msgHash);
const is = invN(s);
const u1 = modN(h * is);
const u2 = modN(r * is);
const R2 = (_a = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)) == null ? void 0 : _a.toAffine();
if (!R2)
return false;
const v = modN(R2.x);
return v === r;
}
return {
CURVE,
getPublicKey,
getSharedSecret,
sign,
verify,
ProjectivePoint: Point,
Signature,
utils
};
}
function SWUFpSqrtRatio(Fp3, Z) {
const q = Fp3.ORDER;
let l = _0n$4;
for (let o = q - _1n$6; o % _2n$6 === _0n$4; o /= _2n$6)
l += _1n$6;
const c1 = l;
const _2n_pow_c1_1 = _2n$6 << c1 - _1n$6 - _1n$6;
const _2n_pow_c1 = _2n_pow_c1_1 * _2n$6;
const c2 = (q - _1n$6) / _2n_pow_c1;
const c3 = (c2 - _1n$6) / _2n$6;
const c4 = _2n_pow_c1 - _1n$6;
const c5 = _2n_pow_c1_1;
const c6 = Fp3.pow(Z, c2);
const c7 = Fp3.pow(Z, (c2 + _1n$6) / _2n$6);
let sqrtRatio = (u, v) => {
let tv1 = c6;
let tv2 = Fp3.pow(v, c4);
let tv3 = Fp3.sqr(tv2);
tv3 = Fp3.mul(tv3, v);
let tv5 = Fp3.mul(u, tv3);
tv5 = Fp3.pow(tv5, c3);
tv5 = Fp3.mul(tv5, tv2);
tv2 = Fp3.mul(tv5, v);
tv3 = Fp3.mul(tv5, u);
let tv4 = Fp3.mul(tv3, tv2);
tv5 = Fp3.pow(tv4, c5);
let isQR = Fp3.eql(tv5, Fp3.ONE);
tv2 = Fp3.mul(tv3, c7);
tv5 = Fp3.mul(tv4, tv1);
tv3 = Fp3.cmov(tv2, tv3, isQR);
tv4 = Fp3.cmov(tv5, tv4, isQR);
for (let i = c1; i > _1n$6; i--) {
let tv52 = i - _2n$6;
tv52 = _2n$6 << tv52 - _1n$6;
let tvv5 = Fp3.pow(tv4, tv52);
const e1 = Fp3.eql(tvv5, Fp3.ONE);
tv2 = Fp3.mul(tv3, tv1);
tv1 = Fp3.mul(tv1, tv1);
tvv5 = Fp3.mul(tv4, tv1);
tv3 = Fp3.cmov(tv2, tv3, e1);
tv4 = Fp3.cmov(tvv5, tv4, e1);
}
return { isValid: isQR, value: tv3 };
};
if (Fp3.ORDER % _4n$1 === _3n$4) {
const c12 = (Fp3.ORDER - _3n$4) / _4n$1;
const c22 = Fp3.sqrt(Fp3.neg(Z));
sqrtRatio = (u, v) => {
let tv1 = Fp3.sqr(v);
const tv2 = Fp3.mul(u, v);
tv1 = Fp3.mul(tv1, tv2);
let y1 = Fp3.pow(tv1, c12);
y1 = Fp3.mul(y1, tv2);
const y2 = Fp3.mul(y1, c22);
const tv3 = Fp3.mul(Fp3.sqr(y1), v);
const isQR = Fp3.eql(tv3, u);
let y = Fp3.cmov(y2, y1, isQR);
return { isValid: isQR, value: y };
};
}
return sqrtRatio;
}
function mapToCurveSimpleSWU(Fp3, opts) {
validateField(Fp3);
if (!Fp3.isValid(opts.A) || !Fp3.isValid(opts.B) || !Fp3.isValid(opts.Z))
throw new Error("mapToCurveSimpleSWU: invalid opts");
const sqrtRatio = SWUFpSqrtRatio(Fp3, opts.Z);
if (!Fp3.isOdd)
throw new Error("Fp.isOdd is not implemented!");
return (u) => {
let tv1, tv2, tv3, tv4, tv5, tv6, x, y;
tv1 = Fp3.sqr(u);
tv1 = Fp3.mul(tv1, opts.Z);
tv2 = Fp3.sqr(tv1);
tv2 = Fp3.add(tv2, tv1);
tv3 = Fp3.add(tv2, Fp3.ONE);
tv3 = Fp3.mul(tv3, opts.B);
tv4 = Fp3.cmov(opts.Z, Fp3.neg(tv2), !Fp3.eql(tv2, Fp3.ZERO));
tv4 = Fp3.mul(tv4, opts.A);
tv2 = Fp3.sqr(tv3);
tv6 = Fp3.sqr(tv4);
tv5 = Fp3.mul(tv6, opts.A);
tv2 = Fp3.add(tv2, tv5);
tv2 = Fp3.mul(tv2, tv3);
tv6 = Fp3.mul(tv6, tv4);
tv5 = Fp3.mul(tv6, opts.B);
tv2 = Fp3.add(tv2, tv5);
x = Fp3.mul(tv1, tv3);
const { isValid, value } = sqrtRatio(tv2, tv6);
y = Fp3.mul(tv1, u);
y = Fp3.mul(y, value);
x = Fp3.cmov(x, tv3, isValid);
y = Fp3.cmov(y, value, isValid);
const e1 = Fp3.isOdd(u) === Fp3.isOdd(y);
y = Fp3.cmov(Fp3.neg(y), y, e1);
x = Fp3.div(x, tv4);
return { x, y };
};
}
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
function getHash(hash2) {
return {
hash: hash2,
hmac: (key, ...msgs) => hmac(hash2, key, concatBytes$3(...msgs)),
randomBytes
};
}
function createCurve(curveDef, defHash) {
const create = (hash2) => weierstrass({ ...curveDef, ...getHash(hash2) });
return Object.freeze({ ...create(defHash), create });
}
const os2ip = bytesToNumberBE;
function i2osp(value, length) {
anum(value);
anum(length);
if (value < 0 || value >= 1 << 8 * length) {
throw new Error(`bad I2OSP call: value=${value} length=${length}`);
}
const res = Array.from({ length }).fill(0);
for (let i = length - 1; i >= 0; i--) {
res[i] = value & 255;
value >>>= 8;
}
return new Uint8Array(res);
}
function strxor(a, b) {
const arr = new Uint8Array(a.length);
for (let i = 0; i < a.length; i++) {
arr[i] = a[i] ^ b[i];
}
return arr;
}
function anum(item) {
if (!Number.isSafeInteger(item))
throw new Error("number expected");
}
function expand_message_xmd(msg, DST, lenInBytes, H) {
abytes(msg);
abytes(DST);
anum(lenInBytes);
if (DST.length > 255)
DST = H(concatBytes$2(utf8ToBytes$1("H2C-OVERSIZE-DST-"), DST));
const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;
const ell = Math.ceil(lenInBytes / b_in_bytes);
if (lenInBytes > 65535 || ell > 255)
throw new Error("expand_message_xmd: invalid lenInBytes");
const DST_prime = concatBytes$2(DST, i2osp(DST.length, 1));
const Z_pad = i2osp(0, r_in_bytes);
const l_i_b_str = i2osp(lenInBytes, 2);
const b = new Array(ell);
const b_0 = H(concatBytes$2(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime));
b[0] = H(concatBytes$2(b_0, i2osp(1, 1), DST_prime));
for (let i = 1; i <= ell; i++) {
const args = [strxor(b_0, b[i - 1]), i2osp(i + 1, 1), DST_prime];
b[i] = H(concatBytes$2(...args));
}
const pseudo_random_bytes = concatBytes$2(...b);
return pseudo_random_bytes.slice(0, lenInBytes);
}
function expand_message_xof(msg, DST, lenInBytes, k, H) {
abytes(msg);
abytes(DST);
anum(lenInBytes);
if (DST.length > 255) {
const dkLen = Math.ceil(2 * k / 8);
DST = H.create({ dkLen }).update(utf8ToBytes$1("H2C-OVERSIZE-DST-")).update(DST).digest();
}
if (lenInBytes > 65535 || DST.length > 255)
throw new Error("expand_message_xof: invalid lenInBytes");
return H.create({ dkLen: lenInBytes }).update(msg).update(i2osp(lenInBytes, 2)).update(DST).update(i2osp(DST.length, 1)).digest();
}
function hash_to_field(msg, count, options) {
validateObject(options, {
DST: "stringOrUint8Array",
p: "bigint",
m: "isSafeInteger",
k: "isSafeInteger",
hash: "hash"
});
const { p, k, m, hash: hash2, expand, DST: _DST } = options;
abytes(msg);
anum(count);
const DST = typeof _DST === "string" ? utf8ToBytes$1(_DST) : _DST;
const log2p = p.toString(2).length;
const L = Math.ceil((log2p + k) / 8);
const len_in_bytes = count * m * L;
let prb;
if (expand === "xmd") {
prb = expand_message_xmd(msg, DST, len_in_bytes, hash2);
} else if (expand === "xof") {
prb = expand_message_xof(msg, DST, len_in_bytes, k, hash2);
} else if (expand === "_internal_pass") {
prb = msg;
} else {
throw new Error('expand must be "xmd" or "xof"');
}
const u = new Array(count);
for (let i = 0; i < count; i++) {
const e = new Array(m);
for (let j = 0; j < m; j++) {
const elm_offset = L * (j + i * m);
const tv = prb.subarray(elm_offset, elm_offset + L);
e[j] = mod$1(os2ip(tv), p);
}
u[i] = e;
}
return u;
}
function isogenyMap(field, map) {
const COEFF = map.map((i) => Array.from(i).reverse());
return (x, y) => {
const [xNum, xDen, yNum, yDen] = COEFF.map((val) => val.reduce((acc, i) => field.add(field.mul(acc, x), i)));
x = field.div(xNum, xDen);
y = field.mul(y, field.div(yNum, yDen));
return { x, y };
};
}
function createHasher(Point, mapToCurve, def) {
if (typeof mapToCurve !== "function")
throw new Error("mapToCurve() must be defined");
return {
// Encodes byte string to elliptic curve.
// hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3
hashToCurve(msg, options) {
const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options });
const u0 = Point.fromAffine(mapToCurve(u[0]));
const u1 = Point.fromAffine(mapToCurve(u[1]));
const P = u0.add(u1).clearCofactor();
P.assertValidity();
return P;
},
// Encodes byte string to elliptic curve.
// encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3
encodeToCurve(msg, options) {
const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options });
const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor();
P.assertValidity();
return P;
},
// Same as encodeToCurve, but without hash
mapToCurve(scalars) {
if (!Array.isArray(scalars))
throw new Error("mapToCurve: expected array of bigints");
for (const i of scalars)
if (typeof i !== "bigint")
throw new Error(`mapToCurve: expected array of bigints, got ${i} in array`);
const P = Point.fromAffine(mapToCurve(scalars)).clearCofactor();
P.assertValidity();
return P;
}
};
}
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const secp256k1P = BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f");
const secp256k1N = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
const _1n$5 = BigInt(1);
const _2n$5 = BigInt(2);
const divNearest = (a, b) => (a + b / _2n$5) / b;
function sqrtMod(y) {
const P = secp256k1P;
const _3n2 = BigInt(3), _6n2 = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);
const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88);
const b2 = y * y * y % P;
const b3 = b2 * b2 * y % P;
const b6 = pow2(b3, _3n2, P) * b3 % P;
const b9 = pow2(b6, _3n2, P) * b3 % P;
const b11 = pow2(b9, _2n$5, P) * b2 % P;
const b22 = pow2(b11, _11n, P) * b11 % P;
const b44 = pow2(b22, _22n, P) * b22 % P;
const b88 = pow2(b44, _44n, P) * b44 % P;
const b176 = pow2(b88, _88n, P) * b88 % P;
const b220 = pow2(b176, _44n, P) * b44 % P;
const b223 = pow2(b220, _3n2, P) * b3 % P;
const t1 = pow2(b223, _23n, P) * b22 % P;
const t2 = pow2(t1, _6n2, P) * b2 % P;
const root = pow2(t2, _2n$5, P);
if (!Fp$2.eql(Fp$2.sqr(root), y))
throw new Error("Cannot find square root");
return root;
}
const Fp$2 = Field(secp256k1P, void 0, void 0, { sqrt: sqrtMod });
const secp256k1 = createCurve({
a: BigInt(0),
// equation params: a, b
b: BigInt(7),
// Seem to be rigid: bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975
Fp: Fp$2,
// Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
n: secp256k1N,
// Curve order, total count of valid points in the field
// Base point (x, y) aka generator point
Gx: BigInt("55066263022277343669578718895168534326250603453777594175500187360389116729240"),
Gy: BigInt("32670510020758816978083085130507043184471273380659243275938904335757337482424"),
h: BigInt(1),
// Cofactor
lowS: true,
// Allow only low-S signatures by default in sign() and verify()
/**
* secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.
* Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.
* For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.
* Explanation: https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066
*/
endo: {
beta: BigInt("0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"),
splitScalar: (k) => {
const n = secp256k1N;
const a1 = BigInt("0x3086d221a7d46bcde86c90e49284eb15");
const b1 = -_1n$5 * BigInt("0xe4437ed6010e88286f547fa90abfe4c3");
const a2 = BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8");
const b2 = a1;
const POW_2_128 = BigInt("0x100000000000000000000000000000000");
const c1 = divNearest(b2 * k, n);
const c2 = divNearest(-b1 * k, n);
let k1 = mod$1(k - c1 * a1 - c2 * a2, n);
let k2 = mod$1(-c1 * b1 - c2 * b2, n);
const k1neg = k1 > POW_2_128;
const k2neg = k2 > POW_2_128;
if (k1neg)
k1 = n - k1;
if (k2neg)
k2 = n - k2;
if (k1 > POW_2_128 || k2 > POW_2_128) {
throw new Error("splitScalar: Endomorphism failed, k=" + k);
}
return { k1neg, k1, k2neg, k2 };
}
}
}, sha256$1);
BigInt(0);
secp256k1.ProjectivePoint;
function hexToBytes$2(data) {
const sliced = data.startsWith("0x") ? data.substring(2) : data;
return hexToBytes$4(sliced);
}
function equalsBytes(a, b) {
if (a.length !== b.length) {
return false;
}
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
function wrapHash(hash2) {
return (msg) => {
assert.bytes(msg);
return hash2(msg);
};
}
function isHexString$1(value, length) {
if (typeof value !== "string" || !value.match(/^0x[0-9A-Fa-f]*$/))
return false;
return true;
}
const stripHexPrefix$1 = (str) => {
if (typeof str !== "string")
throw new Error(`[stripHexPrefix] input must be type 'string', received ${typeof str}`);
return isHexString$1(str) ? str.slice(2) : str;
};
function padToEven$1(value) {
let a = value;
if (typeof a !== "string") {
throw new Error(`[padToEven] value must be type 'string', received ${typeof a}`);
}
if (a.length % 2)
a = `0${a}`;
return a;
}
const assertIsBytes = function(input) {
if (!(input instanceof Uint8Array)) {
const msg = `This method only supports Uint8Array but input was: ${input}`;
throw new Error(msg);
}
};
const BIGINT_0$1 = BigInt(0);
const bytesToUnprefixedHex = bytesToHex$3;
const hexToBytesMapFirstKey = {};
const hexToBytesMapSecondKey = {};
for (let i = 0; i < 16; i++) {
const vSecondKey = i;
const vFirstKey = i * 16;
const key = i.toString(16).toLowerCase();
hexToBytesMapSecondKey[key] = vSecondKey;
hexToBytesMapSecondKey[key.toUpperCase()] = vSecondKey;
hexToBytesMapFirstKey[key] = vFirstKey;
hexToBytesMapFirstKey[key.toUpperCase()] = vFirstKey;
}
const unprefixedHexToBytes = (inp) => {
if (inp.slice(0, 2) === "0x") {
throw new Error("hex string is prefixed with 0x, should be unprefixed");
} else {
inp = padToEven$1(inp);
const byteLen = inp.length;
const bytes2 = new Uint8Array(byteLen / 2);
for (let i = 0; i < byteLen; i += 2) {
bytes2[i / 2] = hexToBytesMapFirstKey[inp[i]] + hexToBytesMapSecondKey[inp[i + 1]];
}
return bytes2;
}
};
const hexByByte = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, "0"));
const bytesToHex$1 = (bytes2) => {
let hex = `0x`;
if (bytes2 === void 0 || bytes2.length === 0)
return hex;
for (const byte of bytes2) {
hex = `${hex}${hexByByte[byte]}`;
}
return hex;
};
const BIGINT_CACHE = [];
for (let i = 0; i <= 256 * 256 - 1; i++) {
BIGINT_CACHE[i] = BigInt(i);
}
const bytesToBigInt = (bytes2, littleEndian = false) => {
if (littleEndian) {
bytes2.reverse();
}
const hex = bytesToHex$1(bytes2);
if (hex === "0x") {
return BIGINT_0$1;
}
if (hex.length === 4) {
return BIGINT_CACHE[bytes2[0]];
}
if (hex.length === 6) {
return BIGINT_CACHE[bytes2[0] * 256 + bytes2[1]];
}
return BigInt(hex);
};
const bytesToInt = (bytes2) => {
const res = Number(bytesToBigInt(bytes2));
if (!Number.isSafeInteger(res))
throw new Error("Number exceeds 53 bits");
return res;
};
const hexToBytes$1 = (hex) => {
if (typeof hex !== "string") {
throw new Error(`hex argument type ${typeof hex} must be of type string`);
}
if (!/^0x[0-9a-fA-F]*$/.test(hex)) {
throw new Error(`Input must be a 0x-prefixed hexadecimal string, got ${hex}`);
}
const unprefixedHex = hex.slice(2);
return unprefixedHexToBytes(unprefixedHex);
};
const intToHex = (i) => {
if (!Number.isSafeInteger(i) || i < 0) {
throw new Error(`Received an invalid integer type: ${i}`);
}
return `0x${i.toString(16)}`;
};
const intToBytes = (i) => {
const hex = intToHex(i);
return hexToBytes$1(hex);
};
const bigIntToBytes = (num, littleEndian = false) => {
const bytes2 = toBytes$1(`0x${padToEven$1(num.toString(16))}`);
return littleEndian ? bytes2.reverse() : bytes2;
};
const zeros = (bytes2) => {
return new Uint8Array(bytes2);
};
const setLength = (msg, length, right) => {
if (right) {
if (msg.length < length) {
return new Uint8Array([...msg, ...zeros(length - msg.length)]);
}
return msg.subarray(0, length);
} else {
if (msg.length < length) {
return new Uint8Array([...zeros(length - msg.length), ...msg]);
}
return msg.subarray(-length);
}
};
const setLengthLeft = (msg, length) => {
assertIsBytes(msg);
return setLength(msg, length, false);
};
const setLengthRight = (msg, length) => {
assertIsBytes(msg);
return setLength(msg, length, true);
};
const stripZeros = (a) => {
let first = a[0];
while (a.length > 0 && first.toString() === "0") {
a = a.slice(1);
first = a[0];
}
return a;
};
const unpadBytes = (a) => {
assertIsBytes(a);
return stripZeros(a);
};
const toBytes$1 = (v) => {
if (v === null || v === void 0) {
return new Uint8Array();
}
if (Array.isArray(v) || v instanceof Uint8Array) {
return Uint8Array.from(v);
}
if (typeof v === "string") {
if (!isHexString$1(v)) {
throw new Error(`Cannot convert string to Uint8Array. toBytes only supports 0x-prefixed hex strings and this string was given: ${v}`);
}
return hexToBytes$1(v);
}
if (typeof v === "number") {
return intToBytes(v);
}
if (typeof v === "bigint") {
if (v < BIGINT_0$1) {
throw new Error(`Cannot convert negative bigint to Uint8Array. Given: ${v}`);
}
let n = v.toString(16);
if (n.length % 2)
n = "0" + n;
return unprefixedHexToBytes(n);
}
if (v.toBytes !== void 0) {
return v.toBytes();
}
throw new Error("invalid type");
};
const short = (bytes2, maxLength = 50) => {
const byteStr = bytes2 instanceof Uint8Array ? bytesToHex$1(bytes2) : bytes2;
const len = byteStr.slice(0, 2) === "0x" ? maxLength + 2 : maxLength;
if (byteStr.length <= len) {
return byteStr;
}
return byteStr.slice(0, len) + "\u2026";
};
const bigIntToHex = (num) => {
return `0x${num.toString(16)}`;
};
const bigIntToUnpaddedBytes = (value) => {
return unpadBytes(bigIntToBytes(value));
};
const bigIntToAddressBytes = (value, strict = true) => {
const addressBytes = bigIntToBytes(value);
if (strict && addressBytes.length > 20) {
throw Error(`Invalid address bytes length=${addressBytes.length} strict=${strict}`);
}
return setLengthLeft(addressBytes, 20);
};
const intToUnpaddedBytes = (value) => {
return unpadBytes(intToBytes(value));
};
const concatBytes$1 = (...arrays) => {
if (arrays.length === 1)
return arrays[0];
const length = arrays.reduce((a, arr) => a + arr.length, 0);
const result = new Uint8Array(length);
for (let i = 0, pad = 0; i < arrays.length; i++) {
const arr = arrays[i];
result.set(arr, pad);
pad += arr.length;
}
return result;
};
const MAX_UINT64 = BigInt("0xffffffffffffffff");
const MAX_INTEGER = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
const MAX_INTEGER_BIGINT = BigInt("115792089237316195423570985008687907853269984665640564039457584007913129639935");
secp256k1.CURVE.n;
secp256k1.CURVE.n / BigInt(2);
const TWO_POW256 = BigInt("0x10000000000000000000000000000000000000000000000000000000000000000");
const KECCAK256_NULL_S = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
const KECCAK256_NULL = hexToBytes$1(KECCAK256_NULL_S);
const KECCAK256_RLP_ARRAY_S = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347";
hexToBytes$1(KECCAK256_RLP_ARRAY_S);
const KECCAK256_RLP_S = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421";
const KECCAK256_RLP = hexToBytes$1(KECCAK256_RLP_S);
Uint8Array.from([128]);
const RIPEMD160_ADDRESS_STRING = "0000000000000000000000000000000000000003";
BigInt(-1);
const BIGINT_0 = BigInt(0);
const BIGINT_1 = BigInt(1);
const BIGINT_2 = BigInt(2);
const BIGINT_3 = BigInt(3);
const BIGINT_7 = BigInt(7);
const BIGINT_8 = BigInt(8);
const BIGINT_27 = BigInt(27);
const BIGINT_28 = BigInt(28);
const BIGINT_31 = BigInt(31);
const BIGINT_32 = BigInt(32);
const BIGINT_64 = BigInt(64);
BigInt(128);
const BIGINT_255 = BigInt(255);
const BIGINT_256 = BigInt(256);
const BIGINT_96 = BigInt(96);
BigInt(100);
const BIGINT_160 = BigInt(160);
const BIGINT_224 = BigInt(224);
const BIGINT_2EXP96 = BigInt(7922816251426434e13);
const BIGINT_2EXP160 = BigInt(1461501637330903e33);
const BIGINT_2EXP224 = BigInt(2695994666715064e52);
function encode(input) {
if (Array.isArray(input)) {
const output2 = [];
let outputLength = 0;
for (let i = 0; i < input.length; i++) {
const encoded = encode(input[i]);
output2.push(encoded);
outputLength += encoded.length;
}
return concatBytes(encodeLength(outputLength, 192), ...output2);
}
const inputBuf = toBytes(input);
if (inputBuf.length === 1 && inputBuf[0] < 128) {
return inputBuf;
}
return concatBytes(encodeLength(inputBuf.length, 128), inputBuf);
}
function safeSlice(input, start, end) {
if (end > input.length) {
throw new Error("invalid RLP (safeSlice): end slice of Uint8Array out-of-bounds");
}
return input.slice(start, end);
}
function decodeLength(v) {
if (v[0] === 0) {
throw new Error("invalid RLP: extra zeros");
}
return parseHexByte(bytesToHex(v));
}
function encodeLength(len, offset) {
if (len < 56) {
return Uint8Array.from([len + offset]);
}
const hexLength = numberToHex(len);
const lLength = hexLength.length / 2;
const firstByte = numberToHex(offset + 55 + lLength);
return Uint8Array.from(hexToBytes(firstByte + hexLength));
}
function decode(input, stream = false) {
if (typeof input === "undefined" || input === null || input.length === 0) {
return Uint8Array.from([]);
}
const inputBytes = toBytes(input);
const decoded = _decode(inputBytes);
if (stream) {
return {
data: decoded.data,
remainder: decoded.remainder.slice()
};
}
if (decoded.remainder.length !== 0) {
throw new Error("invalid RLP: remainder must be zero");
}
return decoded.data;
}
function _decode(input) {
let length, lLength, data, innerRemainder, d;
const decoded = [];
const firstByte = input[0];
if (firstByte <= 127) {
return {
data: input.slice(0, 1),
remainder: input.subarray(1)
};
} else if (firstByte <= 183) {
length = firstByte - 127;
if (firstByte === 128) {
data = Uint8Array.from([]);
} else {
data = safeSlice(input, 1, length);
}
if (length === 2 && data[0] < 128) {
throw new Error("invalid RLP encoding: invalid prefix, single byte < 0x80 are not prefixed");
}
return {
data,
remainder: input.subarray(length)
};
} else if (firstByte <= 191) {
lLength = firstByte - 182;
if (input.length - 1 < lLength) {
throw new Error("invalid RLP: not enough bytes for string length");
}
length = decodeLength(safeSlice(input, 1, lLength));
if (length <= 55) {
throw new Error("invalid RLP: expected string length to be greater than 55");
}
data = safeSlice(input, lLength, length + lLength);
return {
data,
remainder: input.subarray(length + lLength)
};
} else if (firstByte <= 247) {
length = firstByte - 191;
innerRemainder = safeSlice(input, 1, length);
while (innerRemainder.length) {
d = _decode(innerRemainder);
decoded.push(d.data);
innerRemainder = d.remainder;
}
return {
data: decoded,
remainder: input.subarray(length)
};
} else {
lLength = firstByte - 246;
length = decodeLength(safeSlice(input, 1, lLength));
if (length < 56) {
throw new Error("invalid RLP: encoded list too short");
}
const totalLength = lLength + length;
if (totalLength > input.length) {
throw new Error("invalid RLP: total length is larger than the data");
}
innerRemainder = safeSlice(input, lLength, totalLength);
while (innerRemainder.length) {
d = _decode(innerRemainder);
decoded.push(d.data);
innerRemainder = d.remainder;
}
return {
data: decoded,
remainder: input.subarray(totalLength)
};
}
}
const cachedHexes = Array.from({ length: 256 }, (_v, i) => i.toString(16).padStart(2, "0"));
function bytesToHex(uint8a) {
let hex = "";
for (let i = 0; i < uint8a.length; i++) {
hex += cachedHexes[uint8a[i]];
}
return hex;
}
function parseHexByte(hexByte) {
const byte = Number.parseInt(hexByte, 16);
if (Number.isNaN(byte))
throw new Error("Invalid byte sequence");
return byte;
}
function hexToBytes(hex) {
if (typeof hex !== "string") {
throw new TypeError("hexToBytes: expected string, got " + typeof hex);
}
if (hex.length % 2)
throw new Error("hexToBytes: received invalid unpadded hex");
const array = new Uint8Array(hex.length / 2);
for (let i = 0; i < array.length; i++) {
const j = i * 2;
array[i] = parseHexByte(hex.slice(j, j + 2));
}
return array;
}
function concatBytes(...arrays) {
if (arrays.length === 1)
return arrays[0];
const length = arrays.reduce((a, arr) => a + arr.length, 0);
const result = new Uint8Array(length);
for (let i = 0, pad = 0; i < arrays.length; i++) {
const arr = arrays[i];
result.set(arr, pad);
pad += arr.length;
}
return result;
}
function utf8ToBytes(utf) {
return new TextEncoder().encode(utf);
}
function numberToHex(integer) {
if (integer < 0) {
throw new Error("Invalid integer as argument, must be unsigned!");
}
const hex = integer.toString(16);
return hex.length % 2 ? `0${hex}` : hex;
}
function padToEven(a) {
return a.length % 2 ? `0${a}` : a;
}
function isHexString(str) {
return str.length >= 2 && str[0] === "0" && str[1] === "x";
}
function stripHexPrefix(str) {
if (typeof str !== "string") {
return str;
}
return isHexString(str) ? str.slice(2) : str;
}
function toBytes(v) {
if (v instanceof Uint8Array) {
return v;
}
if (typeof v === "string") {
if (isHexString(v)) {
return hexToBytes(padToEven(stripHexPrefix(v)));
}
return utf8ToBytes(v);
}
if (typeof v === "number" || typeof v === "bigint") {
if (!v) {
return Uint8Array.from([]);
}
return hexToBytes(numberToHex(v));
}
if (v === null || v === void 0) {
return Uint8Array.from([]);
}
throw new Error("toBytes: received unsupported type " + typeof v);
}
const RLP = { encode, decode };
const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
const _32n = /* @__PURE__ */ BigInt(32);
function fromBig(n, le = false) {
if (le)
return { h: Number(n & U32_MASK64), l: Number(n >> _32n & U32_MASK64) };
return { h: Number(n >> _32n & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
}
function split(lst, le = false) {
let Ah = new Uint32Array(lst.length);
let Al = new Uint32Array(lst.length);
for (let i = 0; i < lst.length; i++) {
const { h, l } = fromBig(lst[i], le);
[Ah[i], Al[i]] = [h, l];
}
return [Ah, Al];
}
const rotlSH = (h, l, s) => h << s | l >>> 32 - s;
const rotlSL = (h, l, s) => l << s | h >>> 32 - s;
const rotlBH = (h, l, s) => l << s - 32 | h >>> 64 - s;
const rotlBL = (h, l, s) => h << s - 32 | l >>> 64 - s;
const SHA3_PI = [];
const SHA3_ROTL = [];
const _SHA3_IOTA = [];
const _0n$3 = /* @__PURE__ */ BigInt(0);
const _1n$4 = /* @__PURE__ */ BigInt(1);
const _2n$4 = /* @__PURE__ */ BigInt(2);
const _7n = /* @__PURE__ */ BigInt(7);
const _256n = /* @__PURE__ */ BigInt(256);
const _0x71n = /* @__PURE__ */ BigInt(113);
for (let round = 0, R2 = _1n$4, x = 1, y = 0; round < 24; round++) {
[x, y] = [y, (2 * x + 3 * y) % 5];
SHA3_PI.push(2 * (5 * y + x));
SHA3_ROTL.push((round + 1) * (round + 2) / 2 % 64);
let t = _0n$3;
for (let j = 0; j < 7; j++) {
R2 = (R2 << _1n$4 ^ (R2 >> _7n) * _0x71n) % _256n;
if (R2 & _2n$4)
t ^= _1n$4 << (_1n$4 << /* @__PURE__ */ BigInt(j)) - _1n$4;
}
_SHA3_IOTA.push(t);
}
const [SHA3_IOTA_H, SHA3_IOTA_L] = /* @__PURE__ */ split(_SHA3_IOTA, true);
const rotlH = (h, l, s) => s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s);
const rotlL = (h, l, s) => s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s);
function keccakP(s, rounds = 24) {
const B = new Uint32Array(5 * 2);
for (let round = 24 - rounds; round < 24; round++) {
for (let x = 0; x < 10; x++)
B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
for (let x = 0; x < 10; x += 2) {
const idx1 = (x + 8) % 10;
const idx0 = (x + 2) % 10;
const B0 = B[idx0];
const B1 = B[idx0 + 1];
const Th = rotlH(B0, B1, 1) ^ B[idx1];
const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];
for (let y = 0; y < 50; y += 10) {
s[x + y] ^= Th;
s[x + y + 1] ^= Tl;
}
}
let curH = s[2];
let curL = s[3];
for (let t = 0; t < 24; t++) {
const shift = SHA3_ROTL[t];
const Th = rotlH(curH, curL, shift);
const Tl = rotlL(curH, curL, shift);
const PI = SHA3_PI[t];
curH = s[PI];
curL = s[PI + 1];
s[PI] = Th;
s[PI + 1] = Tl;
}
for (let y = 0; y < 50; y += 10) {
for (let x = 0; x < 10; x++)
B[x] = s[y + x];
for (let x = 0; x < 10; x++)
s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];
}
s[0] ^= SHA3_IOTA_H[round];
s[1] ^= SHA3_IOTA_L[round];
}
B.fill(0);
}
class Keccak extends Hash {
// NOTE: we accept arguments in bytes instead of bits here.
constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
super();
this.blockLen = blockLen;
this.suffix = suffix;
this.outputLen = outputLen;
this.enableXOF = enableXOF;
this.rounds = rounds;
this.pos = 0;
this.posOut = 0;
this.finished = false;
this.destroyed = false;
number(outputLen);
if (0 >= this.blockLen || this.blockLen >= 200)
throw new Error("Sha3 supports only keccak-f1600 function");
this.state = new Uint8Array(200);
this.state32 = u32(this.state);
}
keccak() {
if (!isLE)
byteSwap32(this.state32);
keccakP(this.state32, this.rounds);
if (!isLE)
byteSwap32(this.state32);
this.posOut = 0;
this.pos = 0;
}
update(data) {
exists(this);
const { blockLen, state } = this;
data = toBytes$2(data);
const len = data.length;
for (let pos = 0; pos < len; ) {
const take = Math.min(blockLen - this.pos, len - pos);
for (let i = 0; i < take; i++)
state[this.pos++] ^= data[pos++];
if (this.pos === blockLen)
this.keccak();
}
return this;
}
finish() {
if (this.finished)
return;
this.finished = true;
const { state, suffix, pos, blockLen } = this;
state[pos] ^= suffix;
if ((suffix & 128) !== 0 && pos === blockLen - 1)
this.keccak();
state[blockLen - 1] ^= 128;
this.keccak();
}
writeInto(out) {
exists(this, false);
bytes(out);
this.finish();
const bufferOut = this.state;
const { blockLen } = this;
for (let pos = 0, len = out.length; pos < len; ) {
if (this.posOut >= blockLen)
this.keccak();
const take = Math.min(blockLen - this.posOut, len - pos);
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
this.posOut += take;
pos += take;
}
return out;
}
xofInto(out) {
if (!this.enableXOF)
throw new Error("XOF is not possible for this instance");
return this.writeInto(out);
}
xof(bytes2) {
number(bytes2);
return this.xofInto(new Uint8Array(bytes2));
}
digestInto(out) {
output(out, this);
if (this.finished)
throw new Error("digest() was already called");
this.writeInto(out);
this.destroy();
return out;
}
digest() {
return this.digestInto(new Uint8Array(this.outputLen));
}
destroy() {
this.destroyed = true;
this.state.fill(0);
}
_cloneInto(to) {
const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
to || (to = new Keccak(blockLen, suffix, outputLen, enableXOF, rounds));
to.state32.set(this.state32);
to.pos = this.pos;
to.posOut = this.posOut;
to.finished = this.finished;
to.rounds = rounds;
to.suffix = suffix;
to.outputLen = outputLen;
to.enableXOF = enableXOF;
to.destroyed = this.destroyed;
return to;
}
}
const gen = (suffix, blockLen, outputLen) => wrapConstructor(() => new Keccak(blockLen, suffix, outputLen));
const keccak_256 = /* @__PURE__ */ gen(1, 136, 256 / 8);
const keccak256 = (() => {
const k = wrapHash(keccak_256);
k.create = keccak_256.create;
return k;
})();
class Account {
get version() {
if (this._version !== null) {
return this._version;
} else {
throw Error(`version=${this._version} not loaded`);
}
}
set version(_version) {
this._version = _version;
}
get nonce() {
if (this._nonce !== null) {
return this._nonce;
} else {
throw Error(`nonce=${this._nonce} not loaded`);
}
}
set nonce(_nonce) {
this._nonce = _nonce;
}
get balance() {
if (this._balance !== null) {
return this._balance;
} else {
throw Error(`balance=${this._balance} not loaded`);
}
}
set balance(_balance) {
this._balance = _balance;
}
get storageRoot() {
if (this._storageRoot !== null) {
return this._storageRoot;
} else {
throw Error(`storageRoot=${this._storageRoot} not loaded`);
}
}
set storageRoot(_storageRoot) {
this._storageRoot = _storageRoot;
}
get codeHash() {
if (this._codeHash !== null) {
return this._codeHash;
} else {
throw Error(`codeHash=${this._codeHash} not loaded`);
}
}
set codeHash(_codeHash) {
this._codeHash = _codeHash;
}
get codeSize() {
if (this._codeSize !== null) {
return this._codeSize;
} else {
throw Error(`codeSize=${this._codeSize} not loaded`);
}
}
set codeSize(_codeSize) {
this._codeSize = _codeSize;
}
/**
* This constructor assigns and validates the values.
* Use the static factory methods to assist in creating an Account from varying data types.
* undefined get assigned with the defaults present, but null args are retained as is
*/
constructor(nonce = BIGINT_0, balance = BIGINT_0, storageRoot = KECCAK256_RLP, codeHash = KECCAK256_NULL, codeSize = 0, version = 0) {
this._nonce = null;
this._balance = null;
this._storageRoot = null;
this._codeHash = null;
this._codeSize = null;
this._version = null;
this._nonce = nonce;
this._balance = balance;
this._storageRoot = storageRoot;
this._codeHash = codeHash;
if (codeSize === null && codeHash !== null && !this.isContract()) {
codeSize = 0;
}
this._codeSize = codeSize;
this._version = version;
this._validate();
}
_validate() {
if (this._nonce !== null && this._nonce < BIGINT_0) {
throw new Error("nonce must be greater than zero");
}
if (this._balance !== null && this._balance < BIGINT_0) {
throw new Error("balance must be greater than zero");
}
if (this._storageRoot !== null && this._storageRoot.length !== 32) {
throw new Error("storageRoot must have a length of 32");
}
if (this._codeHash !== null && this._codeHash.length !== 32) {
throw new Error("codeHash must have a length of 32");
}
if (this._codeSize !== null && this._codeSize < BIGINT_0) {
throw new Error("codeSize must be greater than zero");
}
}
/**
* Returns an array of Uint8Arrays of the raw bytes for the account, in order.
*/
raw() {
return [
bigIntToUnpaddedBytes(this.nonce),
bigIntToUnpaddedBytes(this.balance),
this.storageRoot,
this.codeHash
];
}
/**
* Returns the RLP serialization of the account as a `Uint8Array`.
*/
serialize() {
return RLP.encode(this.raw());
}
serializeWithPartialInfo() {
const partialData = [];
const zeroEncoded = intToUnpaddedBytes(0);
const oneEncoded = intToUnpaddedBytes(1);
if (this._nonce !== null) {
partialData.push([oneEncoded, bigIntToUnpaddedBytes(this._nonce)]);
} else {
partialData.push([zeroEncoded]);
}
if (this._balance !== null) {
partialData.push([oneEncoded, bigIntToUnpaddedBytes(this._balance)]);
} else {
partialData.push([zeroEncoded]);
}
if (this._storageRoot !== null) {
partialData.push([oneEncoded, this._storageRoot]);
} else {
partialData.push([zeroEncoded]);
}
if (this._codeHash !== null) {
partialData.push([oneEncoded, this._codeHash]);
} else {
partialData.push([zeroEncoded]);
}
if (this._codeSize !== null) {
partialData.push([oneEncoded, intToUnpaddedBytes(this._codeSize)]);
} else {
partialData.push([zeroEncoded]);
}
if (this._version !== null) {
partialData.push([oneEncoded, intToUnpaddedBytes(this._version)]);
} else {
partialData.push([zeroEncoded]);
}
return RLP.encode(partialData);
}
/**
* Returns a `Boolean` determining if the account is a contract.
*/
isContract() {
if (this._codeHash === null && this._codeSize === null) {
throw Error(`Insufficient data as codeHash=null and codeSize=null`);
}
return this._codeHash !== null && !equalsBytes(this._codeHash, KECCAK256_NULL) || this._codeSize !== null && this._codeSize !== 0;
}
/**
* Returns a `Boolean` determining if the account is empty complying to the definition of
* account emptiness in [EIP-161](https://eips.ethereum.org/EIPS/eip-161):
* "An account is considered empty when it has no code and zero nonce and zero balance."
*/
isEmpty() {
if (this._balance !== null && this.balance !== BIGINT_0 || this._nonce === null && this.nonce !== BIGINT_0 || this._codeHash !== null && !equalsBytes(this.codeHash, KECCAK256_NULL)) {
return false;
}
return this.balance === BIGINT_0 && this.nonce === BIGINT_0 && equalsBytes(this.codeHash, KECCAK256_NULL);
}
}
const generateAddress = function(from, nonce) {
assertIsBytes(from);
assertIsBytes(nonce);
if (bytesToBigInt(nonce) === BIGINT_0) {
return keccak256(RLP.encode([from, Uint8Array.from([])])).subarray(-20);
}
return keccak256(RLP.encode([from, nonce])).subarray(-20);
};
const generateAddress2 = function(from, salt, initCode) {
assertIsBytes(from);
assertIsBytes(salt);
assertIsBytes(initCode);
if (from.length !== 20) {
throw new Error("Expected from to be of length 20");
}
if (salt.length !== 32) {
throw new Error("Expected salt to be of length 32");
}
const address = keccak256(concatBytes$1(hexToBytes$1("0xff"), from, salt, keccak256(initCode)));
return address.subarray(-20);
};
const pubToAddress = function(pubKey, sanitize = false) {
assertIsBytes(pubKey);
if (sanitize && pubKey.length !== 64) {
pubKey = secp256k1.ProjectivePoint.fromHex(pubKey).toRawBytes(false).slice(1);
}
if (pubKey.length !== 64) {
throw new Error("Expected pubKey to be of length 64");
}
return keccak256(pubKey).subarray(-20);
};
const publicToAddress = pubToAddress;
class Address {
constructor(bytes2) {
if (bytes2.length !== 20) {
throw new Error("Invalid address length");
}
this.bytes = bytes2;
}
/**
* Is address equal to another.
*/
equals(address) {
return equalsBytes(this.bytes, address.bytes);
}
/**
* Is address zero.
*/
isZero() {
return this.equals(new Address(zeros(20)));
}
/**
* True if address is in the address range defined
* by EIP-1352
*/
isPrecompileOrSystemAddress() {
const address = bytesToBigInt(this.bytes);
const rangeMin = BIGINT_0;
const rangeMax = BigInt("0xffff");
return address >= rangeMin && address <= rangeMax;
}
/**
* Returns hex encoding of address.
*/
toString() {
return bytesToHex$1(this.bytes);
}
/**
* Returns a new Uint8Array representation of address.
*/
toBytes() {
return new Uint8Array(this.bytes);
}
}
function createZeroAddress() {
return new Address(zeros(20));
}
function createAddressFromBigInt(value) {
const bytes2 = bigIntToBytes(value);
if (bytes2.length > 20) {
throw new Error(`Invalid address, too long: ${bytes2.length}`);
}
return new Address(setLengthLeft(bytes2, 20));
}
var TypeOutput;
(function(TypeOutput2) {
TypeOutput2[TypeOutput2["Number"] = 0] = "Number";
TypeOutput2[TypeOutput2["BigInt"] = 1] = "BigInt";
TypeOutput2[TypeOutput2["Uint8Array"] = 2] = "Uint8Array";
TypeOutput2[TypeOutput2["PrefixedHexString"] = 3] = "PrefixedHexString";
})(TypeOutput = TypeOutput || (TypeOutput = {}));
function toType(input, outputType) {
if (input === null) {
return null;
}
if (input === void 0) {
return void 0;
}
if (typeof input === "string" && !isHexString$1(input)) {
throw new Error(`A string must be provided with a 0x-prefix, given: ${input}`);
} else if (typeof input === "number" && !Number.isSafeInteger(input)) {
throw new Error("The provided number is greater than MAX_SAFE_INTEGER (please use an alternative input type)");
}
const output2 = toBytes$1(input);
switch (outputType) {
case TypeOutput.Uint8Array:
return output2;
case TypeOutput.BigInt:
return bytesToBigInt(output2);
case TypeOutput.Number: {
const bigInt = bytesToBigInt(output2);
if (bigInt > BigInt(Number.MAX_SAFE_INTEGER)) {
throw new Error("The provided number is greater than MAX_SAFE_INTEGER (please use an alternative output type)");
}
return Number(bigInt);
}
case TypeOutput.PrefixedHexString:
return bytesToHex$1(output2);
default:
throw new Error("unknown outputType");
}
}
function calculateSigRecovery(v, chainId) {
if (v === BIGINT_0 || v === BIGINT_1)
return v;
if (chainId === void 0) {
return v - BIGINT_27;
}
return v - (chainId * BIGINT_2 + BigInt(35));
}
function isValidSigRecovery(recovery) {
return recovery === BIGINT_0 || recovery === BIGINT_1;
}
const ecrecover = function(msgHash, v, r, s, chainId) {
const signature = concatBytes$1(setLengthLeft(r, 32), setLengthLeft(s, 32));
const recovery = calculateSigRecovery(v, chainId);
if (!isValidSigRecovery(recovery)) {
throw new Error("Invalid signature v value");
}
const sig = secp256k1.Signature.fromCompact(signature).addRecoveryBit(Number(recovery));
const senderPubKey = sig.recoverPublicKey(msgHash);
return senderPubKey.toRawBytes(false).slice(1);
};
function getDefaultExportFromCjs(x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
}
var events = { exports: {} };
events.exports;
var R = typeof Reflect === "object" ? Reflect : null;
var ReflectApply = R && typeof R.apply === "function" ? R.apply : function ReflectApply2(target, receiver, args) {
return Function.prototype.apply.call(target, receiver, args);
};
var ReflectOwnKeys;
if (R && typeof R.ownKeys === "function") {
ReflectOwnKeys = R.ownKeys;
} else if (Object.getOwnPropertySymbols) {
ReflectOwnKeys = function ReflectOwnKeys2(target) {
return Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target));
};
} else {
ReflectOwnKeys = function ReflectOwnKeys2(target) {
return Object.getOwnPropertyNames(target);
};
}
function ProcessEmitWarning(warning) {
if (console && console.warn) console.warn(warning);
}
var NumberIsNaN = Number.isNaN || function NumberIsNaN2(value) {
return value !== value;
};
function EventEmitter() {
EventEmitter.init.call(this);
}
events.exports = EventEmitter;
events.exports.once = once2;
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = void 0;
EventEmitter.prototype._eventsCount = 0;
EventEmitter.prototype._maxListeners = void 0;
var defaultMaxListeners = 10;
function checkListener(listener) {
if (typeof listener !== "function") {
throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
}
}
Object.defineProperty(EventEmitter, "defaultMaxListeners", {
enumerable: true,
get: function() {
return defaultMaxListeners;
},
set: function(arg) {
if (typeof arg !== "number" || arg < 0 || NumberIsNaN(arg)) {
throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + ".");
}
defaultMaxListeners = arg;
}
});
EventEmitter.init = function() {
if (this._events === void 0 || this._events === Object.getPrototypeOf(this)._events) {
this._events = /* @__PURE__ */ Object.create(null);
this._eventsCount = 0;
}
this._maxListeners = this._maxListeners || void 0;
};
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
if (typeof n !== "number" || n < 0 || NumberIsNaN(n)) {
throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + ".");
}
this._maxListeners = n;
return this;
};
function _getMaxListeners(that) {
if (that._maxListeners === void 0)
return EventEmitter.defaultMaxListeners;
return that._maxListeners;
}
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
return _getMaxListeners(this);
};
EventEmitter.prototype.emit = function emit(type) {
var args = [];
for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);
var doError = type === "error";
var events2 = this._events;
if (events2 !== void 0)
doError = doError && events2.error === void 0;
else if (!doError)
return false;
if (doError) {
var er;
if (args.length > 0)
er = args[0];
if (er instanceof Error) {
throw er;
}
var err = new Error("Unhandled error." + (er ? " (" + er.message + ")" : ""));
err.context = er;
throw err;
}
var handler = events2[type];
if (handler === void 0)
return false;
if (typeof handler === "function") {
ReflectApply(handler, this, args);
} else {
var len = handler.length;
var listeners2 = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
ReflectApply(listeners2[i], this, args);
}
return true;
};
function _addListener(target, type, listener, prepend) {
var m;
var events2;
var existing;
checkListener(listener);
events2 = target._events;
if (events2 === void 0) {
events2 = target._events = /* @__PURE__ */ Object.create(null);
target._eventsCount = 0;
} else {
if (events2.newListener !== void 0) {
target.emit(
"newListener",
type,
listener.listener ? listener.listener : listener
);
events2 = target._events;
}
existing = events2[type];
}
if (existing === void 0) {
existing = events2[type] = listener;
++target._eventsCount;
} else {
if (typeof existing === "function") {
existing = events2[type] = prepend ? [listener, existing] : [existing, listener];
} else if (prepend) {
existing.unshift(listener);
} else {
existing.push(listener);
}
m = _getMaxListeners(target);
if (m > 0 && existing.length > m && !existing.warned) {
existing.warned = true;
var w = new Error("Possible EventEmitter memory leak detected. " + existing.length + " " + String(type) + " listeners added. Use emitter.setMaxListeners() to increase limit");
w.name = "MaxListenersExceededWarning";
w.emitter = target;
w.type = type;
w.count = existing.length;
ProcessEmitWarning(w);
}
}
return target;
}
EventEmitter.prototype.addListener = function addListener(type, listener) {
return _addListener(this, type, listener, false);
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.prependListener = function prependListener(type, listener) {
return _addListener(this, type, listener, true);
};
function onceWrapper() {
if (!this.fired) {
this.target.removeListener(this.type, this.wrapFn);
this.fired = true;
if (arguments.length === 0)
return this.listener.call(this.target);
return this.listener.apply(this.target, arguments);
}
}
function _onceWrap(target, type, listener) {
var state = { fired: false, wrapFn: void 0, target, type, listener };
var wrapped = onceWrapper.bind(state);
wrapped.listener = listener;
state.wrapFn = wrapped;
return wrapped;
}
EventEmitter.prototype.once = function once(type, listener) {
checkListener(listener);
this.on(type, _onceWrap(this, type, listener));
return this;
};
EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) {
checkListener(listener);
this.prependListener(type, _onceWrap(this, type, listener));
return this;
};
EventEmitter.prototype.removeListener = function removeListener(type, listener) {
var list, events2, position, i, originalListener;
checkListener(listener);
events2 = this._events;
if (events2 === void 0)
return this;
list = events2[type];
if (list === void 0)
return this;
if (list === listener || list.listener === listener) {
if (--this._eventsCount === 0)
this._events = /* @__PURE__ */ Object.create(null);
else {
delete events2[type];
if (events2.removeListener)
this.emit("removeListener", type, list.listener || listener);
}
} else if (typeof list !== "function") {
position = -1;
for (i = list.length - 1; i >= 0; i--) {
if (list[i] === listener || list[i].listener === listener) {
originalListener = list[i].listener;
position = i;
break;
}
}
if (position < 0)
return this;
if (position === 0)
list.shift();
else {
spliceOne(list, position);
}
if (list.length === 1)
events2[type] = list[0];
if (events2.removeListener !== void 0)
this.emit("removeListener", type, originalListener || listener);
}
return this;
};
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) {
var listeners2, events2, i;
events2 = this._events;
if (events2 === void 0)
return this;
if (events2.removeListener === void 0) {
if (arguments.length === 0) {
this._events = /* @__PURE__ */ Object.create(null);
this._eventsCount = 0;
} else if (events2[type] !== void 0) {
if (--this._eventsCount === 0)
this._events = /* @__PURE__ */ Object.create(null);
else
delete events2[type];
}
return this;
}
if (arguments.length === 0) {
var keys = Object.keys(events2);
var key;
for (i = 0; i < keys.length; ++i) {
key = keys[i];
if (key === "removeListener") continue;
this.removeAllListeners(key);
}
this.removeAllListeners("removeListener");
this._events = /* @__PURE__ */ Object.create(null);
this._eventsCount = 0;
return this;
}
listeners2 = events2[type];
if (typeof listeners2 === "function") {
this.removeListener(type, listeners2);
} else if (listeners2 !== void 0) {
for (i = listeners2.length - 1; i >= 0; i--) {
this.removeListener(type, listeners2[i]);
}
}
return this;
};
function _listeners(target, type, unwrap) {
var events2 = target._events;
if (events2 === void 0)
return [];
var evlistener = events2[type];
if (evlistener === void 0)
return [];
if (typeof evlistener === "function")
return unwrap ? [evlistener.listener || evlistener] : [evlistener];
return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
}
EventEmitter.prototype.listeners = function listeners(type) {
return _listeners(this, type, true);
};
EventEmitter.prototype.rawListeners = function rawListeners(type) {
return _listeners(this, type, false);
};
EventEmitter.listenerCount = function(emitter, type) {
if (typeof emitter.listenerCount === "function") {
return emitter.listenerCount(type);
} else {
return listenerCount.call(emitter, type);
}
};
EventEmitter.prototype.listenerCount = listenerCount;
function listenerCount(type) {
var events2 = this._events;
if (events2 !== void 0) {
var evlistener = events2[type];
if (typeof evlistener === "function") {
return 1;
} else if (evlistener !== void 0) {
return evlistener.length;
}
}
return 0;
}
EventEmitter.prototype.eventNames = function eventNames() {
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
};
function arrayClone(arr, n) {
var copy = new Array(n);
for (var i = 0; i < n; ++i)
copy[i] = arr[i];
return copy;
}
function spliceOne(list, index) {
for (; index + 1 < list.length; index++)
list[index] = list[index + 1];
list.pop();
}
function unwrapListeners(arr) {
var ret = new Array(arr.length);
for (var i = 0; i < ret.length; ++i) {
ret[i] = arr[i].listener || arr[i];
}
return ret;
}
function once2(emitter, name) {
return new Promise(function(resolve, reject) {
function errorListener(err) {
emitter.removeListener(name, resolver);
reject(err);
}
function resolver() {
if (typeof emitter.removeListener === "function") {
emitter.removeListener("error", errorListener);
}
resolve([].slice.call(arguments));
}
eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
if (name !== "error") {
addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });
}
});
}
function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
if (typeof emitter.on === "function") {
eventTargetAgnosticAddListener(emitter, "error", handler, flags);
}
}
function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
if (typeof emitter.on === "function") {
if (flags.once) {
emitter.once(name, listener);
} else {
emitter.on(name, listener);
}
} else if (typeof emitter.addEventListener === "function") {
emitter.addEventListener(name, function wrapListener(arg) {
if (flags.once) {
emitter.removeEventListener(name, wrapListener);
}
listener(arg);
});
} else {
throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter);
}
}
var eventsExports = events.exports;
async function runInSeries(context, tasks, data) {
let error;
for await (const task of tasks) {
try {
if (task.length < 2) {
task.call(context, data);
} else {
await new Promise((resolve, reject) => {
task.call(context, data, (error2) => {
if (error2) {
reject(error2);
} else {
resolve();
}
});
});
}
} catch (e) {
error = e;
}
}
if (error) {
throw error;
}
}
class AsyncEventEmitter extends eventsExports.EventEmitter {
emit(event, ...args) {
let [data, callback] = args;
const self = this;
let listeners2 = self._events[event] ?? [];
if (callback === void 0 && typeof data === "function") {
callback = data;
data = void 0;
}
if (event === "newListener" || event === "removeListener") {
data = {
event: data,
fn: callback
};
callback = void 0;
}
listeners2 = Array.isArray(listeners2) ? listeners2 : [listeners2];
runInSeries(self, listeners2.slice(), data).then(callback).catch(callback);
return self.listenerCount(event) > 0;
}
once(event, listener) {
const self = this;
let g;
if (typeof listener !== "function") {
throw new TypeError("listener must be a function");
}
if (listener.length >= 2) {
g = function(e, next) {
self.removeListener(event, g);
void listener(e, next);
};
} else {
g = function(e) {
self.removeListener(event, g);
void listener(e, g);
};
}
self.on(event, g);
return self;
}
first(event, listener) {
let listeners2 = this._events[event] ?? [];
if (typeof listener !== "function") {
throw new TypeError("listener must be a function");
}
if (!Array.isArray(listeners2)) {
this._events[event] = listeners2 = [listeners2];
}
listeners2.unshift(listener);
return this;
}
before(event, target, listener) {
return this.beforeOrAfter(event, target, listener);
}
after(event, target, listener) {
return this.beforeOrAfter(event, target, listener, "after");
}
beforeOrAfter(event, target, listener, beforeOrAfter) {
let listeners2 = this._events[event] ?? [];
let i;
let index;
const add = beforeOrAfter === "after" ? 1 : 0;
if (typeof listener !== "function") {
throw new TypeError("listener must be a function");
}
if (typeof target !== "function") {
throw new TypeError("target must be a function");
}
if (!Array.isArray(listeners2)) {
this._events[event] = listeners2 = [listeners2];
}
index = listeners2.length;
for (i = listeners2.length; i--; ) {
if (listeners2[i] === target) {
index = i + add;
break;
}
}
listeners2.splice(index, 0, listener);
return this;
}
on(event, listener) {
return super.on(event, listener);
}
addListener(event, listener) {
return super.addListener(event, listener);
}
prependListener(event, listener) {
return super.prependListener(event, listener);
}
prependOnceListener(event, listener) {
return super.prependOnceListener(event, listener);
}
removeAllListeners(event) {
return super.removeAllListeners(event);
}
removeListener(event, listener) {
return super.removeListener(event, listener);
}
eventNames() {
return super.eventNames();
}
listeners(event) {
return super.listeners(event);
}
listenerCount(event) {
return super.listenerCount(event);
}
getMaxListeners() {
return super.getMaxListeners();
}
setMaxListeners(maxListeners) {
return super.setMaxListeners(maxListeners);
}
}
const sha256 = wrapHash(sha256$1);
const computeVersionedHash = (commitment, blobCommitmentVersion) => {
const computedVersionedHash = new Uint8Array(32);
computedVersionedHash.set([blobCommitmentVersion], 0);
computedVersionedHash.set(sha256(commitment).subarray(1), 1);
return computedVersionedHash;
};
var VerkleLeafType;
(function(VerkleLeafType2) {
VerkleLeafType2[VerkleLeafType2["BasicData"] = 0] = "BasicData";
VerkleLeafType2[VerkleLeafType2["CodeHash"] = 1] = "CodeHash";
})(VerkleLeafType = VerkleLeafType || (VerkleLeafType = {}));
const VERKLE_BASIC_DATA_LEAF_KEY = intToBytes(VerkleLeafType.BasicData);
const VERKLE_CODE_HASH_LEAF_KEY = intToBytes(VerkleLeafType.CodeHash);
const VERKLE_CODE_CHUNK_SIZE = 31;
const VERKLE_HEADER_STORAGE_OFFSET = 64;
const VERKLE_CODE_OFFSET = 128;
const VERKLE_NODE_WIDTH = 256;
const VERKLE_MAIN_STORAGE_OFFSET = BigInt(256) ** BigInt(VERKLE_CODE_CHUNK_SIZE);
function getVerkleTreeIndicesForStorageSlot(storageKey) {
let position;
if (storageKey < VERKLE_CODE_OFFSET - VERKLE_HEADER_STORAGE_OFFSET) {
position = BigInt(VERKLE_HEADER_STORAGE_OFFSET) + storageKey;
} else {
position = VERKLE_MAIN_STORAGE_OFFSET + storageKey;
}
const treeIndex = position / BigInt(VERKLE_NODE_WIDTH);
const subIndex = Number(position % BigInt(VERKLE_NODE_WIDTH));
return { treeIndex, subIndex };
}
let TABLE = [
0,
1996959894,
3993919788,
2567524794,
124634137,
1886057615,
3915621685,
2657392035,
249268274,
2044508324,
3772115230,
2547177864,
162941995,
2125561021,
3887607047,
2428444049,
498536548,
1789927666,
4089016648,
2227061214,
450548861,
1843258603,
4107580753,
2211677639,
325883990,
1684777152,
4251122042,
2321926636,
335633487,
1661365465,
4195302755,
2366115317,
997073096,
1281953886,
3579855332,
2724688242,
1006888145,
1258607687,
3524101629,
2768942443,
901097722,
1119000684,
3686517206,
2898065728,
853044451,
1172266101,
3705015759,
2882616665,
651767980,
1373503546,
3369554304,
3218104598,
565507253,
1454621731,
3485111705,
3099436303,
671266974,
1594198024,
3322730930,
2970347812,
795835527,
1483230225,
3244367275,
3060149565,
1994146192,
31158534,
2563907772,
4023717930,
1907459465,
112637215,
2680153253,
3904427059,
2013776290,
251722036,
2517215374,
3775830040,
2137656763,
141376813,
2439277719,
3865271297,
1802195444,
476864866,
2238001368,
4066508878,
1812370925,
453092731,
2181625025,
4111451223,
1706088902,
314042704,
2344532202,
4240017532,
1658658271,
366619977,
2362670323,
4224994405,
1303535960,
984961486,
2747007092,
3569037538,
1256170817,
1037604311,
2765210733,
3554079995,
1131014506,
879679996,
2909243462,
3663771856,
1141124467,
855842277,
2852801631,
3708648649,
1342533948,
654459306,
3188396048,
3373015174,
1466479909,
544179635,
3110523913,
3462522015,
1591671054,
702138776,
2966460450,
3352799412,
1504918807,
783551873,
3082640443,
3233442989,
3988292384,
2596254646,
62317068,
1957810842,
3939845945,
2647816111,
81470997,
1943803523,
3814918930,
2489596804,
225274430,
2053790376,
3826175755,
2466906013,
167816743,
2097651377,
4027552580,
2265490386,
503444072,
1762050814,
4150417245,
2154129355,
426522225,
1852507879,
4275313526,
2312317920,
282753626,
1742555852,
4189708143,
2394877945,
397917763,
1622183637,
3604390888,
2714866558,
953729732,
1340076626,
3518719985,
2797360999,
1068828381,
1219638859,
3624741850,
2936675148,
906185462,
1090812512,
3747672003,
2825379669,
829329135,
1181335161,
3412177804,
3160834842,
628085408,
1382605366,
3423369109,
3138078467,
570562233,
1426400815,
3317316542,
2998733608,
733239954,
1555261956,
3268935591,
3050360625,
752459403,
1541320221,
2607071920,
3965973030,
1969922972,
40735498,
2617837225,
3943577151,
1913087877,
83908371,
2512341634,
3803740692,
2075208622,
213261112,
2463272603,
3855990285,
2094854071,
198958881,
2262029012,
4057260610,
1759359992,
534414190,
2176718541,
4139329115,
1873836001,
414664567,
2282248934,
4279200368,
1711684554,
285281116,
2405801727,
4167216745,
1634467795,
376229701,
2685067896,
3608007406,
1308918612,
956543938,
2808555105,
3495958263,
1231636301,
1047427035,
2932959818,
3654703836,
1088359270,
936918e3,
2847714899,
3736837829,
1202900863,
817233897,
3183342108,
3401237130,
1404277552,
615818150,
3134207493,
3453421203,
1423857449,
601450431,
3009837614,
3294710456,
1567103746,
711928724,
3020668471,
3272380065,
1510334235,
755167117
];
if (typeof Int32Array !== "undefined") {
TABLE = new Int32Array(TABLE);
}
const crc = (current, previous) => {
let crc2 = ~~previous ^ -1;
for (let index = 0; index < current.length; index++) {
crc2 = TABLE[(crc2 ^ current[index]) & 255] ^ crc2 >>> 8;
}
return crc2 ^ -1;
};
const crc32 = (current, previous) => {
return crc(current, previous) >>> 0;
};
var Chain;
(function(Chain2) {
Chain2[Chain2["Mainnet"] = 1] = "Mainnet";
Chain2[Chain2["Goerli"] = 5] = "Goerli";
Chain2[Chain2["Sepolia"] = 11155111] = "Sepolia";
Chain2[Chain2["Holesky"] = 17e3] = "Holesky";
Chain2[Chain2["Kaustinen6"] = 69420] = "Kaustinen6";
})(Chain = Chain || (Chain = {}));
({
[Chain.Mainnet]: {
name: "mainnet",
blockNumber: BIGINT_0,
stateRoot: hexToBytes$1("0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544")
},
[Chain.Goerli]: {
name: "goerli",
blockNumber: BIGINT_0,
stateRoot: hexToBytes$1("0x5d6cded585e73c4e322c30c2f782a336316f17dd85a4863b9d838d2d4b8b3008")
},
[Chain.Sepolia]: {
name: "sepolia",
blockNumber: BIGINT_0,
stateRoot: hexToBytes$1("0x5eb6e371a698b8d68f665192350ffcecbbbf322916f4b51bd79bb6887da3f494")
},
[Chain.Holesky]: {
name: "holesky",
blockNumber: BIGINT_0,
stateRoot: hexToBytes$1("0x69d8c9d72f6fa4ad42d4702b433707212f90db395eb54dc20bc85de253788783")
},
[Chain.Kaustinen6]: {
name: "kaustinen6",
blockNumber: BIGINT_0,
stateRoot: hexToBytes$1("0x1fbf85345a3cbba9a6d44f991b721e55620a22397c2a93ee8d5011136ac300ee")
}
});
var Hardfork;
(function(Hardfork2) {
Hardfork2["Chainstart"] = "chainstart";
Hardfork2["Homestead"] = "homestead";
Hardfork2["Dao"] = "dao";
Hardfork2["TangerineWhistle"] = "tangerineWhistle";
Hardfork2["SpuriousDragon"] = "spuriousDragon";
Hardfork2["Byzantium"] = "byzantium";
Hardfork2["Constantinople"] = "constantinople";
Hardfork2["Petersburg"] = "petersburg";
Hardfork2["Istanbul"] = "istanbul";
Hardfork2["MuirGlacier"] = "muirGlacier";
Hardfork2["Berlin"] = "berlin";
Hardfork2["London"] = "london";
Hardfork2["ArrowGlacier"] = "arrowGlacier";
Hardfork2["GrayGlacier"] = "grayGlacier";
Hardfork2["MergeForkIdTransition"] = "mergeForkIdTransition";
Hardfork2["Paris"] = "paris";
Hardfork2["Shanghai"] = "shanghai";
Hardfork2["Cancun"] = "cancun";
Hardfork2["Prague"] = "prague";
Hardfork2["Osaka"] = "osaka";
})(Hardfork = Hardfork || (Hardfork = {}));
var ConsensusType;
(function(ConsensusType2) {
ConsensusType2["ProofOfStake"] = "pos";
ConsensusType2["ProofOfWork"] = "pow";
ConsensusType2["ProofOfAuthority"] = "poa";
})(ConsensusType = ConsensusType || (ConsensusType = {}));
var ConsensusAlgorithm;
(function(ConsensusAlgorithm2) {
ConsensusAlgorithm2["Ethash"] = "ethash";
ConsensusAlgorithm2["Clique"] = "clique";
ConsensusAlgorithm2["Casper"] = "casper";
})(ConsensusAlgorithm = ConsensusAlgorithm || (ConsensusAlgorithm = {}));
const eipsDict = {
/**
* Frontier/Chainstart
* (there is no Meta-EIP currently for Frontier, so 1 was chosen)
*/
1: {
minimumHardfork: Hardfork.Chainstart
},
/**
* Homestead HF Meta EIP
*/
606: {
minimumHardfork: Hardfork.Chainstart
},
/**
* TangerineWhistle HF Meta EIP
*/
608: {
minimumHardfork: Hardfork.Homestead
},
/**
* Spurious Dragon HF Meta EIP
*/
607: {
minimumHardfork: Hardfork.TangerineWhistle
},
/**
* Byzantium HF Meta EIP
*/
609: {
minimumHardfork: Hardfork.SpuriousDragon
},
/**
* Constantinople HF Meta EIP
*/
1013: {
minimumHardfork: Hardfork.Constantinople
},
/**
* Petersburg HF Meta EIP
*/
1716: {
minimumHardfork: Hardfork.Constantinople
},
/**
* Istanbul HF Meta EIP
*/
1679: {
minimumHardfork: Hardfork.Constantinople
},
/**
* MuirGlacier HF Meta EIP
*/
2384: {
minimumHardfork: Hardfork.Istanbul
},
/**
* Description : SWAPN, DUPN and EXCHANGE instructions
* URL : https://github.com/ethereum/EIPs/blob/bd421962b4e241aa2b00a85d9cf4e57770bdb954/EIPS/eip-663.md
* Status : Review
*/
663: {
minimumHardfork: Hardfork.Chainstart,
requiredEIPs: [3540, 5450]
},
/**
* Description : Transient storage opcodes
* URL : https://eips.ethereum.org/EIPS/eip-1153
* Status : Final
*/
1153: {
minimumHardfork: Hardfork.Chainstart
},
/**
* Description : Fee market change for ETH 1.0 chain
* URL : https://eips.ethereum.org/EIPS/eip-1559
* Status : Final
*/
1559: {
minimumHardfork: Hardfork.Berlin,
requiredEIPs: [2930]
},
/**
* Description : ModExp gas cost
* URL : https://eips.ethereum.org/EIPS/eip-2565
* Status : Final
*/
2565: {
minimumHardfork: Hardfork.Byzantium
},
/**
* Description : BLS12-381 precompiles
* URL : https://eips.ethereum.org/EIPS/eip-2537
* Status : Review
*/
2537: {
minimumHardfork: Hardfork.Chainstart
},
/**
* Description : Typed Transaction Envelope
* URL : https://eips.ethereum.org/EIPS/eip-2718
* Status : Final
*/
2718: {
minimumHardfork: Hardfork.Chainstart
},
/**
* Description : Gas cost increases for state access opcodes
* URL : https://eips.ethereum.org/EIPS/eip-2929
* Status : Final
*/
2929: {
minimumHardfork: Hardfork.Chainstart
},
/**
* Description : Optional access lists
* URL : https://eips.ethereum.org/EIPS/eip-2930
* Status : Final
*/
2930: {
minimumHardfork: Hardfork.Istanbul,
requiredEIPs: [2718, 2929]
},
/**
* Description : Save historical block hashes in state (Verkle related usage, UNSTABLE)
* URL : https://github.com/gballet/EIPs/pull/3/commits/2e9ac09a142b0d9fb4db0b8d4609f92e5d9990c5
* Status : Draft
*/
2935: {
minimumHardfork: Hardfork.Chainstart
},
/**
* Description : BASEFEE opcode
* URL : https://eips.ethereum.org/EIPS/eip-3198
* Status : Final
*/
3198: {
minimumHardfork: Hardfork.London
},
/**
* Description : Reduction in refunds
* URL : https://eips.ethereum.org/EIPS/eip-3529
* Status : Final
*/
3529: {
minimumHardfork: Hardfork.Berlin,
requiredEIPs: [2929]
},
/**
* Description : EVM Object Format (EOF) v1
* URL : https://github.com/ethereum/EIPs/blob/bd421962b4e241aa2b00a85d9cf4e57770bdb954/EIPS/eip-3540.md
* Status : Review
*/
3540: {
minimumHardfork: Hardfork.London,
requiredEIPs: [3541, 3860]
},
/**
* Description : Reject new contracts starting with the 0xEF byte
* URL : https://eips.ethereum.org/EIPS/eip-3541
* Status : Final
*/
3541: {
minimumHardfork: Hardfork.Berlin
},
/**
* Description : Difficulty Bomb Delay to December 1st 2021
* URL : https://eips.ethereum.org/EIPS/eip-3554
* Status : Final
*/
3554: {
minimumHardfork: Hardfork.MuirGlacier
},
/**
* Description : Reject transactions from senders with deployed code
* URL : https://eips.ethereum.org/EIPS/eip-3607
* Status : Final
*/
3607: {
minimumHardfork: Hardfork.Chainstart
},
/**
* Description : Warm COINBASE
* URL : https://eips.ethereum.org/EIPS/eip-3651
* Status : Final
*/
3651: {
minimumHardfork: Hardfork.London,
requiredEIPs: [2929]
},
/**
* Description : EOF - Code Validation
* URL : https://github.com/ethereum/EIPs/blob/bd421962b4e241aa2b00a85d9cf4e57770bdb954/EIPS/eip-3670.md
* Status : Review
*/
3670: {
minimumHardfork: Hardfork.London,
requiredEIPs: [3540]
},
/**
* Description : Upgrade consensus to Proof-of-Stake
* URL : https://eips.ethereum.org/EIPS/eip-3675
* Status : Final
*/
3675: {
minimumHardfork: Hardfork.London
},
/**
* Description : PUSH0 instruction
* URL : https://eips.ethereum.org/EIPS/eip-3855
* Status : Final
*/
3855: {
minimumHardfork: Hardfork.Chainstart
},
/**
* Description : Limit and meter initcode
* URL : https://eips.ethereum.org/EIPS/eip-3860
* Status : Final
*/
3860: {
minimumHardfork: Hardfork.SpuriousDragon
},
/**
* Description : EOF - Static relative jumps
* URL : https://github.com/ethereum/EIPs/blob/bd421962b4e241aa2b00a85d9cf4e57770bdb954/EIPS/eip-4200.md
* Status : Review
*/
4200: {
minimumHardfork: Hardfork.London,
requiredEIPs: [3540, 3670]
},
/**
* Description : Difficulty Bomb Delay to June 2022
* URL : https://eips.ethereum.org/EIPS/eip-4345
* Status : Final
*/
4345: {
minimumHardfork: Hardfork.London
},
/**
* Description : Supplant DIFFICULTY opcode with PREVRANDAO
* URL : https://eips.ethereum.org/EIPS/eip-4399
* Status : Final
*/
4399: {
minimumHardfork: Hardfork.London
},
/**
* Description : EOF - Functions
* URL : https://github.com/ethereum/EIPs/blob/bd421962b4e241aa2b00a85d9cf4e57770bdb954/EIPS/eip-4750.md
* Status : Review
*/
4750: {
minimumHardfork: Hardfork.London,
requiredEIPs: [3540, 3670, 5450]
},
/**
* Description : Beacon block root in the EVM
* URL : https://eips.ethereum.org/EIPS/eip-4788
* Status : Final
*/
4788: {
minimumHardfork: Hardfork.Cancun
},
/**
* Description : Shard Blob Transactions
* URL : https://eips.ethereum.org/EIPS/eip-4844
* Status : Final
*/
4844: {
minimumHardfork: Hardfork.Paris,
requiredEIPs: [1559, 2718, 2930, 4895]
},
/**
* Description : Beacon chain push withdrawals as operations
* URL : https://eips.ethereum.org/EIPS/eip-4895
* Status : Final
*/
4895: {
minimumHardfork: Hardfork.Paris
},
/**
* Description : Delaying Difficulty Bomb to mid-September 2022
* URL : https://eips.ethereum.org/EIPS/eip-5133
* Status : Final
*/
5133: {
minimumHardfork: Hardfork.GrayGlacier
},
/**
* Description : EOF - Stack Validation
* URL : https://github.com/ethereum/EIPs/blob/bd421962b4e241aa2b00a85d9cf4e57770bdb954/EIPS/eip-5450.md
* Status : Review
*/
5450: {
minimumHardfork: Hardfork.London,
requiredEIPs: [3540, 3670, 4200, 4750]
},
/**
* Description : MCOPY - Memory copying instruction
* URL : https://eips.ethereum.org/EIPS/eip-5656
* Status : Final
*/
5656: {
minimumHardfork: Hardfork.Shanghai
},
/**
* Description : Supply validator deposits on chain
* URL : https://eips.ethereum.org/EIPS/eip-6110
* Status : Review
*/
6110: {
minimumHardfork: Hardfork.Cancun,
requiredEIPs: [7685]
},
/**
* Description : EOF - JUMPF and non-returning functions
* URL : https://github.com/ethereum/EIPs/blob/bd421962b4e241aa2b00a85d9cf4e57770bdb954/EIPS/eip-6206.md
* Status : Review
*/
6206: {
minimumHardfork: Hardfork.London,
requiredEIPs: [4750, 5450]
},
/**
* Description : SELFDESTRUCT only in same transaction
* URL : https://eips.ethereum.org/EIPS/eip-6780
* Status : Final
*/
6780: {
minimumHardfork: Hardfork.London
},
/**
* Description : Ethereum state using a unified verkle tree (experimental)
* URL : https://github.com/ethereum/EIPs/pull/6800
* Status : Draft
*/
6800: {
minimumHardfork: Hardfork.London
},
/**
* Description : Execution layer triggerable withdrawals (experimental)
* URL : https://github.com/ethereum/EIPs/blob/3b5fcad6b35782f8aaeba7d4ac26004e8fbd720f/EIPS/eip-7002.md
* Status : Review
*/
7002: {
minimumHardfork: Hardfork.Paris,
requiredEIPs: [7685]
},
/**
* Description : Revamped CALL instructions
* URL : https://github.com/ethereum/EIPs/blob/bd421962b4e241aa2b00a85d9cf4e57770bdb954/EIPS/eip-7069.md
* Status : Review
*/
7069: {
minimumHardfork: Hardfork.Berlin,
/* Note: per EIP these are the additionally required EIPs:
EIP 150 - This is the entire Tangerine Whistle hardfork
EIP 211 - (RETURNDATASIZE / RETURNDATACOPY) - Included in Byzantium
EIP 214 - (STATICCALL) - Included in Byzantium
*/
requiredEIPs: [2929]
},
/**
* Description : Increase the MAX_EFFECTIVE_BALANCE -> Execution layer triggered consolidations (experimental)
* URL : https://eips.ethereum.org/EIPS/eip-7251
* Status : Draft
*/
7251: {
minimumHardfork: Hardfork.Paris,
requiredEIPs: [7685]
},
/**
* Description : EOF - Data section access instructions
* URL : https://github.com/ethereum/EIPs/blob/bd421962b4e241aa2b00a85d9cf4e57770bdb954/EIPS/eip-7480.md
* Status : Review
*/
7480: {
minimumHardfork: Hardfork.London,
requiredEIPs: [3540, 3670]
},
/**
* Description : BLOBBASEFEE opcode
* URL : https://eips.ethereum.org/EIPS/eip-7516
* Status : Final
*/
7516: {
minimumHardfork: Hardfork.Paris,
requiredEIPs: [4844]
},
/**
* Description : EOF Contract Creation
* URL : https://github.com/ethereum/EIPs/blob/dd32a34cfe4473bce143641bfffe4fd67e1987ab/EIPS/eip-7620.md
* Status : Review
*/
7620: {
minimumHardfork: Hardfork.London,
/* Note: per EIP these are the additionally required EIPs:
EIP 170 - (Max contract size) - Included in Spurious Dragon
*/
requiredEIPs: [3540, 3541, 3670]
},
/**
* Description : General purpose execution layer requests
* URL : https://eips.ethereum.org/EIPS/eip-7685
* Status : Review
*/
7685: {
// TODO: Set correct minimum hardfork
minimumHardfork: Hardfork.Cancun,
requiredEIPs: [3675]
},
/**
* Description : EVM Object Format (EOFv1) Meta
* URL : https://github.com/ethereum/EIPs/blob/4153e95befd0264082de3c4c2fe3a85cc74d3152/EIPS/eip-7692.md
* Status : Draft
*/
7692: {
minimumHardfork: Hardfork.Cancun,
requiredEIPs: [663, 3540, 3670, 4200, 4750, 5450, 6206, 7069, 7480, 7620, 7698]
},
/**
* Description : EOF - Creation transaction
* URL : https://github.com/ethereum/EIPs/blob/bd421962b4e241aa2b00a85d9cf4e57770bdb954/EIPS/eip-7698.md
* Status : Draft
*/
7698: {
minimumHardfork: Hardfork.London,
requiredEIPs: [3540, 7620]
},
/**
* Description : Set EOA account code for one transaction
* URL : https://github.com/ethereum/EIPs/blob/62419ca3f45375db00b04a368ea37c0bfb05386a/EIPS/eip-7702.md
* Status : Review
*/
7702: {
// TODO: Set correct minimum hardfork
minimumHardfork: Hardfork.Cancun,
requiredEIPs: [2718, 2929, 2930]
},
/**
* Description : Use historical block hashes saved in state for BLOCKHASH
* URL : https://eips.ethereum.org/EIPS/eip-7709
* Status : Final
*/
7709: {
minimumHardfork: Hardfork.Chainstart,
requiredEIPs: [2935]
}
};
const hardforksDict = {
/**
* Description: Start of the Ethereum main chain
* URL : -
* Status : Final
*/
chainstart: {
eips: [1]
},
/**
* Description: Homestead hardfork with protocol and network changes
* URL : https://eips.ethereum.org/EIPS/eip-606
* Status : Final
*/
homestead: {
eips: [606]
},
/**
* Description: DAO rescue hardfork
* URL : https://eips.ethereum.org/EIPS/eip-779
* Status : Final
*/
dao: {
eips: []
},
/**
* Description: Hardfork with gas cost changes for IO-heavy operations
* URL : https://eips.ethereum.org/EIPS/eip-608
* Status : Final
*/
tangerineWhistle: {
eips: [608]
},
/**
* Description: HF with EIPs for simple replay attack protection, EXP cost increase, state trie clearing, contract code size limit
* URL : https://eips.ethereum.org/EIPS/eip-607
* Status : Final
*/
spuriousDragon: {
eips: [607]
},
/**
* Description: Hardfork with new precompiles, instructions and other protocol changes
* URL : https://eips.ethereum.org/EIPS/eip-609
* Status : Final
*/
byzantium: {
eips: [609]
},
/**
* Description: Postponed hardfork including EIP-1283 (SSTORE gas metering changes)
* URL : https://eips.ethereum.org/EIPS/eip-1013
* Status : Final
*/
constantinople: {
eips: [1013]
},
/**
* Description: Aka constantinopleFix, removes EIP-1283, activate together with or after constantinople
* URL : https://eips.ethereum.org/EIPS/eip-1716
* Status : Final
*/
petersburg: {
eips: [1716]
},
/**
* Description: HF targeted for December 2019 following the Constantinople/Petersburg HF
* URL : https://eips.ethereum.org/EIPS/eip-1679
* Status : Final
*/
istanbul: {
eips: [1679]
},
/**
* Description: HF to delay the difficulty bomb
* URL : https://eips.ethereum.org/EIPS/eip-2384
* Status : Final
*/
muirGlacier: {
eips: [2384]
},
/**
* Description: HF targeted for July 2020 following the Muir Glacier HF
* URL : https://eips.ethereum.org/EIPS/eip-2070
* Status : Final
*/
berlin: {
eips: [2565, 2929, 2718, 2930]
},
/**
* Description: HF targeted for July 2021 following the Berlin fork
* URL : https://github.com/ethereum/eth1.0-specs/blob/master/network-upgrades/mainnet-upgrades/london.md
* Status : Final
*/
london: {
eips: [1559, 3198, 3529, 3541]
},
/**
* Description: HF to delay the difficulty bomb
* URL : https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/arrow-glacier.md
* Status : Final
*/
arrowGlacier: {
eips: [4345]
},
/**
* Description: Delaying the difficulty bomb to Mid September 2022
* URL : https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md
* Status : Final
*/
grayGlacier: {
eips: [5133]
},
/**
* Description: Hardfork to upgrade the consensus mechanism to Proof-of-Stake
* URL : https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/merge.md
* Status : Final
*/
paris: {
consensus: {
type: "pos",
algorithm: "casper",
casper: {}
},
eips: [3675, 4399]
},
/**
* Description: Pre-merge hardfork to fork off non-upgraded clients
* URL : https://eips.ethereum.org/EIPS/eip-3675
* Status : Final
*/
mergeForkIdTransition: {
eips: []
},
/**
* Description: Next feature hardfork after the merge hardfork having withdrawals, warm coinbase, push0, limit/meter initcode
* URL : https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md
* Status : Final
*/
shanghai: {
eips: [3651, 3855, 3860, 4895]
},
/**
* Description: Next feature hardfork after shanghai, includes proto-danksharding EIP 4844 blobs
* (still WIP hence not for production use), transient storage opcodes, parent beacon block root
* availability in EVM, selfdestruct only in same transaction, and blob base fee opcode
* URL : https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/cancun.md
* Status : Final
*/
cancun: {
eips: [1153, 4844, 4788, 5656, 6780, 7516]
},
/**
* Description: Next feature hardfork after cancun, internally used for pectra testing/implementation (incomplete/experimental)
* URL : https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/prague.md
* Status : Final
*/
prague: {
// TODO update this accordingly to the right devnet setup
//eips: [663, 3540, 3670, 4200, 4750, 5450, 6206, 7069, 7480, 7620, 7692, 7698], // This is EOF-only
eips: [2537, 2935, 6110, 7002, 7251, 7685, 7702]
// This is current prague without EOF
},
/**
* Description: Next feature hardfork after prague, internally used for verkle testing/implementation (incomplete/experimental)
* URL : https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/osaka.md
* Status : Final
*/
osaka: {
eips: [2935, 6800]
}
};
class Common {
constructor(opts) {
this._eips = [];
this._paramsCache = {};
this._activatedEIPsCache = [];
this.events = new eventsExports.EventEmitter();
this._chainParams = JSON.parse(JSON.stringify(opts.chain));
this.DEFAULT_HARDFORK = this._chainParams.defaultHardfork ?? Hardfork.Cancun;
this.HARDFORK_CHANGES = this.hardforks().map((hf) => [
hf.name,
hardforksDict[hf.name] ?? (this._chainParams.customHardforks && this._chainParams.customHardforks[hf.name])
]);
this._hardfork = this.DEFAULT_HARDFORK;
this._params = opts.params ? JSON.parse(JSON.stringify(opts.params)) : {};
if (opts.hardfork !== void 0) {
this.setHardfork(opts.hardfork);
}
if (opts.eips) {
this.setEIPs(opts.eips);
}
this.customCrypto = opts.customCrypto ?? {};
if (Object.keys(this._paramsCache).length === 0) {
this._buildParamsCache();
this._buildActivatedEIPsCache();
}
}
/**
* Update the internal Common EIP params set. Existing values
* will get preserved unless there is a new value for a parameter
* provided with params.
*
* Example Format:
*
* ```ts
* {
* 1559: {
* initialBaseFee: 1000000000,
* }
* }
* ```
*
* @param params
*/
updateParams(params) {
for (const [eip, paramsConfig] of Object.entries(params)) {
if (!(eip in this._params)) {
this._params[eip] = JSON.parse(JSON.stringify(paramsConfig));
} else {
this._params[eip] = JSON.parse(JSON.stringify({ ...this._params[eip], ...params[eip] }));
}
}
this._buildParamsCache();
}
/**
* Fully resets the internal Common EIP params set with the values provided.
*
* Example Format:
*
* ```ts
* {
* 1559: {
* initialBaseFee: 1000000000,
* }
* }
* ```
*
* @param params
*/
resetParams(params) {
this._params = JSON.parse(JSON.stringify(params));
this._buildParamsCache();
}
/**
* Sets the hardfork to get params for
* @param hardfork String identifier (e.g. 'byzantium') or {@link Hardfork} enum
*/
setHardfork(hardfork) {
let existing = false;
for (const hfChanges of this.HARDFORK_CHANGES) {
if (hfChanges[0] === hardfork) {
if (this._hardfork !== hardfork) {
this._hardfork = hardfork;
this._buildParamsCache();
this._buildActivatedEIPsCache();
this.events.emit("hardforkChanged", hardfork);
}
existing = true;
}
}
if (!existing) {
throw new Error(`Hardfork with name ${hardfork} not supported`);
}
}
/**
* Returns the hardfork either based on block number (older HFs) or
* timestamp (Shanghai upwards).
*
* @param Opts Block number or timestamp
* @returns The name of the HF
*/
getHardforkBy(opts) {
const blockNumber = toType(opts.blockNumber, TypeOutput.BigInt);
const timestamp = toType(opts.timestamp, TypeOutput.BigInt);
const hfs = this.hardforks().filter((hf) => hf.block !== null || hf.timestamp !== void 0);
let hfIndex = hfs.findIndex((hf) => blockNumber !== void 0 && hf.block !== null && BigInt(hf.block) > blockNumber || timestamp !== void 0 && hf.timestamp !== void 0 && BigInt(hf.timestamp) > timestamp);
if (hfIndex === -1) {
hfIndex = hfs.length;
} else if (hfIndex === 0) {
throw Error("Must have at least one hardfork at block 0");
}
if (timestamp === void 0) {
const stepBack = hfs.slice(0, hfIndex).reverse().findIndex((hf) => hf.block !== null);
hfIndex = hfIndex - stepBack;
}
hfIndex = hfIndex - 1;
const hfStartIndex = hfIndex;
for (; hfIndex < hfs.length - 1; hfIndex++) {
if (hfs[hfIndex].block !== hfs[hfIndex + 1].block || hfs[hfIndex].timestamp !== hfs[hfIndex + 1].timestamp) {
break;
}
}
if (timestamp !== void 0) {
const minTimeStamp = hfs.slice(0, hfStartIndex).reduce((acc, hf) => Math.max(Number(hf.timestamp ?? "0"), acc), 0);
if (minTimeStamp > timestamp) {
throw Error(`Maximum HF determined by timestamp is lower than the block number HF`);
}
const maxTimeStamp = hfs.slice(hfIndex + 1).reduce((acc, hf) => Math.min(Number(hf.timestamp ?? timestamp), acc), Number(timestamp));
if (maxTimeStamp < timestamp) {
throw Error(`Maximum HF determined by block number is lower than timestamp HF`);
}
}
const hardfork = hfs[hfIndex];
return hardfork.name;
}
/**
* Sets a new hardfork either based on block number (older HFs) or
* timestamp (Shanghai upwards).
*
* @param Opts Block number or timestamp
* @returns The name of the HF set
*/
setHardforkBy(opts) {
const hardfork = this.getHardforkBy(opts);
this.setHardfork(hardfork);
return hardfork;
}
/**
* Internal helper function, returns the params for the given hardfork for the chain set
* @param hardfork Hardfork name
* @returns Dictionary with hardfork params or null if hardfork not on chain
*/
_getHardfork(hardfork) {
const hfs = this.hardforks();
for (const hf of hfs) {
if (hf["name"] === hardfork)
return hf;
}
return null;
}
/**
* Sets the active EIPs
* @param eips
*/
setEIPs(eips = []) {
for (const eip of eips) {
if (!(eip in eipsDict)) {
throw new Error(`${eip} not supported`);
}
const minHF = this.gteHardfork(eipsDict[eip]["minimumHardfork"]);
if (!minHF) {
throw new Error(`${eip} cannot be activated on hardfork ${this.hardfork()}, minimumHardfork: ${minHF}`);
}
}
this._eips = eips;
this._buildParamsCache();
this._buildActivatedEIPsCache();
for (const eip of eips) {
if (eipsDict[eip].requiredEIPs !== void 0) {
for (const elem of eipsDict[eip].requiredEIPs) {
if (!(eips.includes(elem) || this.isActivatedEIP(elem))) {
throw new Error(`${eip} requires EIP ${elem}, but is not included in the EIP list`);
}
}
}
}
}
/**
* Internal helper for _buildParamsCache()
*/
_mergeWithParamsCache(params) {
this._paramsCache = {
...this._paramsCache,
...params
};
}
/**
* Build up a cache for all parameter values for the current HF and all activated EIPs
*/
_buildParamsCache() {
this._paramsCache = {};
const hardfork = this.hardfork();
for (const hfChanges of this.HARDFORK_CHANGES) {
if ("eips" in hfChanges[1]) {
const hfEIPs = hfChanges[1]["eips"];
for (const eip of hfEIPs) {
this._mergeWithParamsCache(this._params[eip] ?? {});
}
}
this._mergeWithParamsCache(hfChanges[1].params ?? {});
if (hfChanges[0] === hardfork)
break;
}
for (const eip of this._eips) {
this._mergeWithParamsCache(this._params[eip] ?? {});
}
}
_buildActivatedEIPsCache() {
this._activatedEIPsCache = [];
for (const [name, hf] of this.HARDFORK_CHANGES) {
if (this.gteHardfork(name) && "eips" in hf) {
this._activatedEIPsCache = this._activatedEIPsCache.concat(hf["eips"]);
}
}
this._activatedEIPsCache = this._activatedEIPsCache.concat(this._eips);
}
/**
* Returns a parameter for the current chain setup
*
* If the parameter is present in an EIP, the EIP always takes precedence.
* Otherwise the parameter is taken from the latest applied HF with
* a change on the respective parameter.
*
* @param name Parameter name (e.g. 'minGasLimit')
* @returns The value requested (throws if not found)
*/
param(name) {
if (!(name in this._paramsCache)) {
throw new Error(`Missing parameter value for ${name}`);
}
const value = this._paramsCache[name];
return BigInt(value ?? 0);
}
/**
* Returns the parameter corresponding to a hardfork
* @param name Parameter name (e.g. 'minGasLimit')
* @param hardfork Hardfork name
* @returns The value requested (throws if not found)
*/
paramByHardfork(name, hardfork) {
var _a;
let value;
for (const hfChanges of this.HARDFORK_CHANGES) {
if ("eips" in hfChanges[1]) {
const hfEIPs = hfChanges[1]["eips"];
for (const eip of hfEIPs) {
const eipParams = this._params[eip];
const eipValue = eipParams == null ? void 0 : eipParams[name];
if (eipValue !== void 0) {
value = eipValue;
}
}
} else {
const hfValue = (_a = hfChanges[1].params) == null ? void 0 : _a[name];
if (hfValue !== void 0) {
value = hfValue;
}
}
if (hfChanges[0] === hardfork)
break;
}
if (value === void 0) {
throw new Error(`Missing parameter value for ${name}`);
}
return BigInt(value ?? 0);
}
/**
* Returns a parameter corresponding to an EIP
* @param name Parameter name (e.g. 'minGasLimit' for 'gasConfig' topic)
* @param eip Number of the EIP
* @returns The value requested (throws if not found)
*/
paramByEIP(name, eip) {
if (!(eip in eipsDict)) {
throw new Error(`${eip} not supported`);
}
const eipParams = this._params[eip];
if ((eipParams == null ? void 0 : eipParams[name]) === void 0) {
throw new Error(`Missing parameter value for ${name}`);
}
const value = eipParams[name];
return BigInt(value ?? 0);
}
/**
* Returns a parameter for the hardfork active on block number or
* optional provided total difficulty (Merge HF)
* @param name Parameter name
* @param blockNumber Block number
* * @returns The value requested or `BigInt(0)` if not found
*/
paramByBlock(name, blockNumber, timestamp) {
const hardfork = this.getHardforkBy({ blockNumber, timestamp });
return this.paramByHardfork(name, hardfork);
}
/**
* Checks if an EIP is activated by either being included in the EIPs
* manually passed in with the {@link CommonOpts.eips} or in a
* hardfork currently being active
*
* Note: this method only works for EIPs being supported
* by the {@link CommonOpts.eips} constructor option
* @param eip
*/
isActivatedEIP(eip) {
if (this._activatedEIPsCache.includes(eip)) {
return true;
}
return false;
}
/**
* Checks if set or provided hardfork is active on block number
* @param hardfork Hardfork name or null (for HF set)
* @param blockNumber
* @returns True if HF is active on block number
*/
hardforkIsActiveOnBlock(hardfork, blockNumber) {
blockNumber = toType(blockNumber, TypeOutput.BigInt);
hardfork = hardfork ?? this._hardfork;
const hfBlock = this.hardforkBlock(hardfork);
if (typeof hfBlock === "bigint" && hfBlock !== BIGINT_0 && blockNumber >= hfBlock) {
return true;
}
return false;
}
/**
* Alias to hardforkIsActiveOnBlock when hardfork is set
* @param blockNumber
* @returns True if HF is active on block number
*/
activeOnBlock(blockNumber) {
return this.hardforkIsActiveOnBlock(null, blockNumber);
}
/**
* Sequence based check if given or set HF1 is greater than or equal HF2
* @param hardfork1 Hardfork name or null (if set)
* @param hardfork2 Hardfork name
* @param opts Hardfork options
* @returns True if HF1 gte HF2
*/
hardforkGteHardfork(hardfork1, hardfork2) {
hardfork1 = hardfork1 ?? this._hardfork;
const hardforks = this.hardforks();
let posHf1 = -1, posHf2 = -1;
let index = 0;
for (const hf of hardforks) {
if (hf["name"] === hardfork1)
posHf1 = index;
if (hf["name"] === hardfork2)
posHf2 = index;
index += 1;
}
return posHf1 >= posHf2 && posHf2 !== -1;
}
/**
* Alias to hardforkGteHardfork when hardfork is set
* @param hardfork Hardfork name
* @returns True if hardfork set is greater than hardfork provided
*/
gteHardfork(hardfork) {
return this.hardforkGteHardfork(null, hardfork);
}
/**
* Returns the hardfork change block for hardfork provided or set
* @param hardfork Hardfork name, optional if HF set
* @returns Block number or null if unscheduled
*/
hardforkBlock(hardfork) {
var _a;
hardfork = hardfork ?? this._hardfork;
const block = (_a = this._getHardfork(hardfork)) == null ? void 0 : _a["block"];
if (block === void 0 || block === null) {
return null;
}
return BigInt(block);
}
hardforkTimestamp(hardfork) {
var _a;
hardfork = hardfork ?? this._hardfork;
const timestamp = (_a = this._getHardfork(hardfork)) == null ? void 0 : _a["timestamp"];
if (timestamp === void 0 || timestamp === null) {
return null;
}
return BigInt(timestamp);
}
/**
* Returns the hardfork change block for eip
* @param eip EIP number
* @returns Block number or null if unscheduled
*/
eipBlock(eip) {
for (const hfChanges of this.HARDFORK_CHANGES) {
const hf = hfChanges[1];
if ("eips" in hf) {
if (hf["eips"].includes(eip)) {
return this.hardforkBlock(hfChanges[0]);
}
}
}
return null;
}
/**
* Returns the scheduled timestamp of the EIP (if scheduled and scheduled by timestamp)
* @param eip EIP number
* @returns Scheduled timestamp. If this EIP is unscheduled, or the EIP is scheduled by block number, then it returns `null`.
*/
eipTimestamp(eip) {
for (const hfChanges of this.HARDFORK_CHANGES) {
const hf = hfChanges[1];
if ("eips" in hf) {
if (hf["eips"].includes(eip)) {
return this.hardforkTimestamp(hfChanges[0]);
}
}
}
return null;
}
/**
* Returns the change block for the next hardfork after the hardfork provided or set
* @param hardfork Hardfork name, optional if HF set
* @returns Block timestamp, number or null if not available
*/
nextHardforkBlockOrTimestamp(hardfork) {
hardfork = hardfork ?? this._hardfork;
const hfs = this.hardforks();
let hfIndex = hfs.findIndex((hf) => hf.name === hardfork);
if (hardfork === Hardfork.Paris) {
hfIndex -= 1;
}
if (hfIndex < 0) {
return null;
}
let currHfTimeOrBlock = hfs[hfIndex].timestamp ?? hfs[hfIndex].block;
currHfTimeOrBlock = currHfTimeOrBlock !== null && currHfTimeOrBlock !== void 0 ? Number(currHfTimeOrBlock) : null;
const nextHf = hfs.slice(hfIndex + 1).find((hf) => {
let hfTimeOrBlock = hf.timestamp ?? hf.block;
hfTimeOrBlock = hfTimeOrBlock !== null && hfTimeOrBlock !== void 0 ? Number(hfTimeOrBlock) : null;
return hf.name !== Hardfork.Paris && hfTimeOrBlock !== null && hfTimeOrBlock !== void 0 && hfTimeOrBlock !== currHfTimeOrBlock;
});
if (nextHf === void 0) {
return null;
}
const nextHfBlock = nextHf.timestamp ?? nextHf.block;
if (nextHfBlock === null || nextHfBlock === void 0) {
return null;
}
return BigInt(nextHfBlock);
}
/**
* Internal helper function to calculate a fork hash
* @param hardfork Hardfork name
* @param genesisHash Genesis block hash of the chain
* @returns Fork hash as hex string
*/
_calcForkHash(hardfork, genesisHash) {
let hfBytes = new Uint8Array(0);
let prevBlockOrTime = 0;
for (const hf of this.hardforks()) {
const { block, timestamp, name } = hf;
let blockOrTime = timestamp ?? block;
blockOrTime = blockOrTime !== null ? Number(blockOrTime) : null;
if (typeof blockOrTime === "number" && blockOrTime !== 0 && blockOrTime !== prevBlockOrTime && name !== Hardfork.Paris) {
const hfBlockBytes = hexToBytes$1(`0x${blockOrTime.toString(16).padStart(16, "0")}`);
hfBytes = concatBytes$1(hfBytes, hfBlockBytes);
prevBlockOrTime = blockOrTime;
}
if (hf.name === hardfork)
break;
}
const inputBytes = concatBytes$1(genesisHash, hfBytes);
const forkhash = bytesToHex$1(intToBytes(crc32(inputBytes) >>> 0));
return forkhash;
}
/**
* Returns an eth/64 compliant fork hash (EIP-2124)
* @param hardfork Hardfork name, optional if HF set
* @param genesisHash Genesis block hash of the network, optional if already defined and not needed to be calculated
*/
forkHash(hardfork, genesisHash) {
hardfork = hardfork ?? this._hardfork;
const data = this._getHardfork(hardfork);
if (data === null || (data == null ? void 0 : data.block) === null && (data == null ? void 0 : data.timestamp) === void 0) {
const msg = "No fork hash calculation possible for future hardfork";
throw new Error(msg);
}
if ((data == null ? void 0 : data.forkHash) !== null && (data == null ? void 0 : data.forkHash) !== void 0) {
return data.forkHash;
}
if (!genesisHash)
throw new Error("genesisHash required for forkHash calculation");
return this._calcForkHash(hardfork, genesisHash);
}
/**
*
* @param forkHash Fork hash as a hex string
* @returns Array with hardfork data (name, block, forkHash)
*/
hardforkForForkHash(forkHash) {
const resArray = this.hardforks().filter((hf) => {
return hf.forkHash === forkHash;
});
return resArray.length >= 1 ? resArray[resArray.length - 1] : null;
}
/**
* Sets any missing forkHashes on the passed-in {@link Common} instance
* @param common The {@link Common} to set the forkHashes for
* @param genesisHash The genesis block hash
*/
setForkHashes(genesisHash) {
for (const hf of this.hardforks()) {
const blockOrTime = hf.timestamp ?? hf.block;
if ((hf.forkHash === null || hf.forkHash === void 0) && blockOrTime !== null && blockOrTime !== void 0) {
hf.forkHash = this.forkHash(hf.name, genesisHash);
}
}
}
/**
* Returns the Genesis parameters of the current chain
* @returns Genesis dictionary
*/
genesis() {
return this._chainParams.genesis;
}
/**
* Returns the hardforks for current chain
* @returns {Array} Array with arrays of hardforks
*/
hardforks() {
const hfs = this._chainParams.hardforks;
if (this._chainParams.customHardforks !== void 0) {
this._chainParams.customHardforks;
}
return hfs;
}
/**
* Returns bootstrap nodes for the current chain
* @returns {Dictionary} Dict with bootstrap nodes
*/
bootstrapNodes() {
return this._chainParams.bootstrapNodes;
}
/**
* Returns DNS networks for the current chain
* @returns {String[]} Array of DNS ENR urls
*/
dnsNetworks() {
return this._chainParams.dnsNetworks;
}
/**
* Returns the hardfork set
* @returns Hardfork name
*/
hardfork() {
return this._hardfork;
}
/**
* Returns the Id of current chain
* @returns chain Id
*/
chainId() {
return BigInt(this._chainParams.chainId);
}
/**
* Returns the name of current chain
* @returns chain name (lower case)
*/
chainName() {
return this._chainParams.name;
}
/**
* Returns the additionally activated EIPs
* (by using the `eips` constructor option)
* @returns List of EIPs
*/
eips() {
return this._eips;
}
/**
* Returns the consensus type of the network
* Possible values: "pow"|"poa"|"pos"
*
* Note: This value can update along a Hardfork.
*/
consensusType() {
const hardfork = this.hardfork();
let value;
for (const hfChanges of this.HARDFORK_CHANGES) {
if ("consensus" in hfChanges[1]) {
value = hfChanges[1]["consensus"]["type"];
}
if (hfChanges[0] === hardfork)
break;
}
return value ?? this._chainParams["consensus"]["type"];
}
/**
* Returns the concrete consensus implementation
* algorithm or protocol for the network
* e.g. "ethash" for "pow" consensus type,
* "clique" for "poa" consensus type or
* "casper" for "pos" consensus type.
*
* Note: This value can update along a Hardfork.
*/
consensusAlgorithm() {
const hardfork = this.hardfork();
let value;
for (const hfChanges of this.HARDFORK_CHANGES) {
if ("consensus" in hfChanges[1]) {
value = hfChanges[1]["consensus"]["algorithm"];
}
if (hfChanges[0] === hardfork)
break;
}
return value ?? this._chainParams["consensus"]["algorithm"];
}
/**
* Returns a dictionary with consensus configuration
* parameters based on the consensus algorithm
*
* Expected returns (parameters must be present in
* the respective chain JSON files):
*
* ethash: empty object
* clique: period, epoch
* casper: empty object
*
* Note: This value can update along a Hardfork.
*/
consensusConfig() {
const hardfork = this.hardfork();
let value;
for (const hfChanges of this.HARDFORK_CHANGES) {
if ("consensus" in hfChanges[1]) {
const config = hfChanges[1];
const algorithm = config["consensus"]["algorithm"];
value = config["consensus"][algorithm];
}
if (hfChanges[0] === hardfork)
break;
}
return value ?? this._chainParams["consensus"][this.consensusAlgorithm()] ?? {};
}
/**
* Returns a deep copy of this {@link Common} instance.
*/
copy() {
const copy = Object.assign(Object.create(Object.getPrototypeOf(this)), this);
copy.events = new eventsExports.EventEmitter();
return copy;
}
}
var browser = { exports: {} };
var ms;
var hasRequiredMs;
function requireMs() {
if (hasRequiredMs) return ms;
hasRequiredMs = 1;
var s = 1e3;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var w = d * 7;
var y = d * 365.25;
ms = function(val, options) {
options = options || {};
var type = typeof val;
if (type === "string" && val.length > 0) {
return parse(val);
} else if (type === "number" && isFinite(val)) {
return options.long ? fmtLong(val) : fmtShort(val);
}
throw new Error(
"val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
);
};
function parse(str) {
str = String(str);
if (str.length > 100) {
return;
}
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
str
);
if (!match) {
return;
}
var n = parseFloat(match[1]);
var type = (match[2] || "ms").toLowerCase();
switch (type) {
case "years":
case "year":
case "yrs":
case "yr":
case "y":
return n * y;
case "weeks":
case "week":
case "w":
return n * w;
case "days":
case "day":
case "d":
return n * d;
case "hours":
case "hour":
case "hrs":
case "hr":
case "h":
return n * h;
case "minutes":
case "minute":
case "mins":
case "min":
case "m":
return n * m;
case "seconds":
case "second":
case "secs":
case "sec":
case "s":
return n * s;
case "milliseconds":
case "millisecond":
case "msecs":
case "msec":
case "ms":
return n;
default:
return void 0;
}
}
function fmtShort(ms2) {
var msAbs = Math.abs(ms2);
if (msAbs >= d) {
return Math.round(ms2 / d) + "d";
}
if (msAbs >= h) {
return Math.round(ms2 / h) + "h";
}
if (msAbs >= m) {
return Math.round(ms2 / m) + "m";
}
if (msAbs >= s) {
return Math.round(ms2 / s) + "s";
}
return ms2 + "ms";
}
function fmtLong(ms2) {
var msAbs = Math.abs(ms2);
if (msAbs >= d) {
return plural(ms2, msAbs, d, "day");
}
if (msAbs >= h) {
return plural(ms2, msAbs, h, "hour");
}
if (msAbs >= m) {
return plural(ms2, msAbs, m, "minute");
}
if (msAbs >= s) {
return plural(ms2, msAbs, s, "second");
}
return ms2 + " ms";
}
function plural(ms2, msAbs, n, name) {
var isPlural = msAbs >= n * 1.5;
return Math.round(ms2 / n) + " " + name + (isPlural ? "s" : "");
}
return ms;
}
function setup(env) {
createDebug.debug = createDebug;
createDebug.default = createDebug;
createDebug.coerce = coerce;
createDebug.disable = disable;
createDebug.enable = enable;
createDebug.enabled = enabled;
createDebug.humanize = requireMs();
createDebug.destroy = destroy;
Object.keys(env).forEach((key) => {
createDebug[key] = env[key];
});
createDebug.names = [];
createDebug.skips = [];
createDebug.formatters = {};
function selectColor(namespace) {
let hash2 = 0;
for (let i = 0; i < namespace.length; i++) {
hash2 = (hash2 << 5) - hash2 + namespace.charCodeAt(i);
hash2 |= 0;
}
return createDebug.colors[Math.abs(hash2) % createDebug.colors.length];
}
createDebug.selectColor = selectColor;
function createDebug(namespace) {
let prevTime;
let enableOverride = null;
let namespacesCache;
let enabledCache;
function debug2(...args) {
if (!debug2.enabled) {
return;
}
const self = debug2;
const curr = Number(/* @__PURE__ */ new Date());
const ms2 = curr - (prevTime || curr);
self.diff = ms2;
self.prev = prevTime;
self.curr = curr;
prevTime = curr;
args[0] = createDebug.coerce(args[0]);
if (typeof args[0] !== "string") {
args.unshift("%O");
}
let index = 0;
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
if (match === "%%") {
return "%";
}
index++;
const formatter = createDebug.formatters[format];
if (typeof formatter === "function") {
const val = args[index];
match = formatter.call(self, val);
args.splice(index, 1);
index--;
}
return match;
});
createDebug.formatArgs.call(self, args);
const logFn2 = self.log || createDebug.log;
logFn2.apply(self, args);
}
debug2.namespace = namespace;
debug2.useColors = createDebug.useColors();
debug2.color = createDebug.selectColor(namespace);
debug2.extend = extend;
debug2.destroy = createDebug.destroy;
Object.defineProperty(debug2, "enabled", {
enumerable: true,
configurable: false,
get: () => {
if (enableOverride !== null) {
return enableOverride;
}
if (namespacesCache !== createDebug.namespaces) {
namespacesCache = createDebug.namespaces;
enabledCache = createDebug.enabled(namespace);
}
return enabledCache;
},
set: (v) => {
enableOverride = v;
}
});
if (typeof createDebug.init === "function") {
createDebug.init(debug2);
}
return debug2;
}
function extend(namespace, delimiter) {
const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
newDebug.log = this.log;
return newDebug;
}
function enable(namespaces) {
createDebug.save(namespaces);
createDebug.namespaces = namespaces;
createDebug.names = [];
createDebug.skips = [];
let i;
const split2 = (typeof namespaces === "string" ? namespaces : "").split(/[\s,]+/);
const len = split2.length;
for (i = 0; i < len; i++) {
if (!split2[i]) {
continue;
}
namespaces = split2[i].replace(/\*/g, ".*?");
if (namespaces[0] === "-") {
createDebug.skips.push(new RegExp("^" + namespaces.slice(1) + "$"));
} else {
createDebug.names.push(new RegExp("^" + namespaces + "$"));
}
}
}
function disable() {
const namespaces = [
...createDebug.names.map(toNamespace),
...createDebug.skips.map(toNamespace).map((namespace) => "-" + namespace)
].join(",");
createDebug.enable("");
return namespaces;
}
function enabled(name) {
if (name[name.length - 1] === "*") {
return true;
}
let i;
let len;
for (i = 0, len = createDebug.skips.length; i < len; i++) {
if (createDebug.skips[i].test(name)) {
return false;
}
}
for (i = 0, len = createDebug.names.length; i < len; i++) {
if (createDebug.names[i].test(name)) {
return true;
}
}
return false;
}
function toNamespace(regexp) {
return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\.\*\?$/, "*");
}
function coerce(val) {
if (val instanceof Error) {
return val.stack || val.message;
}
return val;
}
function destroy() {
console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
}
createDebug.enable(createDebug.load());
return createDebug;
}
var common = setup;
browser.exports;
(function(module, exports) {
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = localstorage();
exports.destroy = /* @__PURE__ */ (() => {
let warned = false;
return () => {
if (!warned) {
warned = true;
console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
}
};
})();
exports.colors = [
"#0000CC",
"#0000FF",
"#0033CC",
"#0033FF",
"#0066CC",
"#0066FF",
"#0099CC",
"#0099FF",
"#00CC00",
"#00CC33",
"#00CC66",
"#00CC99",
"#00CCCC",
"#00CCFF",
"#3300CC",
"#3300FF",
"#3333CC",
"#3333FF",
"#3366CC",
"#3366FF",
"#3399CC",
"#3399FF",
"#33CC00",
"#33CC33",
"#33CC66",
"#33CC99",
"#33CCCC",
"#33CCFF",
"#6600CC",
"#6600FF",
"#6633CC",
"#6633FF",
"#66CC00",
"#66CC33",
"#9900CC",
"#9900FF",
"#9933CC",
"#9933FF",
"#99CC00",
"#99CC33",
"#CC0000",
"#CC0033",
"#CC0066",
"#CC0099",
"#CC00CC",
"#CC00FF",
"#CC3300",
"#CC3333",
"#CC3366",
"#CC3399",
"#CC33CC",
"#CC33FF",
"#CC6600",
"#CC6633",
"#CC9900",
"#CC9933",
"#CCCC00",
"#CCCC33",
"#FF0000",
"#FF0033",
"#FF0066",
"#FF0099",
"#FF00CC",
"#FF00FF",
"#FF3300",
"#FF3333",
"#FF3366",
"#FF3399",
"#FF33CC",
"#FF33FF",
"#FF6600",
"#FF6633",
"#FF9900",
"#FF9933",
"#FFCC00",
"#FFCC33"
];
function useColors() {
if (typeof window !== "undefined" && window.process && (window.process.type === "renderer" || window.process.__nwjs)) {
return true;
}
if (typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
return false;
}
let m;
return typeof document !== "undefined" && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773
typeof window !== "undefined" && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
typeof navigator !== "undefined" && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker
typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
}
function formatArgs(args) {
args[0] = (this.useColors ? "%c" : "") + this.namespace + (this.useColors ? " %c" : " ") + args[0] + (this.useColors ? "%c " : " ") + "+" + module.exports.humanize(this.diff);
if (!this.useColors) {
return;
}
const c = "color: " + this.color;
args.splice(1, 0, c, "color: inherit");
let index = 0;
let lastC = 0;
args[0].replace(/%[a-zA-Z%]/g, (match) => {
if (match === "%%") {
return;
}
index++;
if (match === "%c") {
lastC = index;
}
});
args.splice(lastC, 0, c);
}
exports.log = console.debug || console.log || (() => {
});
function save(namespaces) {
try {
if (namespaces) {
exports.storage.setItem("debug", namespaces);
} else {
exports.storage.removeItem("debug");
}
} catch (error) {
}
}
function load() {
let r;
try {
r = exports.storage.getItem("debug");
} catch (error) {
}
if (!r && typeof process !== "undefined" && "env" in process) {
r = process.env.DEBUG;
}
return r;
}
function localstorage() {
try {
return localStorage;
} catch (error) {
}
}
module.exports = common(exports);
const { formatters } = module.exports;
formatters.j = function(v) {
try {
return JSON.stringify(v);
} catch (error) {
return "[UnexpectedJSONParseError]: " + error.message;
}
};
})(browser, browser.exports);
var browserExports = browser.exports;
const debugDefault = /* @__PURE__ */ getDefaultExportFromCjs(browserExports);
const EOFBYTES = new Uint8Array([FORMAT, MAGIC]);
const EOFHASH = keccak256(EOFBYTES);
function isEOF(code) {
const check = code.subarray(0, EOFBYTES.length);
return equalsBytes(EOFBYTES, check);
}
var ERROR = /* @__PURE__ */ ((ERROR2) => {
ERROR2["OUT_OF_GAS"] = "out of gas";
ERROR2["CODESTORE_OUT_OF_GAS"] = "code store out of gas";
ERROR2["CODESIZE_EXCEEDS_MAXIMUM"] = "code size to deposit exceeds maximum code size";
ERROR2["STACK_UNDERFLOW"] = "stack underflow";
ERROR2["STACK_OVERFLOW"] = "stack overflow";
ERROR2["INVALID_JUMP"] = "invalid JUMP";
ERROR2["INVALID_OPCODE"] = "invalid opcode";
ERROR2["OUT_OF_RANGE"] = "value out of range";
ERROR2["REVERT"] = "revert";
ERROR2["STATIC_STATE_CHANGE"] = "static state change";
ERROR2["INTERNAL_ERROR"] = "internal error";
ERROR2["CREATE_COLLISION"] = "create collision";
ERROR2["STOP"] = "stop";
ERROR2["REFUND_EXHAUSTED"] = "refund exhausted";
ERROR2["VALUE_OVERFLOW"] = "value overflow";
ERROR2["INSUFFICIENT_BALANCE"] = "insufficient balance";
ERROR2["INVALID_BEGINSUB"] = "invalid BEGINSUB";
ERROR2["INVALID_RETURNSUB"] = "invalid RETURNSUB";
ERROR2["INVALID_JUMPSUB"] = "invalid JUMPSUB";
ERROR2["INVALID_BYTECODE_RESULT"] = "invalid bytecode deployed";
ERROR2["INITCODE_SIZE_VIOLATION"] = "initcode exceeds max initcode size";
ERROR2["INVALID_INPUT_LENGTH"] = "invalid input length";
ERROR2["INVALID_EOF_FORMAT"] = "invalid EOF format";
ERROR2["BLS_12_381_INVALID_INPUT_LENGTH"] = "invalid input length";
ERROR2["BLS_12_381_POINT_NOT_ON_CURVE"] = "point not on curve";
ERROR2["BLS_12_381_INPUT_EMPTY"] = "input is empty";
ERROR2["BLS_12_381_FP_NOT_IN_FIELD"] = "fp point not in field";
ERROR2["BN254_FP_NOT_IN_FIELD"] = "fp point not in field";
ERROR2["INVALID_COMMITMENT"] = "kzg commitment does not match versioned hash";
ERROR2["INVALID_INPUTS"] = "kzg inputs invalid";
ERROR2["INVALID_PROOF"] = "kzg proof invalid";
return ERROR2;
})(ERROR || {});
class EvmError {
constructor(error) {
this.error = error;
this.errorType = "EvmError";
}
}
function setupEOF(runState, eofMode = EOFContainerMode.Default) {
runState.env.eof = {
container: new EOFContainer(runState.code, eofMode),
eofRunState: {
returnStack: []
// Return stack for RETF/CALLF/JUMPF
}
};
if (runState.env.eof.container.body.txCallData !== void 0) {
runState.env.callData = runState.env.eof.container.body.txCallData;
}
const pc = runState.env.eof.container.header.getCodePosition(0);
runState.programCounter = pc;
}
const ceil = (value, ceiling) => {
const r = value % ceiling;
if (r === 0) {
return value;
} else {
return value + ceiling - r;
}
};
const CONTAINER_SIZE = 8192;
class Memory {
constructor() {
this._store = new Uint8Array(CONTAINER_SIZE);
}
/**
* Extends the memory given an offset and size. Rounds extended
* memory to word-size.
*/
extend(offset, size) {
if (size === 0) {
return;
}
const newSize = ceil(offset + size, 32);
const sizeDiff = newSize - this._store.length;
if (sizeDiff > 0) {
const expandBy = Math.ceil(sizeDiff / CONTAINER_SIZE) * CONTAINER_SIZE;
this._store = concatBytes$1(this._store, new Uint8Array(expandBy));
}
}
/**
* Writes a byte array with length `size` to memory, starting from `offset`.
* @param offset - Starting position
* @param size - How many bytes to write
* @param value - Value
*/
write(offset, size, value) {
if (size === 0) {
return;
}
this.extend(offset, size);
if (value.length !== size) throw new Error("Invalid value size");
if (offset + size > this._store.length) throw new Error("Value exceeds memory capacity");
this._store.set(value, offset);
}
/**
* Reads a slice of memory from `offset` till `offset + size` as a `Uint8Array`.
* It fills up the difference between memory's length and `offset + size` with zeros.
* @param offset - Starting position
* @param size - How many bytes to read
* @param avoidCopy - Avoid memory copy if possible for performance reasons (optional)
*/
read(offset, size, avoidCopy) {
this.extend(offset, size);
const loaded = this._store.subarray(offset, offset + size);
if (avoidCopy === true) {
return loaded;
}
const returnBytes = new Uint8Array(size);
returnBytes.set(loaded);
return returnBytes;
}
}
const defaults = {
value: BIGINT_0,
caller: createZeroAddress(),
data: new Uint8Array(0),
depth: 0,
isStatic: false,
isCompiled: false,
delegatecall: false,
gasRefund: BIGINT_0
};
class Message {
constructor(opts) {
this.to = opts.to;
this.value = opts.value ?? defaults.value;
this.caller = opts.caller ?? defaults.caller;
this.gasLimit = opts.gasLimit;
this.data = opts.data ?? defaults.data;
this.eofCallData = opts.eofCallData;
this.depth = opts.depth ?? defaults.depth;
this.code = opts.code;
this._codeAddress = opts.codeAddress;
this.isStatic = opts.isStatic ?? defaults.isStatic;
this.isCompiled = opts.isCompiled ?? defaults.isCompiled;
this.salt = opts.salt;
this.selfdestruct = opts.selfdestruct;
this.createdAddresses = opts.createdAddresses;
this.delegatecall = opts.delegatecall ?? defaults.delegatecall;
this.gasRefund = opts.gasRefund ?? defaults.gasRefund;
this.blobVersionedHashes = opts.blobVersionedHashes;
this.accessWitness = opts.accessWitness;
if (this.value < 0) {
throw new Error(`value field cannot be negative, received ${this.value}`);
}
}
/**
* Note: should only be called in instances where `_codeAddress` or `to` is defined.
*/
get codeAddress() {
const codeAddress = this._codeAddress ?? this.to;
if (!codeAddress) {
throw new Error("Missing codeAddress");
}
return codeAddress;
}
}
class EVMMockBlockchain {
async getBlock() {
return {
hash() {
return zeros(32);
}
};
}
async putBlock() {
}
shallowCopy() {
return this;
}
}
const DELEGATION_7702_FLAG = new Uint8Array([239, 1, 0]);
const MASK_160 = (BIGINT_1 << BIGINT_160) - BIGINT_1;
function createAddressFromStackBigInt(value) {
const maskedValue = value & MASK_160;
return createAddressFromBigInt(maskedValue);
}
function setLengthLeftStorage(value) {
if (equalsBytes(value, new Uint8Array(value.length))) {
return new Uint8Array(0);
} else {
return setLengthLeft(value, 32);
}
}
function trap(err) {
throw new EvmError(err);
}
function describeLocation(runState) {
const keccakFunction = runState.interpreter._evm.common.customCrypto.keccak256 ?? keccak256;
const hash2 = bytesToHex$1(keccakFunction(runState.interpreter.getCode()));
const address = runState.interpreter.getAddress().toString();
const pc = runState.programCounter - 1;
return `${hash2}/${address}:${pc}`;
}
function divCeil(a, b) {
const div = a / b;
const modulus = mod(a, b);
if (modulus === BIGINT_0) return div;
return div < BIGINT_0 ? div - BIGINT_1 : div + BIGINT_1;
}
function getDataSlice(data, offset, length) {
const len = BigInt(data.length);
if (offset > len) {
offset = len;
}
let end = offset + length;
if (end > len) {
end = len;
}
data = data.subarray(Number(offset), Number(end));
data = setLengthRight(data, Number(length));
return data;
}
function getFullname(code, name) {
switch (name) {
case "LOG":
name += code - 160;
break;
case "PUSH":
name += code - 95;
break;
case "DUP":
name += code - 127;
break;
case "SWAP":
name += code - 143;
break;
}
return name;
}
function jumpIsValid(runState, dest) {
return runState.validJumps[dest] === 1;
}
function maxCallGas(gasLimit, gasLeft, runState, common2) {
if (common2.gteHardfork(Hardfork.TangerineWhistle)) {
const gasAllowed = gasLeft - gasLeft / BIGINT_64;
return gasLimit > gasAllowed ? gasAllowed : gasLimit;
} else {
return gasLimit;
}
}
function subMemUsage(runState, offset, length, common2) {
if (length === BIGINT_0) return BIGINT_0;
const newMemoryWordCount = divCeil(offset + length, BIGINT_32);
if (newMemoryWordCount <= runState.memoryWordCount) return BIGINT_0;
const words = newMemoryWordCount;
const fee = common2.param("memoryGas");
const quadCoefficient = common2.param("quadCoefficientDivGas");
let cost = words * fee + words * words / quadCoefficient;
if (cost > runState.highestMemCost) {
const currentHighestMemCost = runState.highestMemCost;
runState.highestMemCost = cost;
cost -= currentHighestMemCost;
}
runState.memoryWordCount = newMemoryWordCount;
return cost;
}
function writeCallOutput(runState, outOffset, outLength) {
const returnData = runState.interpreter.getReturnData();
if (returnData.length > 0) {
const memOffset = Number(outOffset);
let dataLength = Number(outLength);
if (BigInt(returnData.length) < dataLength) {
dataLength = returnData.length;
}
const data = getDataSlice(returnData, BIGINT_0, BigInt(dataLength));
runState.memory.extend(memOffset, dataLength);
runState.memory.write(memOffset, dataLength, data);
}
}
function updateSstoreGas(runState, currentStorage, value, common2) {
if (value.length === 0 && currentStorage.length === 0 || value.length > 0 && currentStorage.length > 0) {
const gas = common2.param("sstoreResetGas");
return gas;
} else if (value.length === 0 && currentStorage.length > 0) {
const gas = common2.param("sstoreResetGas");
runState.interpreter.refundGas(common2.param("sstoreRefundGas"), "updateSstoreGas");
return gas;
} else {
return common2.param("sstoreSetGas");
}
}
function mod(a, b) {
let r = a % b;
if (r < BIGINT_0) {
r = b + r;
}
return r;
}
function fromTwos(a) {
return BigInt.asIntN(256, a);
}
function toTwos(a) {
return BigInt.asUintN(256, a);
}
const N = BigInt(1157920892373162e62);
function exponentiation(bas, exp) {
let t = BIGINT_1;
while (exp > BIGINT_0) {
if (exp % BIGINT_2 !== BIGINT_0) {
t = t * bas % N;
}
bas = bas * bas % N;
exp = exp / BIGINT_2;
}
return t;
}
function getEIP7702DelegatedAddress(code) {
if (equalsBytes(code.slice(0, 3), DELEGATION_7702_FLAG)) {
return new Address(code.slice(3, 24));
}
}
async function eip7702CodeCheck(runState, code) {
const address = getEIP7702DelegatedAddress(code);
if (address !== void 0) {
return runState.stateManager.getCode(address);
}
return code;
}
const handlers = /* @__PURE__ */ new Map([
// 0x00: STOP
[
0,
function() {
trap(ERROR.STOP);
}
],
// 0x01: ADD
[
1,
function(runState) {
const [a, b] = runState.stack.popN(2);
const r = mod(a + b, TWO_POW256);
runState.stack.push(r);
}
],
// 0x02: MUL
[
2,
function(runState) {
const [a, b] = runState.stack.popN(2);
const r = mod(a * b, TWO_POW256);
runState.stack.push(r);
}
],
// 0x03: SUB
[
3,
function(runState) {
const [a, b] = runState.stack.popN(2);
const r = mod(a - b, TWO_POW256);
runState.stack.push(r);
}
],
// 0x04: DIV
[
4,
function(runState) {
const [a, b] = runState.stack.popN(2);
let r;
if (b === BIGINT_0) {
r = BIGINT_0;
} else {
r = mod(a / b, TWO_POW256);
}
runState.stack.push(r);
}
],
// 0x05: SDIV
[
5,
function(runState) {
const [a, b] = runState.stack.popN(2);
let r;
if (b === BIGINT_0) {
r = BIGINT_0;
} else {
r = toTwos(fromTwos(a) / fromTwos(b));
}
runState.stack.push(r);
}
],
// 0x06: MOD
[
6,
function(runState) {
const [a, b] = runState.stack.popN(2);
let r;
if (b === BIGINT_0) {
r = b;
} else {
r = mod(a, b);
}
runState.stack.push(r);
}
],
// 0x07: SMOD
[
7,
function(runState) {
const [a, b] = runState.stack.popN(2);
let r;
if (b === BIGINT_0) {
r = b;
} else {
r = fromTwos(a) % fromTwos(b);
}
runState.stack.push(toTwos(r));
}
],
// 0x08: ADDMOD
[
8,
function(runState) {
const [a, b, c] = runState.stack.popN(3);
let r;
if (c === BIGINT_0) {
r = BIGINT_0;
} else {
r = mod(a + b, c);
}
runState.stack.push(r);
}
],
// 0x09: MULMOD
[
9,
function(runState) {
const [a, b, c] = runState.stack.popN(3);
let r;
if (c === BIGINT_0) {
r = BIGINT_0;
} else {
r = mod(a * b, c);
}
runState.stack.push(r);
}
],
// 0x0a: EXP
[
10,
function(runState) {
const [base, exponent] = runState.stack.popN(2);
if (base === BIGINT_2) {
switch (exponent) {
case BIGINT_96:
runState.stack.push(BIGINT_2EXP96);
return;
case BIGINT_160:
runState.stack.push(BIGINT_2EXP160);
return;
case BIGINT_224:
runState.stack.push(BIGINT_2EXP224);
return;
}
}
if (exponent === BIGINT_0) {
runState.stack.push(BIGINT_1);
return;
}
if (base === BIGINT_0) {
runState.stack.push(base);
return;
}
const r = exponentiation(base, exponent);
runState.stack.push(r);
}
],
// 0x0b: SIGNEXTEND
[
11,
function(runState) {
let [k, val] = runState.stack.popN(2);
if (k < BIGINT_31) {
const signBit = k * BIGINT_8 + BIGINT_7;
const mask = (BIGINT_1 << signBit) - BIGINT_1;
if (val >> signBit & BIGINT_1) {
val = val | BigInt.asUintN(256, ~mask);
} else {
val = val & mask;
}
}
runState.stack.push(val);
}
],
// 0x10 range - bit ops
// 0x10: LT
[
16,
function(runState) {
const [a, b] = runState.stack.popN(2);
const r = a < b ? BIGINT_1 : BIGINT_0;
runState.stack.push(r);
}
],
// 0x11: GT
[
17,
function(runState) {
const [a, b] = runState.stack.popN(2);
const r = a > b ? BIGINT_1 : BIGINT_0;
runState.stack.push(r);
}
],
// 0x12: SLT
[
18,
function(runState) {
const [a, b] = runState.stack.popN(2);
const r = fromTwos(a) < fromTwos(b) ? BIGINT_1 : BIGINT_0;
runState.stack.push(r);
}
],
// 0x13: SGT
[
19,
function(runState) {
const [a, b] = runState.stack.popN(2);
const r = fromTwos(a) > fromTwos(b) ? BIGINT_1 : BIGINT_0;
runState.stack.push(r);
}
],
// 0x14: EQ
[
20,
function(runState) {
const [a, b] = runState.stack.popN(2);
const r = a === b ? BIGINT_1 : BIGINT_0;
runState.stack.push(r);
}
],
// 0x15: ISZERO
[
21,
function(runState) {
const a = runState.stack.pop();
const r = a === BIGINT_0 ? BIGINT_1 : BIGINT_0;
runState.stack.push(r);
}
],
// 0x16: AND
[
22,
function(runState) {
const [a, b] = runState.stack.popN(2);
const r = a & b;
runState.stack.push(r);
}
],
// 0x17: OR
[
23,
function(runState) {
const [a, b] = runState.stack.popN(2);
const r = a | b;
runState.stack.push(r);
}
],
// 0x18: XOR
[
24,
function(runState) {
const [a, b] = runState.stack.popN(2);
const r = a ^ b;
runState.stack.push(r);
}
],
// 0x19: NOT
[
25,
function(runState) {
const a = runState.stack.pop();
const r = BigInt.asUintN(256, ~a);
runState.stack.push(r);
}
],
// 0x1a: BYTE
[
26,
function(runState) {
const [pos, word] = runState.stack.popN(2);
if (pos > BIGINT_32) {
runState.stack.push(BIGINT_0);
return;
}
const r = word >> (BIGINT_31 - pos) * BIGINT_8 & BIGINT_255;
runState.stack.push(r);
}
],
// 0x1b: SHL
[
27,
function(runState) {
const [a, b] = runState.stack.popN(2);
if (a > BIGINT_256) {
runState.stack.push(BIGINT_0);
return;
}
const r = b << a & MAX_INTEGER_BIGINT;
runState.stack.push(r);
}
],
// 0x1c: SHR
[
28,
function(runState) {
const [a, b] = runState.stack.popN(2);
if (a > 256) {
runState.stack.push(BIGINT_0);
return;
}
const r = b >> a;
runState.stack.push(r);
}
],
// 0x1d: SAR
[
29,
function(runState) {
const [a, b] = runState.stack.popN(2);
let r;
const bComp = BigInt.asIntN(256, b);
const isSigned = bComp < 0;
if (a > 256) {
if (isSigned) {
r = MAX_INTEGER_BIGINT;
} else {
r = BIGINT_0;
}
runState.stack.push(r);
return;
}
const c = b >> a;
if (isSigned) {
const shiftedOutWidth = BIGINT_255 - a;
const mask = MAX_INTEGER_BIGINT >> shiftedOutWidth << shiftedOutWidth;
r = c | mask;
} else {
r = c;
}
runState.stack.push(r);
}
],
// 0x20 range - crypto
// 0x20: KECCAK256
[
32,
function(runState, common2) {
const [offset, length] = runState.stack.popN(2);
let data = new Uint8Array(0);
if (length !== BIGINT_0) {
data = runState.memory.read(Number(offset), Number(length));
}
const r = BigInt(bytesToHex$1((common2.customCrypto.keccak256 ?? keccak256)(data)));
runState.stack.push(r);
}
],
// 0x30 range - closure state
// 0x30: ADDRESS
[
48,
function(runState) {
const address = bytesToBigInt(runState.interpreter.getAddress().bytes);
runState.stack.push(address);
}
],
// 0x31: BALANCE
[
49,
async function(runState) {
const addressBigInt = runState.stack.pop();
const address = createAddressFromStackBigInt(addressBigInt);
const balance = await runState.interpreter.getExternalBalance(address);
runState.stack.push(balance);
}
],
// 0x32: ORIGIN
[
50,
function(runState) {
runState.stack.push(runState.interpreter.getTxOrigin());
}
],
// 0x33: CALLER
[
51,
function(runState) {
runState.stack.push(runState.interpreter.getCaller());
}
],
// 0x34: CALLVALUE
[
52,
function(runState) {
runState.stack.push(runState.interpreter.getCallValue());
}
],
// 0x35: CALLDATALOAD
[
53,
function(runState) {
const pos = runState.stack.pop();
if (pos > runState.interpreter.getCallDataSize()) {
runState.stack.push(BIGINT_0);
return;
}
const i = Number(pos);
let loaded = runState.interpreter.getCallData().subarray(i, i + 32);
loaded = loaded.length ? loaded : Uint8Array.from([0]);
let r = bytesToBigInt(loaded);
if (loaded.length < 32) {
r = r << BIGINT_8 * BigInt(32 - loaded.length);
}
runState.stack.push(r);
}
],
// 0x36: CALLDATASIZE
[
54,
function(runState) {
const r = runState.interpreter.getCallDataSize();
runState.stack.push(r);
}
],
// 0x37: CALLDATACOPY
[
55,
function(runState) {
const [memOffset, dataOffset, dataLength] = runState.stack.popN(3);
if (dataLength !== BIGINT_0) {
const data = getDataSlice(runState.interpreter.getCallData(), dataOffset, dataLength);
const memOffsetNum = Number(memOffset);
const dataLengthNum = Number(dataLength);
runState.memory.write(memOffsetNum, dataLengthNum, data);
}
}
],
// 0x38: CODESIZE
[
56,
function(runState) {
runState.stack.push(runState.interpreter.getCodeSize());
}
],
// 0x39: CODECOPY
[
57,
function(runState) {
const [memOffset, codeOffset, dataLength] = runState.stack.popN(3);
if (dataLength !== BIGINT_0) {
const data = getDataSlice(runState.interpreter.getCode(), codeOffset, dataLength);
const memOffsetNum = Number(memOffset);
const lengthNum = Number(dataLength);
runState.memory.write(memOffsetNum, lengthNum, data);
}
}
],
// 0x3b: EXTCODESIZE
[
59,
async function(runState, common2) {
const addressBigInt = runState.stack.pop();
const address = createAddressFromStackBigInt(addressBigInt);
let code = await runState.stateManager.getCode(address);
if (isEOF(code)) {
runState.stack.push(BigInt(EOFBYTES.length));
return;
} else if (common2.isActivatedEIP(7702)) {
code = await eip7702CodeCheck(runState, code);
}
const size = BigInt(code.length);
runState.stack.push(size);
}
],
// 0x3c: EXTCODECOPY
[
60,
async function(runState, common2) {
const [addressBigInt, memOffset, codeOffset, dataLength] = runState.stack.popN(4);
if (dataLength !== BIGINT_0) {
const address = createAddressFromStackBigInt(addressBigInt);
let code = await runState.stateManager.getCode(address);
if (isEOF(code)) {
code = EOFBYTES;
} else if (common2.isActivatedEIP(7702)) {
code = await eip7702CodeCheck(runState, code);
}
const data = getDataSlice(code, codeOffset, dataLength);
const memOffsetNum = Number(memOffset);
const lengthNum = Number(dataLength);
runState.memory.write(memOffsetNum, lengthNum, data);
}
}
],
// 0x3f: EXTCODEHASH
[
63,
async function(runState, common2) {
const addressBigInt = runState.stack.pop();
const address = createAddressFromStackBigInt(addressBigInt);
const code = await runState.stateManager.getCode(address);
if (isEOF(code)) {
runState.stack.push(bytesToBigInt(EOFHASH));
return;
} else if (common2.isActivatedEIP(7702)) {
const possibleDelegatedAddress = getEIP7702DelegatedAddress(code);
if (possibleDelegatedAddress !== void 0) {
const account2 = await runState.stateManager.getAccount(possibleDelegatedAddress);
if (!account2 || account2.isEmpty()) {
runState.stack.push(BIGINT_0);
return;
}
runState.stack.push(BigInt(bytesToHex$1(account2.codeHash)));
return;
} else {
runState.stack.push(bytesToBigInt(keccak256(code)));
return;
}
}
const account = await runState.stateManager.getAccount(address);
if (!account || account.isEmpty()) {
runState.stack.push(BIGINT_0);
return;
}
runState.stack.push(BigInt(bytesToHex$1(account.codeHash)));
}
],
// 0x3d: RETURNDATASIZE
[
61,
function(runState) {
runState.stack.push(runState.interpreter.getReturnDataSize());
}
],
// 0x3e: RETURNDATACOPY
[
62,
function(runState) {
const [memOffset, returnDataOffset, dataLength] = runState.stack.popN(3);
if (dataLength !== BIGINT_0) {
const data = getDataSlice(
runState.interpreter.getReturnData(),
returnDataOffset,
dataLength
);
const memOffsetNum = Number(memOffset);
const lengthNum = Number(dataLength);
runState.memory.write(memOffsetNum, lengthNum, data);
}
}
],
// 0x3a: GASPRICE
[
58,
function(runState) {
runState.stack.push(runState.interpreter.getTxGasPrice());
}
],
// '0x40' range - block operations
// 0x40: BLOCKHASH
[
64,
async function(runState, common2) {
const number2 = runState.stack.pop();
if (common2.isActivatedEIP(7709)) {
if (number2 >= runState.interpreter.getBlockNumber()) {
runState.stack.push(BIGINT_0);
return;
}
const diff = runState.interpreter.getBlockNumber() - number2;
if (diff > BIGINT_256 || diff <= BIGINT_0) {
runState.stack.push(BIGINT_0);
return;
}
const historyAddress = new Address(
bigIntToAddressBytes(common2.param("historyStorageAddress"))
);
const historyServeWindow = common2.param("historyServeWindow");
const key = setLengthLeft(bigIntToBytes(number2 % historyServeWindow), 32);
if (common2.isActivatedEIP(6800)) {
const { treeIndex, subIndex } = getVerkleTreeIndicesForStorageSlot(number2);
const statelessGas = runState.env.accessWitness.touchAddressOnReadAndComputeGas(
historyAddress,
treeIndex,
subIndex
);
runState.interpreter.useGas(statelessGas, `BLOCKHASH`);
}
const storage = await runState.stateManager.getStorage(historyAddress, key);
runState.stack.push(bytesToBigInt(storage));
} else {
const diff = runState.interpreter.getBlockNumber() - number2;
if (diff > BIGINT_256 || diff <= BIGINT_0) {
runState.stack.push(BIGINT_0);
return;
}
const block = await runState.blockchain.getBlock(Number(number2));
runState.stack.push(bytesToBigInt(block.hash()));
}
}
],
// 0x41: COINBASE
[
65,
function(runState) {
runState.stack.push(runState.interpreter.getBlockCoinbase());
}
],
// 0x42: TIMESTAMP
[
66,
function(runState) {
runState.stack.push(runState.interpreter.getBlockTimestamp());
}
],
// 0x43: NUMBER
[
67,
function(runState) {
runState.stack.push(runState.interpreter.getBlockNumber());
}
],
// 0x44: DIFFICULTY (EIP-4399: supplanted as PREVRANDAO)
[
68,
function(runState, common2) {
if (common2.isActivatedEIP(4399)) {
runState.stack.push(runState.interpreter.getBlockPrevRandao());
} else {
runState.stack.push(runState.interpreter.getBlockDifficulty());
}
}
],
// 0x45: GASLIMIT
[
69,
function(runState) {
runState.stack.push(runState.interpreter.getBlockGasLimit());
}
],
// 0x46: CHAINID
[
70,
function(runState) {
runState.stack.push(runState.interpreter.getChainId());
}
],
// 0x47: SELFBALANCE
[
71,
function(runState) {
runState.stack.push(runState.interpreter.getSelfBalance());
}
],
// 0x48: BASEFEE
[
72,
function(runState) {
runState.stack.push(runState.interpreter.getBlockBaseFee());
}
],
// 0x49: BLOBHASH
[
73,
function(runState) {
const index = runState.stack.pop();
if (runState.env.blobVersionedHashes.length > Number(index)) {
runState.stack.push(bytesToBigInt(runState.env.blobVersionedHashes[Number(index)]));
} else {
runState.stack.push(BIGINT_0);
}
}
],
// 0x4a: BLOBBASEFEE
[
74,
function(runState) {
runState.stack.push(runState.interpreter.getBlobBaseFee());
}
],
// 0x50 range - 'storage' and execution
// 0x50: POP
[
80,
function(runState) {
runState.stack.pop();
}
],
// 0x51: MLOAD
[
81,
function(runState) {
const pos = runState.stack.pop();
const word = runState.memory.read(Number(pos), 32, true);
runState.stack.push(bytesToBigInt(word));
}
],
// 0x52: MSTORE
[
82,
function(runState) {
const [offset, word] = runState.stack.popN(2);
const buf = setLengthLeft(bigIntToBytes(word), 32);
const offsetNum = Number(offset);
runState.memory.write(offsetNum, 32, buf);
}
],
// 0x53: MSTORE8
[
83,
function(runState) {
const [offset, byte] = runState.stack.popN(2);
const buf = bigIntToBytes(byte & BIGINT_255);
const offsetNum = Number(offset);
runState.memory.write(offsetNum, 1, buf);
}
],
// 0x54: SLOAD
[
84,
async function(runState) {
const key = runState.stack.pop();
const keyBuf = setLengthLeft(bigIntToBytes(key), 32);
const value = await runState.interpreter.storageLoad(keyBuf);
const valueBigInt = value.length ? bytesToBigInt(value) : BIGINT_0;
runState.stack.push(valueBigInt);
}
],
// 0x55: SSTORE
[
85,
async function(runState) {
const [key, val] = runState.stack.popN(2);
const keyBuf = setLengthLeft(bigIntToBytes(key), 32);
let value;
if (val === BIGINT_0) {
value = Uint8Array.from([]);
} else {
value = bigIntToBytes(val);
}
await runState.interpreter.storageStore(keyBuf, value);
}
],
// 0x56: JUMP
[
86,
function(runState) {
const dest = runState.stack.pop();
if (dest > runState.interpreter.getCodeSize()) {
trap(ERROR.INVALID_JUMP + " at " + describeLocation(runState));
}
const destNum = Number(dest);
if (!jumpIsValid(runState, destNum)) {
trap(ERROR.INVALID_JUMP + " at " + describeLocation(runState));
}
runState.programCounter = destNum;
}
],
// 0x57: JUMPI
[
87,
function(runState) {
const [dest, cond] = runState.stack.popN(2);
if (cond !== BIGINT_0) {
if (dest > runState.interpreter.getCodeSize()) {
trap(ERROR.INVALID_JUMP + " at " + describeLocation(runState));
}
const destNum = Number(dest);
if (!jumpIsValid(runState, destNum)) {
trap(ERROR.INVALID_JUMP + " at " + describeLocation(runState));
}
runState.programCounter = destNum;
}
}
],
// 0x58: PC
[
88,
function(runState) {
runState.stack.push(BigInt(runState.programCounter - 1));
}
],
// 0x59: MSIZE
[
89,
function(runState) {
runState.stack.push(runState.memoryWordCount * BIGINT_32);
}
],
// 0x5a: GAS
[
90,
function(runState) {
runState.stack.push(runState.interpreter.getGasLeft());
}
],
// 0x5b: JUMPDEST
[91, function() {
}],
// 0x5c: TLOAD (EIP 1153)
[
92,
function(runState) {
const key = runState.stack.pop();
const keyBuf = setLengthLeft(bigIntToBytes(key), 32);
const value = runState.interpreter.transientStorageLoad(keyBuf);
const valueBN = value.length ? bytesToBigInt(value) : BIGINT_0;
runState.stack.push(valueBN);
}
],
// 0x5d: TSTORE (EIP 1153)
[
93,
function(runState) {
if (runState.interpreter.isStatic()) {
trap(ERROR.STATIC_STATE_CHANGE);
}
const [key, val] = runState.stack.popN(2);
const keyBuf = setLengthLeft(bigIntToBytes(key), 32);
let value;
if (val === BIGINT_0) {
value = Uint8Array.from([]);
} else {
value = bigIntToBytes(val);
}
runState.interpreter.transientStorageStore(keyBuf, value);
}
],
// 0x5e: MCOPY (5656)
[
94,
function(runState) {
const [dst, src, length] = runState.stack.popN(3);
const data = runState.memory.read(Number(src), Number(length), true);
runState.memory.write(Number(dst), Number(length), data);
}
],
// 0x5f: PUSH0
[
95,
function(runState) {
runState.stack.push(BIGINT_0);
}
],
// 0x60: PUSH
[
96,
function(runState, common2) {
const numToPush = runState.opCode - 95;
if (runState.programCounter + numToPush > runState.code.length && common2.isActivatedEIP(3540)) {
trap(ERROR.OUT_OF_RANGE);
}
if (common2.isActivatedEIP(6800) && runState.env.chargeCodeAccesses === true) {
const contract = runState.interpreter.getAddress();
const startOffset = Math.min(runState.code.length, runState.programCounter + 1);
const endOffset = Math.min(runState.code.length, startOffset + numToPush - 1);
const statelessGas = runState.env.accessWitness.touchCodeChunksRangeOnReadAndChargeGas(
contract,
startOffset,
endOffset
);
runState.interpreter.useGas(statelessGas, `PUSH`);
}
if (!runState.shouldDoJumpAnalysis) {
runState.stack.push(runState.cachedPushes[runState.programCounter]);
runState.programCounter += numToPush;
} else {
const loaded = bytesToBigInt(
runState.code.subarray(runState.programCounter, runState.programCounter + numToPush)
);
runState.programCounter += numToPush;
runState.stack.push(loaded);
}
}
],
// 0x80: DUP
[
128,
function(runState) {
const stackPos = runState.opCode - 127;
runState.stack.dup(stackPos);
}
],
// 0x90: SWAP
[
144,
function(runState) {
const stackPos = runState.opCode - 143;
runState.stack.swap(stackPos);
}
],
// 0xa0: LOG
[
160,
function(runState) {
const [memOffset, memLength] = runState.stack.popN(2);
const topicsCount = runState.opCode - 160;
const topics = runState.stack.popN(topicsCount);
const topicsBuf = topics.map(function(a) {
return setLengthLeft(bigIntToBytes(a), 32);
});
let mem = new Uint8Array(0);
if (memLength !== BIGINT_0) {
mem = runState.memory.read(Number(memOffset), Number(memLength));
}
runState.interpreter.log(mem, topicsCount, topicsBuf);
}
],
// 0xd0: DATALOAD
[
208,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
}
const pos = runState.stack.pop();
if (pos > runState.env.eof.container.body.dataSection.length) {
runState.stack.push(BIGINT_0);
return;
}
const i = Number(pos);
let loaded = runState.env.eof.container.body.dataSection.subarray(i, i + 32);
loaded = loaded.length ? loaded : Uint8Array.from([0]);
let r = bytesToBigInt(loaded);
if (loaded.length < 32) {
r = r << BIGINT_8 * BigInt(32 - loaded.length);
}
runState.stack.push(r);
}
],
// 0xd1: DATALOADN
[
209,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
}
const toLoad = Number(
bytesToBigInt(runState.code.subarray(runState.programCounter, runState.programCounter + 2))
);
const data = bytesToBigInt(
runState.env.eof.container.body.dataSection.subarray(toLoad, toLoad + 32)
);
runState.stack.push(data);
runState.programCounter += 2;
}
],
// 0xd2: DATASIZE
[
210,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
}
runState.stack.push(BigInt(runState.env.eof.container.body.dataSection.length));
}
],
// 0xd3: DATACOPY
[
211,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
}
const [memOffset, offset, size] = runState.stack.popN(3);
if (size !== BIGINT_0) {
const data = getDataSlice(runState.env.eof.container.body.dataSection, offset, size);
const memOffsetNum = Number(memOffset);
const dataLengthNum = Number(size);
runState.memory.write(memOffsetNum, dataLengthNum, data);
}
}
],
// 0xe0: RJUMP
[
224,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
} else {
const code = runState.env.code;
const rjumpDest = new DataView(code.buffer).getInt16(runState.programCounter);
runState.programCounter += 2 + rjumpDest;
}
}
],
// 0xe1: RJUMPI
[
225,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
} else {
const cond = runState.stack.pop();
if (cond > 0) {
const code = runState.env.code;
const rjumpDest = new DataView(code.buffer).getInt16(runState.programCounter);
runState.programCounter += rjumpDest;
}
runState.programCounter += 2;
}
}
],
// 0xe2: RJUMPV
[
226,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
} else {
const code = runState.env.code;
const jumptableEntries = code[runState.programCounter];
const jumptableSize = (jumptableEntries + 1) * 2;
runState.programCounter += 1;
const jumptableCase = runState.stack.pop();
if (jumptableCase <= jumptableEntries) {
const rjumpDest = new DataView(code.buffer).getInt16(
runState.programCounter + Number(jumptableCase) * 2
);
runState.programCounter += jumptableSize + rjumpDest;
} else {
runState.programCounter += jumptableSize;
}
}
}
],
// 0xe3: CALLF
[
227,
function(runState, _common) {
var _a;
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
}
const sectionTarget = bytesToInt(
runState.code.slice(runState.programCounter, runState.programCounter + 2)
);
const stackItems = runState.stack.length;
const typeSection = runState.env.eof.container.body.typeSections[sectionTarget];
if (1024 < stackItems + (typeSection == null ? void 0 : typeSection.inputs) - (typeSection == null ? void 0 : typeSection.maxStackHeight)) {
trap(EOFError.StackOverflow);
}
if (runState.env.eof.eofRunState.returnStack.length >= 1024) {
trap(EOFError.ReturnStackOverflow);
}
(_a = runState.env.eof) == null ? void 0 : _a.eofRunState.returnStack.push(runState.programCounter + 2);
runState.programCounter = runState.env.eof.container.header.getCodePosition(sectionTarget);
}
],
// 0xe4: RETF
[
228,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
}
const newPc = runState.env.eof.eofRunState.returnStack.pop();
if (newPc === void 0) {
trap(EOFError.RetfNoReturn);
}
runState.programCounter = newPc;
}
],
// 0xe5: JUMPF
[
229,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
}
const sectionTarget = bytesToInt(
runState.code.slice(runState.programCounter, runState.programCounter + 2)
);
const stackItems = runState.stack.length;
const typeSection = runState.env.eof.container.body.typeSections[sectionTarget];
if (1024 < stackItems + (typeSection == null ? void 0 : typeSection.inputs) - (typeSection == null ? void 0 : typeSection.maxStackHeight)) {
trap(EOFError.StackOverflow);
}
runState.programCounter = runState.env.eof.container.header.getCodePosition(sectionTarget);
}
],
// 0xe6: DUPN
[
230,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
}
const toDup = Number(
bytesToBigInt(
runState.code.subarray(runState.programCounter, runState.programCounter + 1)
)
) + 1;
runState.stack.dup(toDup);
runState.programCounter++;
}
],
// 0xe7: SWAPN
[
231,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
}
const toSwap = Number(
bytesToBigInt(
runState.code.subarray(runState.programCounter, runState.programCounter + 1)
)
) + 1;
runState.stack.swap(toSwap);
runState.programCounter++;
}
],
// 0xe8: EXCHANGE
[
232,
function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
}
const toExchange = Number(
bytesToBigInt(runState.code.subarray(runState.programCounter, runState.programCounter + 1))
);
const n = (toExchange >> 4) + 1;
const m = (toExchange & 15) + 1;
runState.stack.exchange(n, n + m);
runState.programCounter++;
}
],
// 0xec: EOFCREATE
[
236,
async function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
} else {
const containerIndex = runState.env.code[runState.programCounter];
const containerCode = runState.env.eof.container.body.containerSections[containerIndex];
const [value, salt, inputOffset, inputSize] = runState.stack.popN(4);
const gasLimit = runState.messageGasLimit;
runState.messageGasLimit = void 0;
let data = new Uint8Array(0);
if (inputSize !== BIGINT_0) {
data = runState.memory.read(Number(inputOffset), Number(inputSize), true);
}
runState.programCounter++;
const ret = await runState.interpreter.eofcreate(
gasLimit,
value,
containerCode,
setLengthLeft(bigIntToBytes(salt), 32),
data
);
runState.stack.push(ret);
}
}
],
// 0xee: RETURNCONTRACT
[
238,
async function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
} else {
const containerIndex = runState.env.code[runState.programCounter];
const containerCode = runState.env.eof.container.body.containerSections[containerIndex];
const deployContainer = new EOFContainer(containerCode, EOFContainerMode.Initmode);
const [auxDataOffset, auxDataSize] = runState.stack.popN(2);
let auxData = new Uint8Array(0);
if (auxDataSize !== BIGINT_0) {
auxData = runState.memory.read(Number(auxDataOffset), Number(auxDataSize));
}
const originalDataSize = deployContainer.header.dataSize;
const preDeployDataSectionSize = deployContainer.body.dataSection.length;
const actualSectionSize = preDeployDataSectionSize + Number(auxDataSize);
if (actualSectionSize < originalDataSize) {
trap(EOFError.InvalidReturnContractDataSize);
}
if (actualSectionSize > 65535) {
trap(ERROR.OUT_OF_GAS);
}
const newSize = setLengthLeft(bigIntToBytes(BigInt(actualSectionSize)), 2);
const dataSizePtr = deployContainer.header.dataSizePtr;
containerCode[dataSizePtr] = newSize[0];
containerCode[dataSizePtr + 1] = newSize[1];
const returnContainer = concatBytes$1(containerCode, auxData);
runState.interpreter.finish(returnContainer);
}
}
],
// '0xf0' range - closures
// 0xf0: CREATE
[
240,
async function(runState, common2) {
const [value, offset, length] = runState.stack.popN(3);
if (common2.isActivatedEIP(3860) && length > Number(common2.param("maxInitCodeSize")) && !runState.interpreter._evm.allowUnlimitedInitCodeSize) {
trap(ERROR.INITCODE_SIZE_VIOLATION);
}
const gasLimit = runState.messageGasLimit;
runState.messageGasLimit = void 0;
let data = new Uint8Array(0);
if (length !== BIGINT_0) {
data = runState.memory.read(Number(offset), Number(length), true);
}
if (isEOF(data)) {
runState.stack.push(BIGINT_0);
return;
}
const ret = await runState.interpreter.create(gasLimit, value, data);
runState.stack.push(ret);
}
],
// 0xf5: CREATE2
[
245,
async function(runState, common2) {
if (runState.interpreter.isStatic()) {
trap(ERROR.STATIC_STATE_CHANGE);
}
const [value, offset, length, salt] = runState.stack.popN(4);
if (common2.isActivatedEIP(3860) && length > Number(common2.param("maxInitCodeSize")) && !runState.interpreter._evm.allowUnlimitedInitCodeSize) {
trap(ERROR.INITCODE_SIZE_VIOLATION);
}
const gasLimit = runState.messageGasLimit;
runState.messageGasLimit = void 0;
let data = new Uint8Array(0);
if (length !== BIGINT_0) {
data = runState.memory.read(Number(offset), Number(length), true);
}
if (isEOF(data)) {
runState.stack.push(BIGINT_0);
return;
}
const ret = await runState.interpreter.create2(
gasLimit,
value,
data,
setLengthLeft(bigIntToBytes(salt), 32)
);
runState.stack.push(ret);
}
],
// 0xf1: CALL
[
241,
async function(runState, common2) {
const [_currentGasLimit, toAddr, value, inOffset, inLength, outOffset, outLength] = runState.stack.popN(7);
const toAddress = createAddressFromStackBigInt(toAddr);
let data = new Uint8Array(0);
if (inLength !== BIGINT_0) {
data = runState.memory.read(Number(inOffset), Number(inLength), true);
}
let gasLimit = runState.messageGasLimit;
if (value !== BIGINT_0) {
const callStipend = common2.param("callStipendGas");
runState.interpreter.addStipend(callStipend);
gasLimit += callStipend;
}
runState.messageGasLimit = void 0;
const ret = await runState.interpreter.call(gasLimit, toAddress, value, data);
writeCallOutput(runState, outOffset, outLength);
runState.stack.push(ret);
}
],
// 0xf2: CALLCODE
[
242,
async function(runState, common2) {
const [_currentGasLimit, toAddr, value, inOffset, inLength, outOffset, outLength] = runState.stack.popN(7);
const toAddress = createAddressFromStackBigInt(toAddr);
let gasLimit = runState.messageGasLimit;
if (value !== BIGINT_0) {
const callStipend = common2.param("callStipendGas");
runState.interpreter.addStipend(callStipend);
gasLimit += callStipend;
}
runState.messageGasLimit = void 0;
let data = new Uint8Array(0);
if (inLength !== BIGINT_0) {
data = runState.memory.read(Number(inOffset), Number(inLength), true);
}
const ret = await runState.interpreter.callCode(gasLimit, toAddress, value, data);
writeCallOutput(runState, outOffset, outLength);
runState.stack.push(ret);
}
],
// 0xf4: DELEGATECALL
[
244,
async function(runState) {
const value = runState.interpreter.getCallValue();
const [_currentGasLimit, toAddr, inOffset, inLength, outOffset, outLength] = runState.stack.popN(6);
const toAddress = createAddressFromStackBigInt(toAddr);
let data = new Uint8Array(0);
if (inLength !== BIGINT_0) {
data = runState.memory.read(Number(inOffset), Number(inLength), true);
}
const gasLimit = runState.messageGasLimit;
runState.messageGasLimit = void 0;
const ret = await runState.interpreter.callDelegate(gasLimit, toAddress, value, data);
writeCallOutput(runState, outOffset, outLength);
runState.stack.push(ret);
}
],
// 0xf8: EXTCALL
[
248,
async function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
} else {
const [toAddr, inOffset, inLength, value] = runState.stack.popN(4);
const gasLimit = runState.messageGasLimit;
runState.messageGasLimit = void 0;
if (gasLimit === -BIGINT_1) {
runState.stack.push(BIGINT_1);
runState.returnBytes = new Uint8Array(0);
return;
}
const toAddress = createAddressFromStackBigInt(toAddr);
let data = new Uint8Array(0);
if (inLength !== BIGINT_0) {
data = runState.memory.read(Number(inOffset), Number(inLength), true);
}
const ret = await runState.interpreter.call(gasLimit, toAddress, value, data);
runState.stack.push(ret);
}
}
],
// 0xf9: EXTDELEGATECALL
[
249,
async function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
} else {
const value = runState.interpreter.getCallValue();
const [toAddr, inOffset, inLength] = runState.stack.popN(3);
const gasLimit = runState.messageGasLimit;
runState.messageGasLimit = void 0;
if (gasLimit === -BIGINT_1) {
runState.stack.push(BIGINT_1);
runState.returnBytes = new Uint8Array(0);
return;
}
const toAddress = createAddressFromStackBigInt(toAddr);
const code = await runState.stateManager.getCode(toAddress);
if (!isEOF(code)) {
runState.stack.push(BIGINT_1);
return;
}
let data = new Uint8Array(0);
if (inLength !== BIGINT_0) {
data = runState.memory.read(Number(inOffset), Number(inLength), true);
}
const ret = await runState.interpreter.callDelegate(gasLimit, toAddress, value, data);
runState.stack.push(ret);
}
}
],
// 0xfa: STATICCALL
[
250,
async function(runState) {
const value = BIGINT_0;
const [_currentGasLimit, toAddr, inOffset, inLength, outOffset, outLength] = runState.stack.popN(6);
const toAddress = createAddressFromStackBigInt(toAddr);
const gasLimit = runState.messageGasLimit;
runState.messageGasLimit = void 0;
let data = new Uint8Array(0);
if (inLength !== BIGINT_0) {
data = runState.memory.read(Number(inOffset), Number(inLength), true);
}
const ret = await runState.interpreter.callStatic(gasLimit, toAddress, value, data);
writeCallOutput(runState, outOffset, outLength);
runState.stack.push(ret);
}
],
// 0xfb: EXTSTATICCALL
[
251,
async function(runState, _common) {
if (runState.env.eof === void 0) {
trap(ERROR.INVALID_OPCODE);
} else {
const value = BIGINT_0;
const [toAddr, inOffset, inLength] = runState.stack.popN(3);
const gasLimit = runState.messageGasLimit;
runState.messageGasLimit = void 0;
if (gasLimit === -BIGINT_1) {
runState.stack.push(BIGINT_1);
runState.returnBytes = new Uint8Array(0);
return;
}
const toAddress = createAddressFromStackBigInt(toAddr);
let data = new Uint8Array(0);
if (inLength !== BIGINT_0) {
data = runState.memory.read(Number(inOffset), Number(inLength), true);
}
const ret = await runState.interpreter.callStatic(gasLimit, toAddress, value, data);
runState.stack.push(ret);
}
}
],
// 0xf3: RETURN
[
243,
function(runState) {
const [offset, length] = runState.stack.popN(2);
let returnData = new Uint8Array(0);
if (length !== BIGINT_0) {
returnData = runState.memory.read(Number(offset), Number(length));
}
runState.interpreter.finish(returnData);
}
],
// 0xfd: REVERT
[
253,
function(runState) {
const [offset, length] = runState.stack.popN(2);
let returnData = new Uint8Array(0);
if (length !== BIGINT_0) {
returnData = runState.memory.read(Number(offset), Number(length));
}
runState.interpreter.revert(returnData);
}
],
// '0x70', range - other
// 0xff: SELFDESTRUCT
[
255,
async function(runState) {
const selfdestructToAddressBigInt = runState.stack.pop();
const selfdestructToAddress = createAddressFromStackBigInt(selfdestructToAddressBigInt);
return runState.interpreter.selfDestruct(selfdestructToAddress);
}
]
]);
const pushFn = handlers.get(96);
for (let i = 97; i <= 127; i++) {
handlers.set(i, pushFn);
}
const dupFn = handlers.get(128);
for (let i = 129; i <= 143; i++) {
handlers.set(i, dupFn);
}
const swapFn = handlers.get(144);
for (let i = 145; i <= 159; i++) {
handlers.set(i, swapFn);
}
const logFn = handlers.get(160);
for (let i = 161; i <= 164; i++) {
handlers.set(i, logFn);
}
function updateSstoreGasEIP1283(runState, currentStorage, originalStorage, value, common2) {
if (equalsBytes(currentStorage, value)) {
return common2.param("netSstoreNoopGas");
}
if (equalsBytes(originalStorage, currentStorage)) {
if (originalStorage.length === 0) {
return common2.param("netSstoreInitGas");
}
if (value.length === 0) {
runState.interpreter.refundGas(
common2.param("netSstoreClearRefundGas"),
"EIP-1283 -> netSstoreClearRefund"
);
}
return common2.param("netSstoreCleanGas");
}
if (originalStorage.length !== 0) {
if (currentStorage.length === 0) {
runState.interpreter.subRefund(
common2.param("netSstoreClearRefundGas"),
"EIP-1283 -> netSstoreClearRefund"
);
} else if (value.length === 0) {
runState.interpreter.refundGas(
common2.param("netSstoreClearRefundGas"),
"EIP-1283 -> netSstoreClearRefund"
);
}
}
if (equalsBytes(originalStorage, value)) {
if (originalStorage.length === 0) {
runState.interpreter.refundGas(
common2.param("netSstoreResetClearRefundGas"),
"EIP-1283 -> netSstoreResetClearRefund"
);
} else {
runState.interpreter.refundGas(
common2.param("netSstoreResetRefundGas"),
"EIP-1283 -> netSstoreResetRefund"
);
}
}
return common2.param("netSstoreDirtyGas");
}
function accessAddressEIP2929(runState, address, common2, chargeGas = true, isSelfdestruct = false) {
if (!common2.isActivatedEIP(2929)) return BIGINT_0;
if (!runState.interpreter.journal.isWarmedAddress(address)) {
runState.interpreter.journal.addWarmedAddress(address);
if (chargeGas && !common2.isActivatedEIP(6800)) {
return common2.param("coldaccountaccessGas");
}
} else if (chargeGas && !isSelfdestruct) {
return common2.param("warmstoragereadGas");
}
return BIGINT_0;
}
function accessStorageEIP2929(runState, key, isSstore, common2, chargeGas = true) {
if (!common2.isActivatedEIP(2929)) return BIGINT_0;
const address = runState.interpreter.getAddress().bytes;
const slotIsCold = !runState.interpreter.journal.isWarmedStorage(address, key);
if (slotIsCold) {
runState.interpreter.journal.addWarmedStorage(address, key);
if (chargeGas && !common2.isActivatedEIP(6800)) {
return common2.param("coldsloadGas");
}
} else if (chargeGas && (!isSstore || common2.isActivatedEIP(6800))) {
return common2.param("warmstoragereadGas");
}
return BIGINT_0;
}
function adjustSstoreGasEIP2929(runState, key, defaultCost, costName, common2) {
if (!common2.isActivatedEIP(2929)) return defaultCost;
const address = runState.interpreter.getAddress().bytes;
const warmRead = common2.param("warmstoragereadGas");
const coldSload = common2.param("coldsloadGas");
if (runState.interpreter.journal.isWarmedStorage(address, key)) {
switch (costName) {
case "noop":
return warmRead;
case "initRefund":
return common2.param("sstoreInitEIP2200Gas") - warmRead;
case "cleanRefund":
return common2.param("sstoreResetGas") - coldSload - warmRead;
}
}
return defaultCost;
}
function updateSstoreGasEIP2200(runState, currentStorage, originalStorage, value, key, common2) {
if (runState.interpreter.getGasLeft() <= common2.param("sstoreSentryEIP2200Gas")) {
trap(ERROR.OUT_OF_GAS);
}
if (equalsBytes(currentStorage, value)) {
const sstoreNoopCost = common2.param("sstoreNoopEIP2200Gas");
return adjustSstoreGasEIP2929(runState, key, sstoreNoopCost, "noop", common2);
}
if (equalsBytes(originalStorage, currentStorage)) {
if (originalStorage.length === 0) {
return common2.param("sstoreInitEIP2200Gas");
}
if (value.length === 0) {
runState.interpreter.refundGas(
common2.param("sstoreClearRefundEIP2200Gas"),
"EIP-2200 -> sstoreClearRefundEIP2200"
);
}
return common2.param("sstoreCleanEIP2200Gas");
}
if (originalStorage.length > 0) {
if (currentStorage.length === 0) {
runState.interpreter.subRefund(
common2.param("sstoreClearRefundEIP2200Gas"),
"EIP-2200 -> sstoreClearRefundEIP2200"
);
} else if (value.length === 0) {
runState.interpreter.refundGas(
common2.param("sstoreClearRefundEIP2200Gas"),
"EIP-2200 -> sstoreClearRefundEIP2200"
);
}
}
if (equalsBytes(originalStorage, value)) {
if (originalStorage.length === 0) {
const sstoreInitRefund = common2.param("sstoreInitRefundEIP2200Gas");
runState.interpreter.refundGas(
adjustSstoreGasEIP2929(runState, key, sstoreInitRefund, "initRefund", common2),
"EIP-2200 -> initRefund"
);
} else {
const sstoreCleanRefund = common2.param("sstoreCleanRefundEIP2200Gas");
runState.interpreter.refundGas(
BigInt(adjustSstoreGasEIP2929(runState, key, sstoreCleanRefund, "cleanRefund", common2)),
"EIP-2200 -> cleanRefund"
);
}
}
return common2.param("sstoreDirtyEIP2200Gas");
}
const EXTCALL_TARGET_MAX = BigInt(2) ** BigInt(8 * 20) - BigInt(1);
async function eip7702GasCost(runState, common2, address, charge2929Gas) {
const code = await runState.stateManager.getCode(address);
if (equalsBytes(code.slice(0, 3), DELEGATION_7702_FLAG)) {
return accessAddressEIP2929(runState, code.slice(3, 24), common2, charge2929Gas);
}
return BIGINT_0;
}
const dynamicGasHandlers = /* @__PURE__ */ new Map([
[
/* EXP */
10,
async function(runState, gas, common2) {
const [_base, exponent] = runState.stack.peek(2);
if (exponent === BIGINT_0) {
return gas;
}
let byteLength = exponent.toString(2).length / 8;
if (byteLength > Math.trunc(byteLength)) {
byteLength = Math.trunc(byteLength) + 1;
}
if (byteLength < 1 || byteLength > 32) {
trap(ERROR.OUT_OF_RANGE);
}
const expPricePerByte = common2.param("expByteGas");
gas += BigInt(byteLength) * expPricePerByte;
return gas;
}
],
[
/* KECCAK256 */
32,
async function(runState, gas, common2) {
const [offset, length] = runState.stack.peek(2);
gas += subMemUsage(runState, offset, length, common2);
gas += common2.param("keccak256WordGas") * divCeil(length, BIGINT_32);
return gas;
}
],
[
/* BALANCE */
49,
async function(runState, gas, common2) {
const address = createAddressFromStackBigInt(runState.stack.peek()[0]);
let charge2929Gas = true;
if (common2.isActivatedEIP(6800)) {
const coldAccessGas = runState.env.accessWitness.touchAddressOnReadAndComputeGas(
address,
0,
VERKLE_BASIC_DATA_LEAF_KEY
);
gas += coldAccessGas;
charge2929Gas = coldAccessGas === BIGINT_0;
}
if (common2.isActivatedEIP(2929)) {
gas += accessAddressEIP2929(runState, address.bytes, common2, charge2929Gas);
}
return gas;
}
],
[
/* CALLDATACOPY */
55,
async function(runState, gas, common2) {
const [memOffset, _dataOffset, dataLength] = runState.stack.peek(3);
gas += subMemUsage(runState, memOffset, dataLength, common2);
if (dataLength !== BIGINT_0) {
gas += common2.param("copyGas") * divCeil(dataLength, BIGINT_32);
}
return gas;
}
],
[
/* CODECOPY */
57,
async function(runState, gas, common2) {
const [memOffset, _codeOffset, dataLength] = runState.stack.peek(3);
gas += subMemUsage(runState, memOffset, dataLength, common2);
if (dataLength !== BIGINT_0) {
gas += common2.param("copyGas") * divCeil(dataLength, BIGINT_32);
if (common2.isActivatedEIP(6800) && runState.env.chargeCodeAccesses === true) {
const contract = runState.interpreter.getAddress();
let codeEnd = _codeOffset + dataLength;
const codeSize = runState.interpreter.getCodeSize();
if (codeEnd > codeSize) {
codeEnd = codeSize;
}
gas += runState.env.accessWitness.touchCodeChunksRangeOnReadAndChargeGas(
contract,
Number(_codeOffset),
Number(codeEnd)
);
}
}
return gas;
}
],
[
/* EXTCODESIZE */
59,
async function(runState, gas, common2) {
const address = createAddressFromStackBigInt(runState.stack.peek()[0]);
let charge2929Gas = true;
if (common2.isActivatedEIP(6800) && runState.interpreter._evm.getPrecompile(address) === void 0) {
let coldAccessGas = BIGINT_0;
coldAccessGas += runState.env.accessWitness.touchAddressOnReadAndComputeGas(
address,
0,
VERKLE_BASIC_DATA_LEAF_KEY
);
gas += coldAccessGas;
charge2929Gas = coldAccessGas === BIGINT_0;
}
if (common2.isActivatedEIP(2929)) {
gas += accessAddressEIP2929(runState, address.bytes, common2, charge2929Gas);
}
if (common2.isActivatedEIP(7702)) {
gas += await eip7702GasCost(runState, common2, address, charge2929Gas);
}
return gas;
}
],
[
/* EXTCODECOPY */
60,
async function(runState, gas, common2) {
const [addressBigInt, memOffset, _codeOffset, dataLength] = runState.stack.peek(4);
const address = createAddressFromStackBigInt(addressBigInt);
gas += subMemUsage(runState, memOffset, dataLength, common2);
let charge2929Gas = true;
if (common2.isActivatedEIP(6800) && runState.interpreter._evm.getPrecompile(address) === void 0) {
let coldAccessGas = BIGINT_0;
coldAccessGas += runState.env.accessWitness.touchAddressOnReadAndComputeGas(
address,
0,
VERKLE_BASIC_DATA_LEAF_KEY
);
gas += coldAccessGas;
charge2929Gas = coldAccessGas === BIGINT_0;
}
if (common2.isActivatedEIP(2929)) {
gas += accessAddressEIP2929(runState, address.bytes, common2, charge2929Gas);
}
if (common2.isActivatedEIP(7702)) {
gas += await eip7702GasCost(runState, common2, address, charge2929Gas);
}
if (dataLength !== BIGINT_0) {
gas += common2.param("copyGas") * divCeil(dataLength, BIGINT_32);
if (common2.isActivatedEIP(6800)) {
let codeEnd = _codeOffset + dataLength;
const codeSize = BigInt((await runState.stateManager.getCode(address)).length);
if (codeEnd > codeSize) {
codeEnd = codeSize;
}
gas += runState.env.accessWitness.touchCodeChunksRangeOnReadAndChargeGas(
address,
Number(_codeOffset),
Number(codeEnd)
);
}
}
return gas;
}
],
[
/* RETURNDATACOPY */
62,
async function(runState, gas, common2) {
const [memOffset, returnDataOffset, dataLength] = runState.stack.peek(3);
if (returnDataOffset + dataLength > runState.interpreter.getReturnDataSize()) {
if (runState.env.eof === void 0) {
trap(ERROR.OUT_OF_GAS);
}
}
gas += subMemUsage(runState, memOffset, dataLength, common2);
if (dataLength !== BIGINT_0) {
gas += common2.param("copyGas") * divCeil(dataLength, BIGINT_32);
}
return gas;
}
],
[
/* EXTCODEHASH */
63,
async function(runState, gas, common2) {
const address = createAddressFromStackBigInt(runState.stack.peek()[0]);
let charge2929Gas = true;
if (common2.isActivatedEIP(6800)) {
let coldAccessGas = BIGINT_0;
coldAccessGas += runState.env.accessWitness.touchAddressOnReadAndComputeGas(
address,
0,
VERKLE_CODE_HASH_LEAF_KEY
);
gas += coldAccessGas;
charge2929Gas = coldAccessGas === BIGINT_0;
}
if (common2.isActivatedEIP(2929)) {
gas += accessAddressEIP2929(runState, address.bytes, common2, charge2929Gas);
}
if (common2.isActivatedEIP(7702)) {
gas += await eip7702GasCost(runState, common2, address, charge2929Gas);
}
return gas;
}
],
[
/* MLOAD */
81,
async function(runState, gas, common2) {
const pos = runState.stack.peek()[0];
gas += subMemUsage(runState, pos, BIGINT_32, common2);
return gas;
}
],
[
/* MSTORE */
82,
async function(runState, gas, common2) {
const offset = runState.stack.peek()[0];
gas += subMemUsage(runState, offset, BIGINT_32, common2);
return gas;
}
],
[
/* MSTORE8 */
83,
async function(runState, gas, common2) {
const offset = runState.stack.peek()[0];
gas += subMemUsage(runState, offset, BIGINT_1, common2);
return gas;
}
],
[
/* SLOAD */
84,
async function(runState, gas, common2) {
const key = runState.stack.peek()[0];
const keyBuf = setLengthLeft(bigIntToBytes(key), 32);
let charge2929Gas = true;
if (common2.isActivatedEIP(6800)) {
const address = runState.interpreter.getAddress();
const { treeIndex, subIndex } = getVerkleTreeIndicesForStorageSlot(key);
const coldAccessGas = runState.env.accessWitness.touchAddressOnReadAndComputeGas(
address,
treeIndex,
subIndex
);
gas += coldAccessGas;
charge2929Gas = coldAccessGas === BIGINT_0;
}
if (common2.isActivatedEIP(2929)) {
gas += accessStorageEIP2929(runState, keyBuf, false, common2, charge2929Gas);
}
return gas;
}
],
[
/* SSTORE */
85,
async function(runState, gas, common2) {
if (runState.interpreter.isStatic()) {
trap(ERROR.STATIC_STATE_CHANGE);
}
const [key, val] = runState.stack.peek(2);
const keyBytes = setLengthLeft(bigIntToBytes(key), 32);
let value;
if (val === BIGINT_0) {
value = Uint8Array.from([]);
} else {
value = bigIntToBytes(val);
}
const currentStorage = setLengthLeftStorage(
await runState.interpreter.storageLoad(keyBytes)
);
const originalStorage = setLengthLeftStorage(
await runState.interpreter.storageLoad(keyBytes, true)
);
if (common2.hardfork() === Hardfork.Constantinople) {
gas += updateSstoreGasEIP1283(
runState,
currentStorage,
originalStorage,
setLengthLeftStorage(value),
common2
);
} else if (common2.gteHardfork(Hardfork.Istanbul)) {
if (!common2.isActivatedEIP(6800)) {
gas += updateSstoreGasEIP2200(
runState,
currentStorage,
originalStorage,
setLengthLeftStorage(value),
keyBytes,
common2
);
}
} else {
gas += updateSstoreGas(runState, currentStorage, setLengthLeftStorage(value), common2);
}
let charge2929Gas = true;
if (common2.isActivatedEIP(6800)) {
const contract = runState.interpreter.getAddress();
const { treeIndex, subIndex } = getVerkleTreeIndicesForStorageSlot(key);
const coldAccessGas = runState.env.accessWitness.touchAddressOnWriteAndComputeGas(
contract,
treeIndex,
subIndex
);
gas += coldAccessGas;
charge2929Gas = coldAccessGas === BIGINT_0;
}
if (common2.isActivatedEIP(2929)) {
gas += accessStorageEIP2929(runState, keyBytes, true, common2, charge2929Gas);
}
return gas;
}
],
[
/* MCOPY */
94,
async function(runState, gas, common2) {
const [dst, src, length] = runState.stack.peek(3);
const wordsCopied = (length + BIGINT_31) / BIGINT_32;
gas += BIGINT_3 * wordsCopied;
gas += subMemUsage(runState, src, length, common2);
gas += subMemUsage(runState, dst, length, common2);
return gas;
}
],
[
/* LOG */
160,
async function(runState, gas, common2) {
if (runState.interpreter.isStatic()) {
trap(ERROR.STATIC_STATE_CHANGE);
}
const [memOffset, memLength] = runState.stack.peek(2);
const topicsCount = runState.opCode - 160;
if (topicsCount < 0 || topicsCount > 4) {
trap(ERROR.OUT_OF_RANGE);
}
gas += subMemUsage(runState, memOffset, memLength, common2);
gas += common2.param("logTopicGas") * BigInt(topicsCount) + memLength * common2.param("logDataGas");
return gas;
}
],
/* DATACOPY */
[
211,
async function(runState, gas, common2) {
const [memOffset, _dataOffset, dataLength] = runState.stack.peek(3);
gas += subMemUsage(runState, memOffset, dataLength, common2);
if (dataLength !== BIGINT_0) {
gas += common2.param("copyGas") * divCeil(dataLength, BIGINT_32);
}
return gas;
}
],
/* EOFCREATE */
[
236,
async function(runState, gas, common2) {
const containerIndex = runState.env.code[runState.programCounter + 1];
const [_value, _salt, inputOffset, inputSize] = runState.stack.peek(4);
gas += subMemUsage(runState, inputOffset, inputSize, common2);
const container = runState.env.eof.container.body.containerSections[containerIndex];
gas += common2.param("keccak256WordGas") * divCeil(BigInt(container.length), BIGINT_32);
const gasLeft = runState.interpreter.getGasLeft() - gas;
runState.messageGasLimit = maxCallGas(gasLeft, gasLeft, runState, common2);
return gas;
}
],
/* RETURNCONTRACT */
[
238,
async function(runState, gas, common2) {
const [auxDataOffset, auxDataSize] = runState.stack.peek(2);
gas += subMemUsage(runState, auxDataOffset, auxDataSize, common2);
return gas;
}
],
[
/* CREATE */
240,
async function(runState, gas, common2) {
if (runState.interpreter.isStatic()) {
trap(ERROR.STATIC_STATE_CHANGE);
}
const [_value, offset, length] = runState.stack.peek(3);
if (common2.isActivatedEIP(2929)) {
gas += accessAddressEIP2929(
runState,
runState.interpreter.getAddress().bytes,
common2,
false
);
}
if (common2.isActivatedEIP(3860)) {
gas += (length + BIGINT_31) / BIGINT_32 * common2.param("initCodeWordGas");
}
gas += subMemUsage(runState, offset, length, common2);
let gasLimit = BigInt(runState.interpreter.getGasLeft()) - gas;
gasLimit = maxCallGas(gasLimit, gasLimit, runState, common2);
runState.messageGasLimit = gasLimit;
return gas;
}
],
[
/* CALL */
241,
async function(runState, gas, common2) {
const [currentGasLimit, toAddr, value, inOffset, inLength, outOffset, outLength] = runState.stack.peek(7);
const toAddress = createAddressFromStackBigInt(toAddr);
if (runState.interpreter.isStatic() && value !== BIGINT_0) {
trap(ERROR.STATIC_STATE_CHANGE);
}
gas += subMemUsage(runState, inOffset, inLength, common2);
gas += subMemUsage(runState, outOffset, outLength, common2);
let charge2929Gas = true;
if (common2.isActivatedEIP(6800) && runState.interpreter._evm.getPrecompile(toAddress) === void 0) {
const coldAccessGas = runState.env.accessWitness.touchAndChargeMessageCall(toAddress);
if (value !== BIGINT_0) {
const contractAddress = runState.interpreter.getAddress();
gas += runState.env.accessWitness.touchAndChargeValueTransfer(
contractAddress,
toAddress
);
}
gas += coldAccessGas;
charge2929Gas = coldAccessGas === BIGINT_0;
}
if (common2.isActivatedEIP(2929)) {
gas += accessAddressEIP2929(runState, toAddress.bytes, common2, charge2929Gas);
}
if (common2.isActivatedEIP(7702)) {
gas += await eip7702GasCost(runState, common2, toAddress, charge2929Gas);
}
if (value !== BIGINT_0 && !common2.isActivatedEIP(6800)) {
gas += common2.param("callValueTransferGas");
}
if (common2.gteHardfork(Hardfork.SpuriousDragon)) {
const account = await runState.stateManager.getAccount(toAddress);
let deadAccount = false;
if (account === void 0 || account.isEmpty()) {
deadAccount = true;
}
if (deadAccount && !(value === BIGINT_0)) {
gas += common2.param("callNewAccountGas");
}
} else if (await runState.stateManager.getAccount(toAddress) === void 0) {
gas += common2.param("callNewAccountGas");
}
const gasLimit = maxCallGas(
currentGasLimit,
runState.interpreter.getGasLeft() - gas,
runState,
common2
);
if (gasLimit > runState.interpreter.getGasLeft() - gas) {
trap(ERROR.OUT_OF_GAS);
}
if (gas > runState.interpreter.getGasLeft()) {
trap(ERROR.OUT_OF_GAS);
}
runState.messageGasLimit = gasLimit;
return gas;
}
],
[
/* CALLCODE */
242,
async function(runState, gas, common2) {
const [currentGasLimit, toAddr, value, inOffset, inLength, outOffset, outLength] = runState.stack.peek(7);
const toAddress = createAddressFromStackBigInt(toAddr);
gas += subMemUsage(runState, inOffset, inLength, common2);
gas += subMemUsage(runState, outOffset, outLength, common2);
let charge2929Gas = true;
if (common2.isActivatedEIP(6800) && runState.interpreter._evm.getPrecompile(toAddress) === void 0) {
const coldAccessGas = runState.env.accessWitness.touchAndChargeMessageCall(toAddress);
gas += coldAccessGas;
charge2929Gas = coldAccessGas === BIGINT_0;
}
if (common2.isActivatedEIP(2929)) {
gas += accessAddressEIP2929(
runState,
createAddressFromStackBigInt(toAddr).bytes,
common2,
charge2929Gas
);
}
if (common2.isActivatedEIP(7702)) {
gas += await eip7702GasCost(runState, common2, toAddress, charge2929Gas);
}
if (value !== BIGINT_0) {
gas += common2.param("callValueTransferGas");
}
const gasLimit = maxCallGas(
currentGasLimit,
runState.interpreter.getGasLeft() - gas,
runState,
common2
);
if (gasLimit > runState.interpreter.getGasLeft() - gas) {
trap(ERROR.OUT_OF_GAS);
}
runState.messageGasLimit = gasLimit;
return gas;
}
],
[
/* RETURN */
243,
async function(runState, gas, common2) {
const [offset, length] = runState.stack.peek(2);
gas += subMemUsage(runState, offset, length, common2);
return gas;
}
],
[
/* DELEGATECALL */
244,
async function(runState, gas, common2) {
const [currentGasLimit, toAddr, inOffset, inLength, outOffset, outLength] = runState.stack.peek(6);
const toAddress = createAddressFromStackBigInt(toAddr);
gas += subMemUsage(runState, inOffset, inLength, common2);
gas += subMemUsage(runState, outOffset, outLength, common2);
let charge2929Gas = true;
if (common2.isActivatedEIP(6800) && runState.interpreter._evm.getPrecompile(toAddress) === void 0) {
const coldAccessGas = runState.env.accessWitness.touchAndChargeMessageCall(toAddress);
gas += coldAccessGas;
charge2929Gas = coldAccessGas === BIGINT_0;
}
if (common2.isActivatedEIP(2929)) {
gas += accessAddressEIP2929(
runState,
createAddressFromStackBigInt(toAddr).bytes,
common2,
charge2929Gas
);
}
if (common2.isActivatedEIP(7702)) {
gas += await eip7702GasCost(runState, common2, toAddress, charge2929Gas);
}
const gasLimit = maxCallGas(
currentGasLimit,
runState.interpreter.getGasLeft() - gas,
runState,
common2
);
if (gasLimit > runState.interpreter.getGasLeft() - gas) {
trap(ERROR.OUT_OF_GAS);
}
runState.messageGasLimit = gasLimit;
return gas;
}
],
[
/* CREATE2 */
245,
async function(runState, gas, common2) {
if (runState.interpreter.isStatic()) {
trap(ERROR.STATIC_STATE_CHANGE);
}
const [_value, offset, length, _salt] = runState.stack.peek(4);
gas += subMemUsage(runState, offset, length, common2);
if (common2.isActivatedEIP(2929)) {
gas += accessAddressEIP2929(
runState,
runState.interpreter.getAddress().bytes,
common2,
false
);
}
if (common2.isActivatedEIP(3860)) {
gas += (length + BIGINT_31) / BIGINT_32 * common2.param("initCodeWordGas");
}
gas += common2.param("keccak256WordGas") * divCeil(length, BIGINT_32);
let gasLimit = runState.interpreter.getGasLeft() - gas;
gasLimit = maxCallGas(gasLimit, gasLimit, runState, common2);
runState.messageGasLimit = gasLimit;
return gas;
}
],
/* EXTCALL */
[
248,
async function(runState, gas, common2) {
const [toAddr, inOffset, inLength, value] = runState.stack.peek(4);
if (runState.interpreter.isStatic() && value !== BIGINT_0) {
trap(ERROR.STATIC_STATE_CHANGE);
}
if (value > BIGINT_0) {
gas += common2.param("callValueTransferGas");
}
if (toAddr > EXTCALL_TARGET_MAX) {
trap(EOFError.InvalidExtcallTarget);
}
gas += subMemUsage(runState, inOffset, inLength, common2);
const toAddress = createAddressFromStackBigInt(toAddr);
gas += accessAddressEIP2929(runState, toAddress.bytes, common2);
if (value > BIGINT_0) {
const account = await runState.stateManager.getAccount(toAddress);
const deadAccount = account === void 0 || account.isEmpty();
if (deadAccount) {
gas += common2.param("callNewAccountGas");
}
}
const minRetainedGas = common2.param("minRetainedGas");
const minCalleeGas = common2.param("minCalleeGas");
const currentGasAvailable = runState.interpreter.getGasLeft() - gas;
const reducedGas = currentGasAvailable / BIGINT_64;
let gasLimit;
if (reducedGas < minRetainedGas) {
gasLimit = currentGasAvailable - minRetainedGas;
} else {
gasLimit = currentGasAvailable - reducedGas;
}
if (runState.env.depth >= Number(common2.param("stackLimit")) || runState.env.contract.balance < value || gasLimit < minCalleeGas) {
gasLimit = -BIGINT_1;
}
runState.messageGasLimit = gasLimit;
return gas;
}
],
/* EXTDELEGATECALL */
[
249,
async function(runState, gas, common2) {
const [toAddr, inOffset, inLength] = runState.stack.peek(3);
if (toAddr > EXTCALL_TARGET_MAX) {
trap(EOFError.InvalidExtcallTarget);
}
gas += subMemUsage(runState, inOffset, inLength, common2);
const toAddress = createAddressFromStackBigInt(toAddr);
gas += accessAddressEIP2929(runState, toAddress.bytes, common2);
const minRetainedGas = common2.param("minRetainedGas");
const minCalleeGas = common2.param("minCalleeGas");
const currentGasAvailable = runState.interpreter.getGasLeft() - gas;
const reducedGas = currentGasAvailable / BIGINT_64;
let gasLimit;
if (reducedGas < minRetainedGas) {
gasLimit = currentGasAvailable - minRetainedGas;
} else {
gasLimit = currentGasAvailable - reducedGas;
}
if (runState.env.depth >= Number(common2.param("stackLimit")) || gasLimit < minCalleeGas) {
gasLimit = -BIGINT_1;
}
runState.messageGasLimit = gasLimit;
return gas;
}
],
[
/* STATICCALL */
250,
async function(runState, gas, common2) {
const [currentGasLimit, toAddr, inOffset, inLength, outOffset, outLength] = runState.stack.peek(6);
gas += subMemUsage(runState, inOffset, inLength, common2);
gas += subMemUsage(runState, outOffset, outLength, common2);
let charge2929Gas = true;
if (common2.isActivatedEIP(6800)) {
const toAddress = createAddressFromStackBigInt(toAddr);
const coldAccessGas = runState.env.accessWitness.touchAndChargeMessageCall(toAddress);
gas += coldAccessGas;
charge2929Gas = coldAccessGas === BIGINT_0;
}
if (common2.isActivatedEIP(2929)) {
gas += accessAddressEIP2929(
runState,
createAddressFromStackBigInt(toAddr).bytes,
common2,
charge2929Gas
);
}
if (common2.isActivatedEIP(7702)) {
gas += await eip7702GasCost(
runState,
common2,
createAddressFromStackBigInt(toAddr),
charge2929Gas
);
}
const gasLimit = maxCallGas(
currentGasLimit,
runState.interpreter.getGasLeft() - gas,
runState,
common2
);
runState.messageGasLimit = gasLimit;
return gas;
}
],
/* EXTSTATICCALL */
[
251,
async function(runState, gas, common2) {
const [toAddr, inOffset, inLength] = runState.stack.peek(3);
if (toAddr > EXTCALL_TARGET_MAX) {
trap(EOFError.InvalidExtcallTarget);
}
gas += subMemUsage(runState, inOffset, inLength, common2);
const toAddress = createAddressFromStackBigInt(toAddr);
gas += accessAddressEIP2929(runState, toAddress.bytes, common2);
const minRetainedGas = common2.param("minRetainedGas");
const minCalleeGas = common2.param("minCalleeGas");
const currentGasAvailable = runState.interpreter.getGasLeft() - gas;
const reducedGas = currentGasAvailable / BIGINT_64;
let gasLimit;
if (reducedGas < minRetainedGas) {
gasLimit = currentGasAvailable - minRetainedGas;
} else {
gasLimit = currentGasAvailable - reducedGas;
}
if (runState.env.depth >= Number(common2.param("stackLimit")) || gasLimit < minCalleeGas) {
gasLimit = -BIGINT_1;
}
runState.messageGasLimit = gasLimit;
return gas;
}
],
[
/* REVERT */
253,
async function(runState, gas, common2) {
const [offset, length] = runState.stack.peek(2);
gas += subMemUsage(runState, offset, length, common2);
return gas;
}
],
[
/* SELFDESTRUCT */
255,
async function(runState, gas, common2) {
if (runState.interpreter.isStatic()) {
trap(ERROR.STATIC_STATE_CHANGE);
}
const selfdestructToaddressBigInt = runState.stack.peek()[0];
const selfdestructToAddress = createAddressFromStackBigInt(selfdestructToaddressBigInt);
const contractAddress = runState.interpreter.getAddress();
let deductGas = false;
const balance = await runState.interpreter.getExternalBalance(contractAddress);
if (common2.gteHardfork(Hardfork.SpuriousDragon)) {
if (balance > BIGINT_0) {
const account = await runState.stateManager.getAccount(selfdestructToAddress);
if (account === void 0 || account.isEmpty()) {
deductGas = true;
}
}
} else if (common2.gteHardfork(Hardfork.TangerineWhistle)) {
const exists2 = await runState.stateManager.getAccount(selfdestructToAddress) !== void 0;
if (!exists2) {
deductGas = true;
}
}
if (deductGas) {
gas += common2.param("callNewAccountGas");
}
let selfDestructToCharge2929Gas = true;
if (common2.isActivatedEIP(6800)) {
gas += runState.env.accessWitness.touchAddressOnReadAndComputeGas(
contractAddress,
0,
VERKLE_BASIC_DATA_LEAF_KEY
);
if (balance > BIGINT_0) {
gas += runState.env.accessWitness.touchAddressOnWriteAndComputeGas(
contractAddress,
0,
VERKLE_BASIC_DATA_LEAF_KEY
);
}
let selfDestructToColdAccessGas = runState.env.accessWitness.touchAddressOnReadAndComputeGas(
selfdestructToAddress,
0,
VERKLE_BASIC_DATA_LEAF_KEY
);
if (balance > BIGINT_0) {
selfDestructToColdAccessGas += runState.env.accessWitness.touchAddressOnWriteAndComputeGas(
selfdestructToAddress,
0,
VERKLE_BASIC_DATA_LEAF_KEY
);
}
gas += selfDestructToColdAccessGas;
selfDestructToCharge2929Gas = selfDestructToColdAccessGas === BIGINT_0;
}
if (common2.isActivatedEIP(2929)) {
gas += accessAddressEIP2929(
runState,
selfdestructToAddress.bytes,
common2,
selfDestructToCharge2929Gas,
true
);
}
return gas;
}
]
]);
const logDynamicFunc = dynamicGasHandlers.get(160);
for (let i = 161; i <= 164; i++) {
dynamicGasHandlers.set(i, logDynamicFunc);
}
class Opcode {
constructor({
code,
name,
fullName,
fee,
isAsync,
dynamicGas
}) {
this.code = code;
this.name = name;
this.fullName = fullName;
this.fee = fee;
this.feeBigInt = BigInt(fee);
this.isAsync = isAsync;
this.dynamicGas = dynamicGas;
this.isInvalid = this.name === "INVALID";
Object.freeze(this);
}
}
const defaultOp = (name) => {
return { name, isAsync: false, dynamicGas: false };
};
const dynamicGasOp = (name) => {
return { name, isAsync: false, dynamicGas: true };
};
const asyncOp = (name) => {
return { name, isAsync: true, dynamicGas: false };
};
const asyncAndDynamicGasOp = (name) => {
return { name, isAsync: true, dynamicGas: true };
};
const opcodes = {
// 0x0 range - arithmetic ops
// name, async
0: defaultOp("STOP"),
1: defaultOp("ADD"),
2: defaultOp("MUL"),
3: defaultOp("SUB"),
4: defaultOp("DIV"),
5: defaultOp("SDIV"),
6: defaultOp("MOD"),
7: defaultOp("SMOD"),
8: defaultOp("ADDMOD"),
9: defaultOp("MULMOD"),
10: dynamicGasOp("EXP"),
11: defaultOp("SIGNEXTEND"),
// 0x10 range - bit ops
16: defaultOp("LT"),
17: defaultOp("GT"),
18: defaultOp("SLT"),
19: defaultOp("SGT"),
20: defaultOp("EQ"),
21: defaultOp("ISZERO"),
22: defaultOp("AND"),
23: defaultOp("OR"),
24: defaultOp("XOR"),
25: defaultOp("NOT"),
26: defaultOp("BYTE"),
// 0x20 range - crypto
32: dynamicGasOp("KECCAK256"),
// 0x30 range - closure state
48: asyncOp("ADDRESS"),
49: asyncAndDynamicGasOp("BALANCE"),
50: asyncOp("ORIGIN"),
51: asyncOp("CALLER"),
52: asyncOp("CALLVALUE"),
53: asyncOp("CALLDATALOAD"),
54: asyncOp("CALLDATASIZE"),
55: asyncAndDynamicGasOp("CALLDATACOPY"),
56: defaultOp("CODESIZE"),
57: dynamicGasOp("CODECOPY"),
58: defaultOp("GASPRICE"),
59: asyncAndDynamicGasOp("EXTCODESIZE"),
60: asyncAndDynamicGasOp("EXTCODECOPY"),
// '0x40' range - block operations
64: asyncOp("BLOCKHASH"),
65: asyncOp("COINBASE"),
66: asyncOp("TIMESTAMP"),
67: asyncOp("NUMBER"),
68: asyncOp("DIFFICULTY"),
69: asyncOp("GASLIMIT"),
// 0x50 range - 'storage' and execution
80: defaultOp("POP"),
81: dynamicGasOp("MLOAD"),
82: dynamicGasOp("MSTORE"),
83: dynamicGasOp("MSTORE8"),
84: asyncAndDynamicGasOp("SLOAD"),
85: asyncAndDynamicGasOp("SSTORE"),
86: defaultOp("JUMP"),
87: defaultOp("JUMPI"),
88: defaultOp("PC"),
89: defaultOp("MSIZE"),
90: defaultOp("GAS"),
91: defaultOp("JUMPDEST"),
// 0x60, range
96: defaultOp("PUSH"),
97: defaultOp("PUSH"),
98: defaultOp("PUSH"),
99: defaultOp("PUSH"),
100: defaultOp("PUSH"),
101: defaultOp("PUSH"),
102: defaultOp("PUSH"),
103: defaultOp("PUSH"),
104: defaultOp("PUSH"),
105: defaultOp("PUSH"),
106: defaultOp("PUSH"),
107: defaultOp("PUSH"),
108: defaultOp("PUSH"),
109: defaultOp("PUSH"),
110: defaultOp("PUSH"),
111: defaultOp("PUSH"),
112: defaultOp("PUSH"),
113: defaultOp("PUSH"),
114: defaultOp("PUSH"),
115: defaultOp("PUSH"),
116: defaultOp("PUSH"),
117: defaultOp("PUSH"),
118: defaultOp("PUSH"),
119: defaultOp("PUSH"),
120: defaultOp("PUSH"),
121: defaultOp("PUSH"),
122: defaultOp("PUSH"),
123: defaultOp("PUSH"),
124: defaultOp("PUSH"),
125: defaultOp("PUSH"),
126: defaultOp("PUSH"),
127: defaultOp("PUSH"),
128: defaultOp("DUP"),
129: defaultOp("DUP"),
130: defaultOp("DUP"),
131: defaultOp("DUP"),
132: defaultOp("DUP"),
133: defaultOp("DUP"),
134: defaultOp("DUP"),
135: defaultOp("DUP"),
136: defaultOp("DUP"),
137: defaultOp("DUP"),
138: defaultOp("DUP"),
139: defaultOp("DUP"),
140: defaultOp("DUP"),
141: defaultOp("DUP"),
142: defaultOp("DUP"),
143: defaultOp("DUP"),
144: defaultOp("SWAP"),
145: defaultOp("SWAP"),
146: defaultOp("SWAP"),
147: defaultOp("SWAP"),
148: defaultOp("SWAP"),
149: defaultOp("SWAP"),
150: defaultOp("SWAP"),
151: defaultOp("SWAP"),
152: defaultOp("SWAP"),
153: defaultOp("SWAP"),
154: defaultOp("SWAP"),
155: defaultOp("SWAP"),
156: defaultOp("SWAP"),
157: defaultOp("SWAP"),
158: defaultOp("SWAP"),
159: defaultOp("SWAP"),
160: dynamicGasOp("LOG"),
161: dynamicGasOp("LOG"),
162: dynamicGasOp("LOG"),
163: dynamicGasOp("LOG"),
164: dynamicGasOp("LOG"),
// '0xf0' range - closures
240: asyncAndDynamicGasOp("CREATE"),
241: asyncAndDynamicGasOp("CALL"),
242: asyncAndDynamicGasOp("CALLCODE"),
243: dynamicGasOp("RETURN"),
// '0x70', range - other
254: defaultOp("INVALID"),
255: asyncAndDynamicGasOp("SELFDESTRUCT")
};
const hardforkOpcodes = [
{
hardfork: Hardfork.Homestead,
opcodes: {
244: asyncAndDynamicGasOp("DELEGATECALL")
// EIP-7
}
},
{
hardfork: Hardfork.TangerineWhistle,
opcodes: {
84: asyncAndDynamicGasOp("SLOAD"),
241: asyncAndDynamicGasOp("CALL"),
242: asyncAndDynamicGasOp("CALLCODE"),
59: asyncAndDynamicGasOp("EXTCODESIZE"),
60: asyncAndDynamicGasOp("EXTCODECOPY"),
244: asyncAndDynamicGasOp("DELEGATECALL"),
// EIP-7
255: asyncAndDynamicGasOp("SELFDESTRUCT"),
49: asyncAndDynamicGasOp("BALANCE")
}
},
{
hardfork: Hardfork.Byzantium,
opcodes: {
253: dynamicGasOp("REVERT"),
// EIP-140
250: asyncAndDynamicGasOp("STATICCALL"),
// EIP-214
61: asyncOp("RETURNDATASIZE"),
// EIP-211
62: asyncAndDynamicGasOp("RETURNDATACOPY")
// EIP-211
}
},
{
hardfork: Hardfork.Constantinople,
opcodes: {
27: defaultOp("SHL"),
// EIP-145
28: defaultOp("SHR"),
// EIP-145
29: defaultOp("SAR"),
// EIP-145
63: asyncAndDynamicGasOp("EXTCODEHASH"),
// EIP-1052
245: asyncAndDynamicGasOp("CREATE2")
// EIP-1014
}
},
{
hardfork: Hardfork.Istanbul,
opcodes: {
70: defaultOp("CHAINID"),
// EIP-1344
71: defaultOp("SELFBALANCE")
// EIP-1884
}
},
{
hardfork: Hardfork.Paris,
opcodes: {
68: asyncOp("PREVRANDAO")
// EIP-4399
}
}
];
const eipOpcodes = [
{
eip: 663,
opcodes: {
230: defaultOp("DUPN"),
231: defaultOp("SWAPN"),
232: defaultOp("EXCHANGE")
}
},
{
eip: 1153,
opcodes: {
92: defaultOp("TLOAD"),
93: defaultOp("TSTORE")
}
},
{
eip: 3198,
opcodes: {
72: defaultOp("BASEFEE")
}
},
{
eip: 3855,
opcodes: {
95: defaultOp("PUSH0")
}
},
{
eip: 4200,
opcodes: {
224: defaultOp("RJUMP"),
225: defaultOp("RJUMPI"),
226: defaultOp("RJUMPV")
}
},
{
eip: 4750,
opcodes: {
227: defaultOp("CALLF"),
228: defaultOp("RETF")
}
},
{
eip: 4844,
opcodes: {
73: defaultOp("BLOBHASH")
}
},
{
eip: 5656,
opcodes: {
94: dynamicGasOp("MCOPY")
}
},
{
eip: 6206,
opcodes: {
229: defaultOp("JUMPF")
}
},
{
eip: 7069,
opcodes: {
247: defaultOp("RETURNDATALOAD"),
248: asyncAndDynamicGasOp("EXTCALL"),
249: asyncAndDynamicGasOp("EXTDELEGATECALL"),
251: asyncAndDynamicGasOp("EXTSTATICCALL")
}
},
{
eip: 7480,
opcodes: {
208: defaultOp("DATALOAD"),
209: defaultOp("DATALOADN"),
210: defaultOp("DATASIZE"),
211: dynamicGasOp("DATACOPY")
}
},
{
eip: 7516,
opcodes: {
74: defaultOp("BLOBBASEFEE")
}
},
{
eip: 7620,
opcodes: {
236: asyncAndDynamicGasOp("EOFCREATE"),
238: asyncAndDynamicGasOp("RETURNCONTRACT")
}
}
];
function createOpcodes(opcodes2) {
const result = /* @__PURE__ */ new Map();
for (const [key, value] of Object.entries(opcodes2)) {
const code = parseInt(key, 10);
if (isNaN(value.fee)) value.fee = 0;
result.set(
code,
new Opcode({
code,
fullName: getFullname(code, value.name),
...value
})
);
}
return result;
}
function getOpcodesForHF(common2, customOpcodes) {
let opcodeBuilder = { ...opcodes };
const handlersCopy = new Map(handlers);
const dynamicGasHandlersCopy = new Map(dynamicGasHandlers);
for (let fork = 0; fork < hardforkOpcodes.length; fork++) {
if (common2.gteHardfork(hardforkOpcodes[fork].hardfork)) {
opcodeBuilder = { ...opcodeBuilder, ...hardforkOpcodes[fork].opcodes };
}
}
for (const eipOps of eipOpcodes) {
if (common2.isActivatedEIP(eipOps.eip)) {
opcodeBuilder = { ...opcodeBuilder, ...eipOps.opcodes };
}
}
for (const key in opcodeBuilder) {
const baseFee = Number(common2.param(`${opcodeBuilder[key].name.toLowerCase()}Gas`));
if (baseFee === void 0) {
throw new Error(`base fee not defined for: ${opcodeBuilder[key].name}`);
}
opcodeBuilder[key].fee = baseFee;
}
if (customOpcodes) {
for (const _code of customOpcodes) {
const code = _code;
if (code.logicFunction === void 0) {
delete opcodeBuilder[code.opcode];
continue;
}
if (code.opcodeName === void 0 || code.baseFee === void 0) {
throw new Error(
`Custom opcode ${code.opcode} does not have the required values: opcodeName and baseFee are required`
);
}
const entry = {
[code.opcode]: {
name: code.opcodeName,
isAsync: true,
dynamicGas: code.gasFunction !== void 0,
fee: code.baseFee,
feeBigInt: BigInt(code.baseFee)
}
};
opcodeBuilder = { ...opcodeBuilder, ...entry };
if (code.gasFunction !== void 0) {
dynamicGasHandlersCopy.set(code.opcode, code.gasFunction);
}
handlersCopy.set(code.opcode, code.logicFunction);
}
}
const ops = createOpcodes(opcodeBuilder);
const opcodeMap = [];
for (const [opNumber, op] of ops) {
const dynamicGas = dynamicGasHandlersCopy.get(opNumber);
const handler = handlersCopy.get(opNumber);
opcodeMap[opNumber] = {
opcodeInfo: op,
opHandler: handler,
gasHandler: dynamicGas
};
}
const INVALID = opcodeMap[254];
for (let i = 0; i <= 255; i++) {
if (opcodeMap[i] === void 0) {
opcodeMap[i] = INVALID;
}
}
return {
dynamicGasHandlers: dynamicGasHandlersCopy,
handlers: handlersCopy,
opcodes: ops,
opcodeMap
};
}
class Stack {
constructor(maxHeight) {
this._len = 0;
this._store = [];
this._maxHeight = maxHeight ?? 1024;
}
get length() {
return this._len;
}
push(value) {
if (this._len >= this._maxHeight) {
throw new EvmError(ERROR.STACK_OVERFLOW);
}
this._store[this._len++] = value;
}
pop() {
if (this._len < 1) {
throw new EvmError(ERROR.STACK_UNDERFLOW);
}
return this._store[--this._len];
}
/**
* Pop multiple items from stack. Top of stack is first item
* in returned array.
* @param num - Number of items to pop
*/
popN(num = 1) {
if (this._len < num) {
throw new EvmError(ERROR.STACK_UNDERFLOW);
}
if (num === 0) {
return [];
}
const arr = Array(num);
const cache = this._store;
for (let pop = 0; pop < num; pop++) {
arr[pop] = cache[--this._len];
}
return arr;
}
/**
* Return items from the stack
* @param num Number of items to return
* @throws {@link ERROR.STACK_UNDERFLOW}
*/
peek(num = 1) {
const peekArray = Array(num);
let start = this._len;
for (let peek = 0; peek < num; peek++) {
const index = --start;
if (index < 0) {
throw new EvmError(ERROR.STACK_UNDERFLOW);
}
peekArray[peek] = this._store[index];
}
return peekArray;
}
/**
* Swap top of stack with an item in the stack.
* @param position - Index of item from top of the stack (0-indexed)
*/
swap(position) {
if (this._len <= position) {
throw new EvmError(ERROR.STACK_UNDERFLOW);
}
const head = this._len - 1;
const i = head - position;
const storageCached = this._store;
const tmp = storageCached[head];
storageCached[head] = storageCached[i];
storageCached[i] = tmp;
}
/**
* Pushes a copy of an item in the stack.
* @param position - Index of item to be copied (1-indexed)
*/
// I would say that we do not need this method any more
// since you can't copy a primitive data type
// Nevertheless not sure if we "loose" something here?
// Will keep commented out for now
dup(position) {
const len = this._len;
if (len < position) {
throw new EvmError(ERROR.STACK_UNDERFLOW);
}
if (len >= this._maxHeight) {
throw new EvmError(ERROR.STACK_OVERFLOW);
}
const i = len - position;
this._store[this._len++] = this._store[i];
}
/**
* Swap number 1 with number 2 on the stack
* @param swap1
* @param swap2
*/
exchange(swap1, swap2) {
const headIndex = this._len - 1;
const exchangeIndex1 = headIndex - swap1;
const exchangeIndex2 = headIndex - swap2;
if (exchangeIndex1 < 0 || exchangeIndex2 < 0) {
throw new EvmError(ERROR.STACK_UNDERFLOW);
}
const cache = this._store[exchangeIndex2];
this._store[exchangeIndex2] = this._store[exchangeIndex1];
this._store[exchangeIndex1] = cache;
}
/**
* Returns a copy of the current stack. This represents the actual state of the stack
* (not the internal state of the stack, which might have unreachable elements in it)
*/
getStack() {
return this._store.slice(0, this._len);
}
}
const debugGas$1 = debugDefault("evm:gas");
class Interpreter {
// TODO remove gasLeft as constructor argument
constructor(evm, stateManager, blockchain, env, gasLeft, journal, performanceLogs, profilerOpts) {
this.opDebuggers = {};
this._evm = evm;
this._stateManager = stateManager;
this.common = this._evm.common;
if (this.common.consensusType() === "poa" && this._evm["_optsCached"].cliqueSigner === void 0)
throw new Error(
"Must include cliqueSigner function if clique/poa is being used for consensus type"
);
this._runState = {
programCounter: 0,
opCode: 254,
// INVALID opcode
memory: new Memory(),
memoryWordCount: BIGINT_0,
highestMemCost: BIGINT_0,
stack: new Stack(),
code: new Uint8Array(0),
validJumps: Uint8Array.from([]),
cachedPushes: {},
stateManager: this._stateManager,
blockchain,
env,
shouldDoJumpAnalysis: true,
interpreter: this,
gasRefund: env.gasRefund,
gasLeft,
returnBytes: new Uint8Array(0)
};
this.journal = journal;
this._env = env;
this._result = {
logs: [],
returnValue: void 0,
selfdestruct: /* @__PURE__ */ new Set()
};
this.profilerOpts = profilerOpts;
this.performanceLogger = performanceLogs;
}
async run(code, opts = {}) {
var _a;
if (!this.common.isActivatedEIP(3540) || code[0] !== FORMAT) {
this._runState.code = code;
} else if (this.common.isActivatedEIP(3540)) {
if (code[1] !== MAGIC) {
return {
runState: this._runState,
exceptionError: new EvmError(ERROR.INVALID_BYTECODE_RESULT)
};
}
if (code[2] !== VERSION) {
return {
runState: this._runState,
exceptionError: new EvmError(ERROR.INVALID_EOF_FORMAT)
};
}
this._runState.code = code;
const isTxCreate = this._env.isCreate && this._env.depth === 0;
const eofMode = isTxCreate ? EOFContainerMode.TxInitmode : EOFContainerMode.Default;
try {
setupEOF(this._runState, eofMode);
} catch (e) {
return {
runState: this._runState,
exceptionError: new EvmError(ERROR.INVALID_EOF_FORMAT)
// TODO: verify if all gas should be consumed
};
}
if (isTxCreate) {
try {
validateEOF(
this._runState.code,
this._evm,
ContainerSectionType.InitCode,
EOFContainerMode.TxInitmode
);
} catch (e) {
return {
runState: this._runState,
exceptionError: new EvmError(ERROR.INVALID_EOF_FORMAT)
// TODO: verify if all gas should be consumed
};
}
}
}
this._runState.programCounter = opts.pc ?? this._runState.programCounter;
const pc = this._runState.programCounter;
if (pc !== 0 && (pc < 0 || pc >= this._runState.code.length)) {
throw new Error("Internal error: program counter not in range");
}
let err;
let cachedOpcodes;
let doJumpAnalysis = true;
let timer;
let overheadTimer;
if (((_a = this.profilerOpts) == null ? void 0 : _a.enabled) === true && this.performanceLogger.hasTimer()) {
timer = this.performanceLogger.pauseTimer();
overheadTimer = this.performanceLogger.startTimer("Overhead");
}
while (this._runState.programCounter < this._runState.code.length) {
const programCounter = this._runState.programCounter;
let opCode;
let opCodeObj;
if (doJumpAnalysis) {
opCode = this._runState.code[programCounter];
if (opCode === 86 || opCode === 87 || opCode === 94) {
const { jumps, pushes, opcodesCached } = this._getValidJumpDestinations(
this._runState.code
);
this._runState.validJumps = jumps;
this._runState.cachedPushes = pushes;
this._runState.shouldDoJumpAnalysis = false;
cachedOpcodes = opcodesCached;
doJumpAnalysis = false;
}
} else {
opCodeObj = cachedOpcodes[programCounter];
opCode = opCodeObj.opcodeInfo.code;
}
if (opCode === 254 && this.common.isActivatedEIP(6800) && // is this a code loaded from state using witnesses
this._runState.env.chargeCodeAccesses === true) {
const contract = this._runState.interpreter.getAddress();
if (!await this._runState.stateManager.checkChunkWitnessPresent(contract, programCounter)) {
throw Error(`Invalid witness with missing codeChunk for pc=${programCounter}`);
}
}
this._runState.opCode = opCode;
try {
if (overheadTimer !== void 0) {
this.performanceLogger.pauseTimer();
}
await this.runStep(opCodeObj);
if (overheadTimer !== void 0) {
this.performanceLogger.unpauseTimer(overheadTimer);
}
} catch (e) {
if (overheadTimer !== void 0) {
this.performanceLogger.unpauseTimer(overheadTimer);
}
if (!("errorType" in e && e.errorType === "EvmError")) {
throw e;
}
if (e.error !== ERROR.STOP) {
err = e;
}
break;
}
}
if (timer !== void 0) {
this.performanceLogger.stopTimer(overheadTimer, 0);
this.performanceLogger.unpauseTimer(timer);
}
return {
runState: this._runState,
exceptionError: err
};
}
/**
* Executes the opcode to which the program counter is pointing,
* reducing its base gas cost, and increments the program counter.
*/
async runStep(opcodeObj) {
var _a, _b;
const opEntry = opcodeObj ?? this.lookupOpInfo(this._runState.opCode);
const opInfo = opEntry.opcodeInfo;
let timer;
if (((_a = this.profilerOpts) == null ? void 0 : _a.enabled) === true) {
timer = this.performanceLogger.startTimer(opInfo.name);
}
let gas = opInfo.feeBigInt;
try {
if (opInfo.dynamicGas) {
gas = await opEntry.gasHandler(this._runState, gas, this.common);
}
if (this.common.isActivatedEIP(6800) && this._env.chargeCodeAccesses === true) {
const contract = this._runState.interpreter.getAddress();
const statelessGas = this._runState.env.accessWitness.touchCodeChunksRangeOnReadAndChargeGas(
contract,
this._runState.programCounter,
this._runState.programCounter
);
gas += statelessGas;
debugGas$1(`codechunk accessed statelessGas=${statelessGas} (-> ${gas})`);
}
if (this._evm.events.listenerCount("step") > 0 || this._evm.DEBUG) {
await this._runStepHook(gas, this.getGasLeft());
}
if (opInfo.isInvalid) {
throw new EvmError(ERROR.INVALID_OPCODE);
}
this.useGas(gas, opInfo);
this._runState.programCounter++;
const opFn = opEntry.opHandler;
if (opInfo.isAsync) {
await opFn.apply(null, [this._runState, this.common]);
} else {
opFn.apply(null, [this._runState, this.common]);
}
} finally {
if (((_b = this.profilerOpts) == null ? void 0 : _b.enabled) === true) {
this.performanceLogger.stopTimer(
timer,
Number(gas),
"opcodes",
opInfo.fee,
Number(gas) - opInfo.fee
);
}
}
}
/**
* Get info for an opcode from EVM's list of opcodes.
*/
lookupOpInfo(op) {
return this._evm._opcodeMap[op];
}
async _runStepHook(dynamicFee, gasLeft) {
const opcodeInfo = this.lookupOpInfo(this._runState.opCode);
const opcode = opcodeInfo.opcodeInfo;
const eventObj = {
pc: this._runState.programCounter,
gasLeft,
gasRefund: this._runState.gasRefund,
opcode: {
name: opcode.fullName,
fee: opcode.fee,
dynamicFee,
isAsync: opcode.isAsync
},
stack: this._runState.stack.getStack(),
depth: this._env.depth,
address: this._env.address,
account: this._env.contract,
memory: this._runState.memory._store.subarray(0, Number(this._runState.memoryWordCount) * 32),
memoryWordCount: this._runState.memoryWordCount,
codeAddress: this._env.codeAddress,
stateManager: this._runState.stateManager
};
if (this._evm.DEBUG) {
let hexStack = [];
hexStack = eventObj.stack.map((item) => {
return bigIntToHex(BigInt(item));
});
const name = eventObj.opcode.name;
const opTrace = {
pc: eventObj.pc,
op: name,
gas: bigIntToHex(eventObj.gasLeft),
gasCost: bigIntToHex(dynamicFee),
stack: hexStack,
depth: eventObj.depth
};
if (!(name in this.opDebuggers)) {
this.opDebuggers[name] = debugDefault(`evm:ops:${name}`);
}
this.opDebuggers[name](JSON.stringify(opTrace));
}
await this._evm._emit("step", eventObj);
}
// Returns all valid jump and jumpsub destinations.
_getValidJumpDestinations(code) {
const jumps = new Uint8Array(code.length).fill(0);
const pushes = {};
const opcodesCached = Array(code.length);
for (let i = 0; i < code.length; i++) {
const opcode = code[i];
opcodesCached[i] = this.lookupOpInfo(opcode);
if (opcode <= 127) {
if (opcode >= 96) {
const extraSteps = opcode - 95;
const push = bytesToBigInt(code.slice(i + 1, i + opcode - 94));
pushes[i + 1] = push;
i += extraSteps;
} else if (opcode === 91) {
jumps[i] = 1;
}
}
}
return { jumps, pushes, opcodesCached };
}
/**
* Subtracts an amount from the gas counter.
* @param amount - Amount of gas to consume
* @param context - Usage context for debugging
* @throws if out of gas
*/
useGas(amount, context) {
this._runState.gasLeft -= amount;
if (this._evm.DEBUG) {
let tempString = "";
if (typeof context === "string") {
tempString = context + ": ";
} else if (context !== void 0) {
tempString = `${context.name} fee: `;
}
debugGas$1(`${tempString}used ${amount} gas (-> ${this._runState.gasLeft})`);
}
if (this._runState.gasLeft < BIGINT_0) {
this._runState.gasLeft = BIGINT_0;
trap(ERROR.OUT_OF_GAS);
}
}
/**
* Adds a positive amount to the gas counter.
* @param amount - Amount of gas refunded
* @param context - Usage context for debugging
*/
refundGas(amount, context) {
if (this._evm.DEBUG) {
debugGas$1(
`${typeof context === "string" ? context + ": " : ""}refund ${amount} gas (-> ${this._runState.gasRefund})`
);
}
this._runState.gasRefund += amount;
}
/**
* Reduces amount of gas to be refunded by a positive value.
* @param amount - Amount to subtract from gas refunds
* @param context - Usage context for debugging
*/
subRefund(amount, context) {
if (this._evm.DEBUG) {
debugGas$1(
`${typeof context === "string" ? context + ": " : ""}sub gas refund ${amount} (-> ${this._runState.gasRefund})`
);
}
this._runState.gasRefund -= amount;
if (this._runState.gasRefund < BIGINT_0) {
this._runState.gasRefund = BIGINT_0;
trap(ERROR.REFUND_EXHAUSTED);
}
}
/**
* Increments the internal gasLeft counter. Used for adding callStipend.
* @param amount - Amount to add
*/
addStipend(amount) {
if (this._evm.DEBUG) {
debugGas$1(`add stipend ${amount} (-> ${this._runState.gasLeft})`);
}
this._runState.gasLeft += amount;
}
/**
* Returns balance of the given account.
* @param address - Address of account
*/
async getExternalBalance(address) {
if (address.equals(this._env.address)) {
return this._env.contract.balance;
}
let account = await this._stateManager.getAccount(address);
if (!account) {
account = new Account();
}
return account.balance;
}
/**
* Store 256-bit a value in memory to persistent storage.
*/
async storageStore(key, value) {
await this._stateManager.putStorage(this._env.address, key, value);
const account = await this._stateManager.getAccount(this._env.address);
if (!account) {
throw new Error("could not read account while persisting memory");
}
this._env.contract = account;
}
/**
* Loads a 256-bit value to memory from persistent storage.
* @param key - Storage key
* @param original - If true, return the original storage value (default: false)
*/
async storageLoad(key, original = false) {
if (original) {
return this._stateManager.originalStorageCache.get(this._env.address, key);
} else {
return this._stateManager.getStorage(this._env.address, key);
}
}
/**
* Store 256-bit a value in memory to transient storage.
* @param address Address to use
* @param key Storage key
* @param value Storage value
*/
transientStorageStore(key, value) {
return this._evm.transientStorage.put(this._env.address, key, value);
}
/**
* Loads a 256-bit value to memory from transient storage.
* @param address Address to use
* @param key Storage key
*/
transientStorageLoad(key) {
return this._evm.transientStorage.get(this._env.address, key);
}
/**
* Set the returning output data for the execution.
* @param returnData - Output data to return
*/
finish(returnData) {
this._result.returnValue = returnData;
trap(ERROR.STOP);
}
/**
* Set the returning output data for the execution. This will halt the
* execution immediately and set the execution result to "reverted".
* @param returnData - Output data to return
*/
revert(returnData) {
this._result.returnValue = returnData;
trap(ERROR.REVERT);
}
/**
* Returns address of currently executing account.
*/
getAddress() {
return this._env.address;
}
/**
* Returns balance of self.
*/
getSelfBalance() {
return this._env.contract.balance;
}
/**
* Returns the deposited value by the instruction/transaction
* responsible for this execution.
*/
getCallValue() {
return this._env.callValue;
}
/**
* Returns input data in current environment. This pertains to the input
* data passed with the message call instruction or transaction.
*/
getCallData() {
return this._env.callData;
}
/**
* Returns size of input data in current environment. This pertains to the
* input data passed with the message call instruction or transaction.
*/
getCallDataSize() {
return BigInt(this._env.callData.length);
}
/**
* Returns caller address. This is the address of the account
* that is directly responsible for this execution.
*/
getCaller() {
return bytesToBigInt(this._env.caller.bytes);
}
/**
* Returns the size of code running in current environment.
*/
getCodeSize() {
return BigInt(this._env.code.length);
}
/**
* Returns the code running in current environment.
*/
getCode() {
return this._env.code;
}
/**
* Returns the current gasCounter.
*/
getGasLeft() {
return this._runState.gasLeft;
}
/**
* Returns size of current return data buffer. This contains the return data
* from the last executed call, callCode, callDelegate, callStatic or create.
* Note: create only fills the return data buffer in case of a failure.
*/
getReturnDataSize() {
return BigInt(this._runState.returnBytes.length);
}
/**
* Returns the current return data buffer. This contains the return data
* from last executed call, callCode, callDelegate, callStatic or create.
* Note: create only fills the return data buffer in case of a failure.
*/
getReturnData() {
return this._runState.returnBytes;
}
/**
* Returns true if the current call must be executed statically.
*/
isStatic() {
return this._env.isStatic;
}
/**
* Returns price of gas in current environment.
*/
getTxGasPrice() {
return this._env.gasPrice;
}
/**
* Returns the execution's origination address. This is the
* sender of original transaction; it is never an account with
* non-empty associated code.
*/
getTxOrigin() {
return bytesToBigInt(this._env.origin.bytes);
}
/**
* Returns the block’s number.
*/
getBlockNumber() {
return this._env.block.header.number;
}
/**
* Returns the block's beneficiary address.
*/
getBlockCoinbase() {
let coinbase;
if (this.common.consensusAlgorithm() === ConsensusAlgorithm.Clique) {
coinbase = this._evm["_optsCached"].cliqueSigner(this._env.block.header);
} else {
coinbase = this._env.block.header.coinbase;
}
return bytesToBigInt(coinbase.toBytes());
}
/**
* Returns the block's timestamp.
*/
getBlockTimestamp() {
return this._env.block.header.timestamp;
}
/**
* Returns the block's difficulty.
*/
getBlockDifficulty() {
return this._env.block.header.difficulty;
}
/**
* Returns the block's prevRandao field.
*/
getBlockPrevRandao() {
return bytesToBigInt(this._env.block.header.prevRandao);
}
/**
* Returns the block's gas limit.
*/
getBlockGasLimit() {
return this._env.block.header.gasLimit;
}
/**
* Returns the Base Fee of the block as proposed in [EIP-3198](https://eips.ethereum.org/EIPS/eip-3198)
*/
getBlockBaseFee() {
const baseFee = this._env.block.header.baseFeePerGas;
if (baseFee === void 0) {
throw new Error("Block has no Base Fee");
}
return baseFee;
}
/**
* Returns the Blob Base Fee of the block as proposed in [EIP-7516](https://eips.ethereum.org/EIPS/eip-7516)
*/
getBlobBaseFee() {
const blobBaseFee = this._env.block.header.getBlobGasPrice();
if (blobBaseFee === void 0) {
throw new Error("Block has no Blob Base Fee");
}
return blobBaseFee;
}
/**
* Returns the chain ID for current chain. Introduced for the
* CHAINID opcode proposed in [EIP-1344](https://eips.ethereum.org/EIPS/eip-1344).
*/
getChainId() {
return this.common.chainId();
}
/**
* Sends a message with arbitrary data to a given address path.
*/
async call(gasLimit, address, value, data) {
const msg = new Message({
caller: this._env.address,
gasLimit,
to: address,
value,
data,
isStatic: this._env.isStatic,
depth: this._env.depth + 1,
blobVersionedHashes: this._env.blobVersionedHashes,
accessWitness: this._env.accessWitness
});
return this._baseCall(msg);
}
/**
* Message-call into this account with an alternative account's code.
*/
async callCode(gasLimit, address, value, data) {
const msg = new Message({
caller: this._env.address,
gasLimit,
to: this._env.address,
codeAddress: address,
value,
data,
isStatic: this._env.isStatic,
depth: this._env.depth + 1,
blobVersionedHashes: this._env.blobVersionedHashes,
accessWitness: this._env.accessWitness
});
return this._baseCall(msg);
}
/**
* Sends a message with arbitrary data to a given address path, but disallow
* state modifications. This includes log, create, selfdestruct and call with
* a non-zero value.
*/
async callStatic(gasLimit, address, value, data) {
const msg = new Message({
caller: this._env.address,
gasLimit,
to: address,
value,
data,
isStatic: true,
depth: this._env.depth + 1,
blobVersionedHashes: this._env.blobVersionedHashes,
accessWitness: this._env.accessWitness
});
return this._baseCall(msg);
}
/**
* Message-call into this account with an alternative account’s code, but
* persisting the current values for sender and value.
*/
async callDelegate(gasLimit, address, value, data) {
const msg = new Message({
caller: this._env.caller,
gasLimit,
to: this._env.address,
codeAddress: address,
value,
data,
isStatic: this._env.isStatic,
delegatecall: true,
depth: this._env.depth + 1,
blobVersionedHashes: this._env.blobVersionedHashes,
accessWitness: this._env.accessWitness
});
return this._baseCall(msg);
}
async _baseCall(msg) {
const selfdestruct = new Set(this._result.selfdestruct);
msg.selfdestruct = selfdestruct;
msg.gasRefund = this._runState.gasRefund;
this._runState.returnBytes = new Uint8Array(0);
let createdAddresses;
if (this.common.isActivatedEIP(6780)) {
createdAddresses = new Set(this._result.createdAddresses);
msg.createdAddresses = createdAddresses;
}
this._runState.returnBytes = new Uint8Array(0);
if (this._env.depth >= Number(this.common.param("stackLimit")) || msg.delegatecall !== true && this._env.contract.balance < msg.value) {
return BIGINT_0;
}
const results = await this._evm.runCall({ message: msg });
if (results.execResult.logs) {
this._result.logs = this._result.logs.concat(results.execResult.logs);
}
this.useGas(results.execResult.executionGasUsed, "CALL, STATICCALL, DELEGATECALL, CALLCODE");
if (results.execResult.returnValue !== void 0 && (!results.execResult.exceptionError || results.execResult.exceptionError.error === ERROR.REVERT)) {
this._runState.returnBytes = results.execResult.returnValue;
}
if (!results.execResult.exceptionError) {
for (const addressToSelfdestructHex of selfdestruct) {
this._result.selfdestruct.add(addressToSelfdestructHex);
}
if (this.common.isActivatedEIP(6780)) {
for (const item of createdAddresses) {
this._result.createdAddresses.add(item);
}
}
const account = await this._stateManager.getAccount(this._env.address);
if (!account) {
throw new Error("could not read contract account");
}
this._env.contract = account;
this._runState.gasRefund = results.execResult.gasRefund ?? BIGINT_0;
}
return this._getReturnCode(results);
}
/**
* Creates a new contract with a given value.
*/
async create(gasLimit, value, codeToRun, salt, eofCallData) {
const selfdestruct = new Set(this._result.selfdestruct);
const caller = this._env.address;
const depth = this._env.depth + 1;
this._runState.returnBytes = new Uint8Array(0);
if (this._env.depth >= Number(this.common.param("stackLimit")) || this._env.contract.balance < value) {
return BIGINT_0;
}
if (this._env.contract.nonce >= MAX_UINT64) {
return BIGINT_0;
}
this._env.contract.nonce += BIGINT_1;
await this.journal.putAccount(this._env.address, this._env.contract);
if (this.common.isActivatedEIP(3860)) {
if (codeToRun.length > Number(this.common.param("maxInitCodeSize")) && this._evm.allowUnlimitedInitCodeSize === false) {
return BIGINT_0;
}
}
const message = new Message({
caller,
gasLimit,
value,
data: codeToRun,
eofCallData,
salt,
depth,
selfdestruct,
gasRefund: this._runState.gasRefund,
blobVersionedHashes: this._env.blobVersionedHashes,
accessWitness: this._env.accessWitness
});
let createdAddresses;
if (this.common.isActivatedEIP(6780)) {
createdAddresses = new Set(this._result.createdAddresses);
message.createdAddresses = createdAddresses;
}
const results = await this._evm.runCall({ message });
if (results.execResult.logs) {
this._result.logs = this._result.logs.concat(results.execResult.logs);
}
this.useGas(results.execResult.executionGasUsed, "CREATE");
if (results.execResult.exceptionError && results.execResult.exceptionError.error === ERROR.REVERT) {
this._runState.returnBytes = results.execResult.returnValue;
}
if (!results.execResult.exceptionError || results.execResult.exceptionError.error === ERROR.CODESTORE_OUT_OF_GAS) {
for (const addressToSelfdestructHex of selfdestruct) {
this._result.selfdestruct.add(addressToSelfdestructHex);
}
if (this.common.isActivatedEIP(6780)) {
for (const item of createdAddresses) {
this._result.createdAddresses.add(item);
}
}
const account = await this._stateManager.getAccount(this._env.address);
if (!account) {
throw new Error("could not read contract account");
}
this._env.contract = account;
this._runState.gasRefund = results.execResult.gasRefund ?? BIGINT_0;
if (results.createdAddress) {
return bytesToBigInt(results.createdAddress.bytes);
}
}
return this._getReturnCode(results, true);
}
/**
* Creates a new contract with a given value. Generates
* a deterministic address via CREATE2 rules.
*/
async create2(gasLimit, value, data, salt) {
return this.create(gasLimit, value, data, salt);
}
/**
* Creates a new contract with a given value. Generates
* a deterministic address via EOFCREATE rules.
*/
async eofcreate(gasLimit, value, containerData, salt, callData) {
return this.create(gasLimit, value, containerData, salt, callData);
}
/**
* Mark account for later deletion and give the remaining balance to the
* specified beneficiary address. This will cause a trap and the
* execution will be aborted immediately.
* @param toAddress - Beneficiary address
*/
async selfDestruct(toAddress) {
return this._selfDestruct(toAddress);
}
async _selfDestruct(toAddress) {
if (!this._result.selfdestruct.has(bytesToHex$1(this._env.address.bytes))) {
this.refundGas(this.common.param("selfdestructRefundGas"));
}
this._result.selfdestruct.add(bytesToHex$1(this._env.address.bytes));
const toSelf = equalsBytes(toAddress.bytes, this._env.address.bytes);
if (!toSelf) {
let toAccount = await this._stateManager.getAccount(toAddress);
if (!toAccount) {
toAccount = new Account();
}
toAccount.balance += this._env.contract.balance;
await this.journal.putAccount(toAddress, toAccount);
}
let doModify = !this.common.isActivatedEIP(6780);
if (!doModify) {
doModify = this._env.createdAddresses.has(this._env.address.toString());
if (!doModify) {
doModify = !toSelf;
}
}
if (doModify) {
await this._stateManager.modifyAccountFields(this._env.address, {
balance: BIGINT_0
});
}
trap(ERROR.STOP);
}
/**
* Creates a new log in the current environment.
*/
log(data, numberOfTopics, topics) {
if (numberOfTopics < 0 || numberOfTopics > 4) {
trap(ERROR.OUT_OF_RANGE);
}
if (topics.length !== numberOfTopics) {
trap(ERROR.INTERNAL_ERROR);
}
const log = [this._env.address.bytes, topics, data];
this._result.logs.push(log);
}
_getReturnCode(results, isEOFCreate = false) {
if (this._runState.env.eof === void 0 || isEOFCreate) {
if (results.execResult.exceptionError) {
return BIGINT_0;
} else {
return BIGINT_1;
}
} else {
if (results.execResult.exceptionError !== void 0) {
if (results.execResult.exceptionError.error === ERROR.REVERT) {
return BIGINT_1;
} else {
return BIGINT_2;
}
}
return BIGINT_0;
}
}
}
class Journal {
constructor(stateManager, common2) {
var _a, _b;
this.DEBUG = typeof window === "undefined" ? ((_b = (_a = process == null ? void 0 : process.env) == null ? void 0 : _a.DEBUG) == null ? void 0 : _b.includes("ethjs")) ?? false : false;
this._debug = debugDefault("evm:journal");
this.cleanJournal();
this.journalHeight = 0;
this.stateManager = stateManager;
this.common = common2;
}
/**
* Clears the internal `accessList` map, and mark this journal to start reporting
* which addresses and storages have been accessed
*/
startReportingAccessList() {
this.accessList = /* @__PURE__ */ new Map();
}
/**
* Clears the internal `preimages` map, and marks this journal to start reporting
* the images (hashed addresses) of the accounts that have been accessed
*/
startReportingPreimages() {
this.preimages = /* @__PURE__ */ new Map();
}
async putAccount(address, account) {
this.touchAddress(address);
return this.stateManager.putAccount(address, account);
}
async deleteAccount(address) {
this.touchAddress(address);
await this.stateManager.deleteAccount(address);
}
touchAddress(address) {
const str = address.toString().slice(2);
this.touchAccount(str);
}
touchAccount(address) {
if (this.preimages !== void 0) {
const bytesAddress = unprefixedHexToBytes(address);
if (this.stateManager.getAppliedKey === void 0) {
throw new Error(
"touchAccount: stateManager.getAppliedKey can not be undefined if preimage storing is enabled"
);
}
const hashedKey = this.stateManager.getAppliedKey(bytesAddress);
this.preimages.set(bytesToHex$1(hashedKey), bytesAddress);
}
if (!this.touched.has(address)) {
this.touched.add(address);
const diffArr = this.journalDiff[this.journalDiff.length - 1][1];
diffArr[2].add(address);
}
}
async commit() {
this.journalHeight--;
this.journalDiff.push([this.journalHeight, [/* @__PURE__ */ new Set(), /* @__PURE__ */ new Map(), /* @__PURE__ */ new Set()]]);
await this.stateManager.commit();
}
async checkpoint() {
this.journalHeight++;
this.journalDiff.push([this.journalHeight, [/* @__PURE__ */ new Set(), /* @__PURE__ */ new Map(), /* @__PURE__ */ new Set()]]);
await this.stateManager.checkpoint();
}
async revert() {
let finalI;
for (let i = this.journalDiff.length - 1; i >= 0; i--) {
finalI = i;
const [height, diff] = this.journalDiff[i];
if (height < this.journalHeight) {
break;
}
const addressSet = diff[0];
const slotsMap = diff[1];
const touchedSet = diff[2];
for (const address of addressSet) {
if (this.journal.has(address)) {
this.journal.delete(address);
}
}
for (const [address, delSlots] of slotsMap) {
if (this.journal.has(address)) {
const slots = this.journal.get(address);
for (const delSlot of delSlots) {
slots.delete(delSlot);
}
}
}
for (const address of touchedSet) {
if (address !== RIPEMD160_ADDRESS_STRING) {
this.touched.delete(address);
}
}
}
this.journalDiff = this.journalDiff.slice(0, finalI + 1);
this.journalHeight--;
await this.stateManager.revert();
}
cleanJournal() {
this.journalHeight = 0;
this.journal = /* @__PURE__ */ new Map();
this.alwaysWarmJournal = /* @__PURE__ */ new Map();
this.touched = /* @__PURE__ */ new Set();
this.journalDiff = [[0, [/* @__PURE__ */ new Set(), /* @__PURE__ */ new Map(), /* @__PURE__ */ new Set()]]];
}
/**
* Removes accounts from the state trie that have been touched,
* as defined in EIP-161 (https://eips.ethereum.org/EIPS/eip-161).
* Also cleanups any other internal fields
*/
async cleanup() {
if (this.common.gteHardfork(Hardfork.SpuriousDragon)) {
for (const addressHex of this.touched) {
const address = new Address(hexToBytes$2(`0x${addressHex}`));
const account = await this.stateManager.getAccount(address);
if (account === void 0 || account.isEmpty()) {
await this.deleteAccount(address);
if (this.DEBUG) {
this._debug(`Cleanup touched account address=${address} (>= SpuriousDragon)`);
}
}
}
}
this.cleanJournal();
delete this.accessList;
delete this.preimages;
}
addAlwaysWarmAddress(addressStr, addToAccessList = false) {
const address = stripHexPrefix$1(addressStr);
if (!this.alwaysWarmJournal.has(address)) {
this.alwaysWarmJournal.set(address, /* @__PURE__ */ new Set());
}
if (addToAccessList && this.accessList !== void 0) {
if (!this.accessList.has(address)) {
this.accessList.set(address, /* @__PURE__ */ new Set());
}
}
}
addAlwaysWarmSlot(addressStr, slotStr, addToAccessList = false) {
const address = stripHexPrefix$1(addressStr);
this.addAlwaysWarmAddress(address, addToAccessList);
const slotsSet = this.alwaysWarmJournal.get(address);
const slot = stripHexPrefix$1(slotStr);
slotsSet.add(slot);
if (addToAccessList && this.accessList !== void 0) {
this.accessList.get(address).add(slot);
}
}
/**
* Returns true if the address is warm in the current context
* @param address - The address (as a Uint8Array) to check
*/
isWarmedAddress(address) {
const addressHex = bytesToUnprefixedHex(address);
const warm = this.journal.has(addressHex) || this.alwaysWarmJournal.has(addressHex);
return warm;
}
/**
* Add a warm address in the current context
* @param addressArr - The address (as a Uint8Array) to check
*/
addWarmedAddress(addressArr) {
const address = bytesToUnprefixedHex(addressArr);
if (!this.journal.has(address)) {
this.journal.set(address, /* @__PURE__ */ new Set());
const diffArr = this.journalDiff[this.journalDiff.length - 1][1];
diffArr[0].add(address);
}
if (this.accessList !== void 0) {
if (!this.accessList.has(address)) {
this.accessList.set(address, /* @__PURE__ */ new Set());
}
}
}
/**
* Returns true if the slot of the address is warm
* @param address - The address (as a Uint8Array) to check
* @param slot - The slot (as a Uint8Array) to check
*/
isWarmedStorage(address, slot) {
const addressHex = bytesToUnprefixedHex(address);
const slots = this.journal.get(addressHex);
if (slots === void 0) {
if (this.alwaysWarmJournal.has(addressHex)) {
return this.alwaysWarmJournal.get(addressHex).has(bytesToUnprefixedHex(slot));
}
return false;
}
if (slots.has(bytesToUnprefixedHex(slot))) {
return true;
} else if (this.alwaysWarmJournal.has(addressHex)) {
return this.alwaysWarmJournal.get(addressHex).has(bytesToUnprefixedHex(slot));
}
return false;
}
/**
* Mark the storage slot in the address as warm in the current context
* @param address - The address (as a Uint8Array) to check
* @param slot - The slot (as a Uint8Array) to check
*/
addWarmedStorage(address, slot) {
const addressHex = bytesToUnprefixedHex(address);
let slots = this.journal.get(addressHex);
if (slots === void 0) {
this.addWarmedAddress(address);
slots = this.journal.get(addressHex);
}
const slotStr = bytesToUnprefixedHex(slot);
if (!slots.has(slotStr)) {
slots.add(slotStr);
const diff = this.journalDiff[this.journalDiff.length - 1][1];
const addressSlotMap = diff[1];
if (!addressSlotMap.has(addressHex)) {
addressSlotMap.set(addressHex, /* @__PURE__ */ new Set());
}
const slotsSet = addressSlotMap.get(addressHex);
slotsSet.add(slotStr);
}
if (this.accessList !== void 0) {
const addrSet = this.accessList.get(addressHex);
addrSet.add(slotStr);
}
}
}
const blockGasLimit = 3e7;
const slotTime = 12;
const bpsNormalizer = blockGasLimit / slotTime;
class Timer {
constructor(tag) {
this.runTime = 0;
this.tag = tag;
this.startTime = performance.now();
}
pause() {
this.runTime = this.runTime + performance.now() - this.startTime;
}
unpause() {
this.startTime = performance.now();
}
time() {
return (performance.now() - this.startTime + this.runTime) / 1e3;
}
}
class EVMPerformanceLogger {
constructor() {
this.clear();
}
clear() {
this.opcodes = {};
this.precompiles = {};
}
getLogs() {
function getLogsFor(obj) {
const output2 = [];
for (const key in obj) {
const field = obj[key];
const gasPerSecond = field.gasUsed / field.time;
const entry = {
calls: field.calls,
totalTime: Math.round(field.time * 1e6) / 1e3,
avgTimePerCall: Math.round(field.time / field.calls * 1e6) / 1e3,
gasUsed: field.gasUsed,
millionGasPerSecond: Math.round(gasPerSecond / 1e3) / 1e3,
blocksPerSlot: Math.round(gasPerSecond / bpsNormalizer * 1e3) / 1e3,
tag: key
};
if (field.dynamicGasUsed !== void 0) {
entry.staticGas = field.staticGas;
entry.staticGasUsed = field.staticGas * field.calls;
entry.dynamicGasUsed = field.dynamicGasUsed;
}
output2.push(entry);
}
output2.sort((a, b) => {
return b.millionGasPerSecond - a.millionGasPerSecond;
});
return output2;
}
return {
opcodes: getLogsFor(this.opcodes),
precompiles: getLogsFor(this.precompiles)
};
}
hasTimer() {
return this.currentTimer !== void 0;
}
// Start a new timer
// Only one timer can be timing at the same time
startTimer(tag) {
if (this.currentTimer !== void 0) {
throw new Error("Cannot have two timers running at the same time");
}
this.currentTimer = new Timer(tag);
return this.currentTimer;
}
// Pauses current timer and returns that timer
pauseTimer() {
const timer = this.currentTimer;
if (timer === void 0) {
throw new Error("No timer to pause");
}
timer.pause();
this.currentTimer = void 0;
return timer;
}
// Unpauses current timer and returns that timer
unpauseTimer(timer) {
if (this.currentTimer !== void 0) {
throw new Error("Cannot unpause timer: another timer is already running");
}
timer.unpause();
this.currentTimer = timer;
}
// Stops a timer from running
stopTimer(timer, gasUsed, targetTimer = "opcodes", staticGas, dynamicGas) {
if (this.currentTimer === void 0 || this.currentTimer !== timer) {
throw new Error("Cannot stop timer: another timer is already running");
}
const time = timer.time();
const tag = timer.tag;
this.currentTimer = void 0;
const target = this[targetTimer];
if (target[tag] === void 0) {
target[tag] = {
calls: 0,
time: 0,
gasUsed: 0
};
}
const obj = target[tag];
obj.calls++;
obj.time += time;
obj.gasUsed += gasUsed;
if (targetTimer === "opcodes") {
obj.staticGas = staticGas;
obj.dynamicGasUsed = (obj.dynamicGasUsed ?? 0) + dynamicGas;
}
}
}
const paramsEVM = {
/**
* Frontier/Chainstart
*/
1: {
// gasConfig
maxRefundQuotient: 2,
// Maximum refund quotient; max tx refund is min(tx.gasUsed/maxRefundQuotient, tx.gasRefund)
// gasPrices
basefeeGas: 2,
// Gas base cost, used e.g. for ChainID opcode (Istanbul)
expGas: 10,
// Base fee of the EXP opcode
expByteGas: 10,
// Times ceil(log256(exponent)) for the EXP instruction
keccak256Gas: 30,
// Base fee of the SHA3 opcode
keccak256WordGas: 6,
// Once per word of the SHA3 operation's data
sloadGas: 50,
// Base fee of the SLOAD opcode
sstoreSetGas: 2e4,
// Once per SSTORE operation if the zeroness changes from zero
sstoreResetGas: 5e3,
// Once per SSTORE operation if the zeroness does not change from zero
sstoreRefundGas: 15e3,
// Once per SSTORE operation if the zeroness changes to zero
jumpdestGas: 1,
// Base fee of the JUMPDEST opcode
logGas: 375,
// Base fee of the LOG opcode
logDataGas: 8,
// Per byte in a LOG* operation's data
logTopicGas: 375,
// Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas
createGas: 32e3,
// Base fee of the CREATE opcode
callGas: 40,
// Base fee of the CALL opcode
callStipendGas: 2300,
// Free gas given at beginning of call
callValueTransferGas: 9e3,
// Paid for CALL when the value transfer is non-zero
callNewAccountGas: 25e3,
// Paid for CALL when the destination address didn't exist prior
selfdestructRefundGas: 24e3,
// Refunded following a selfdestruct operation
memoryGas: 3,
// Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL
quadCoefficientDivGas: 512,
// Divisor for the quadratic particle of the memory cost equation
createDataGas: 200,
//
copyGas: 3,
// Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added
ecRecoverGas: 3e3,
sha256Gas: 60,
sha256WordGas: 12,
ripemd160Gas: 600,
ripemd160WordGas: 120,
identityGas: 15,
identityWordGas: 3,
stopGas: 0,
// Base fee of the STOP opcode
addGas: 3,
// Base fee of the ADD opcode
mulGas: 5,
// Base fee of the MUL opcode
subGas: 3,
// Base fee of the SUB opcode
divGas: 5,
// Base fee of the DIV opcode
sdivGas: 5,
// Base fee of the SDIV opcode
modGas: 5,
// Base fee of the MOD opcode
smodGas: 5,
// Base fee of the SMOD opcode
addmodGas: 8,
// Base fee of the ADDMOD opcode
mulmodGas: 8,
// Base fee of the MULMOD opcode
signextendGas: 5,
// Base fee of the SIGNEXTEND opcode
ltGas: 3,
// Base fee of the LT opcode
gtGas: 3,
// Base fee of the GT opcode
sltGas: 3,
// Base fee of the SLT opcode
sgtGas: 3,
// Base fee of the SGT opcode
eqGas: 3,
// Base fee of the EQ opcode
iszeroGas: 3,
// Base fee of the ISZERO opcode
andGas: 3,
// Base fee of the AND opcode
orGas: 3,
// Base fee of the OR opcode
xorGas: 3,
// Base fee of the XOR opcode
notGas: 3,
// Base fee of the NOT opcode
byteGas: 3,
// Base fee of the BYTE opcode
addressGas: 2,
// Base fee of the ADDRESS opcode
balanceGas: 20,
// Base fee of the BALANCE opcode
originGas: 2,
// Base fee of the ORIGIN opcode
callerGas: 2,
// Base fee of the CALLER opcode
callvalueGas: 2,
// Base fee of the CALLVALUE opcode
calldataloadGas: 3,
// Base fee of the CALLDATALOAD opcode
calldatasizeGas: 2,
// Base fee of the CALLDATASIZE opcode
calldatacopyGas: 3,
// Base fee of the CALLDATACOPY opcode
codesizeGas: 2,
// Base fee of the CODESIZE opcode
codecopyGas: 3,
// Base fee of the CODECOPY opcode
gaspriceGas: 2,
// Base fee of the GASPRICE opcode
extcodesizeGas: 20,
// Base fee of the EXTCODESIZE opcode
extcodecopyGas: 20,
// Base fee of the EXTCODECOPY opcode
blockhashGas: 20,
// Base fee of the BLOCKHASH opcode
coinbaseGas: 2,
// Base fee of the COINBASE opcode
timestampGas: 2,
// Base fee of the TIMESTAMP opcode
numberGas: 2,
// Base fee of the NUMBER opcode
difficultyGas: 2,
// Base fee of the DIFFICULTY opcode
gaslimitGas: 2,
// Base fee of the GASLIMIT opcode
popGas: 2,
// Base fee of the POP opcode
mloadGas: 3,
// Base fee of the MLOAD opcode
mstoreGas: 3,
// Base fee of the MSTORE opcode
mstore8Gas: 3,
// Base fee of the MSTORE8 opcode
sstoreGas: 0,
// Base fee of the SSTORE opcode
jumpGas: 8,
// Base fee of the JUMP opcode
jumpiGas: 10,
// Base fee of the JUMPI opcode
pcGas: 2,
// Base fee of the PC opcode
msizeGas: 2,
// Base fee of the MSIZE opcode
gasGas: 2,
// Base fee of the GAS opcode
pushGas: 3,
// Base fee of the PUSH opcode
dupGas: 3,
// Base fee of the DUP opcode
swapGas: 3,
// Base fee of the SWAP opcode
callcodeGas: 40,
// Base fee of the CALLCODE opcode
returnGas: 0,
// Base fee of the RETURN opcode
invalidGas: 0,
// Base fee of the INVALID opcode
selfdestructGas: 0,
// Base fee of the SELFDESTRUCT opcode
prevrandaoGas: 0,
// TODO: these below 0-gas additions might also point to non-clean implementations in the code base
// evm
stackLimit: 1024,
// Maximum size of VM stack allowed
callCreateDepth: 1024
// Maximum depth of call/create stack
},
/**
. * Homestead HF Meta EIP
. */
606: {
// gasPrices
delegatecallGas: 40
// Base fee of the DELEGATECALL opcode
},
/**
. * TangerineWhistle HF Meta EIP
. */
608: {
// gasPrices
sloadGas: 200,
// Once per SLOAD operation
callGas: 700,
// Once per CALL operation & message call transaction
extcodesizeGas: 700,
// Base fee of the EXTCODESIZE opcode
extcodecopyGas: 700,
// Base fee of the EXTCODECOPY opcode
balanceGas: 400,
// Base fee of the BALANCE opcode
delegatecallGas: 700,
// Base fee of the DELEGATECALL opcode
callcodeGas: 700,
// Base fee of the CALLCODE opcode
selfdestructGas: 5e3
// Base fee of the SELFDESTRUCT opcode
},
/**
. * Spurious Dragon HF Meta EIP
. */
607: {
// gasPrices
expByteGas: 50,
// Times ceil(log256(exponent)) for the EXP instruction
// evm
maxCodeSize: 24576
// Maximum length of contract code
},
/**
. * Byzantium HF Meta EIP
. */
609: {
// gasPrices
modexpGquaddivisorGas: 20,
// Gquaddivisor from modexp precompile for gas calculation
bn254AddGas: 500,
// Gas costs for curve addition precompile
bn254MulGas: 4e4,
// Gas costs for curve multiplication precompile
bn254PairingGas: 1e5,
// Base gas costs for curve pairing precompile
bn254PairingWordGas: 8e4,
// Gas costs regarding curve pairing precompile input length
revertGas: 0,
// Base fee of the REVERT opcode
staticcallGas: 700,
// Base fee of the STATICCALL opcode
returndatasizeGas: 2,
// Base fee of the RETURNDATASIZE opcode
returndatacopyGas: 3
// Base fee of the RETURNDATACOPY opcode
},
/**
. * Constantinople HF Meta EIP
. */
1013: {
// gasPrices
netSstoreNoopGas: 200,
// Once per SSTORE operation if the value doesn't change
netSstoreInitGas: 2e4,
// Once per SSTORE operation from clean zero
netSstoreCleanGas: 5e3,
// Once per SSTORE operation from clean non-zero
netSstoreDirtyGas: 200,
// Once per SSTORE operation from dirty
netSstoreClearRefundGas: 15e3,
// Once per SSTORE operation for clearing an originally existing storage slot
netSstoreResetRefundGas: 4800,
// Once per SSTORE operation for resetting to the original non-zero value
netSstoreResetClearRefundGas: 19800,
// Once per SSTORE operation for resetting to the original zero value
shlGas: 3,
// Base fee of the SHL opcode
shrGas: 3,
// Base fee of the SHR opcode
sarGas: 3,
// Base fee of the SAR opcode
extcodehashGas: 400,
// Base fee of the EXTCODEHASH opcode
create2Gas: 32e3
// Base fee of the CREATE2 opcode
},
/**
. * Petersburg HF Meta EIP
. */
1716: {
// gasPrices
netSstoreNoopGas: null,
// Removed along EIP-1283
netSstoreInitGas: null,
// Removed along EIP-1283
netSstoreCleanGas: null,
// Removed along EIP-1283
netSstoreDirtyGas: null,
// Removed along EIP-1283
netSstoreClearRefundGas: null,
// Removed along EIP-1283
netSstoreResetRefundGas: null,
// Removed along EIP-1283
netSstoreResetClearRefundGas: null
// Removed along EIP-1283
},
/**
. * Istanbul HF Meta EIP
. */
1679: {
// gasPrices
blake2RoundGas: 1,
// Gas cost per round for the Blake2 F precompile
bn254AddGas: 150,
// Gas costs for curve addition precompile
bn254MulGas: 6e3,
// Gas costs for curve multiplication precompile
bn254PairingGas: 45e3,
// Base gas costs for curve pairing precompile
bn254PairingWordGas: 34e3,
// Gas costs regarding curve pairing precompile input length
sstoreSentryEIP2200Gas: 2300,
// Minimum gas required to be present for an SSTORE call, not consumed
sstoreNoopEIP2200Gas: 800,
// Once per SSTORE operation if the value doesn't change
sstoreDirtyEIP2200Gas: 800,
// Once per SSTORE operation if a dirty value is changed
sstoreInitEIP2200Gas: 2e4,
// Once per SSTORE operation from clean zero to non-zero
sstoreInitRefundEIP2200Gas: 19200,
// Once per SSTORE operation for resetting to the original zero value
sstoreCleanEIP2200Gas: 5e3,
// Once per SSTORE operation from clean non-zero to something else
sstoreCleanRefundEIP2200Gas: 4200,
// Once per SSTORE operation for resetting to the original non-zero value
sstoreClearRefundEIP2200Gas: 15e3,
// Once per SSTORE operation for clearing an originally existing storage slot
balanceGas: 700,
// Base fee of the BALANCE opcode
extcodehashGas: 700,
// Base fee of the EXTCODEHASH opcode
chainidGas: 2,
// Base fee of the CHAINID opcode
selfbalanceGas: 5,
// Base fee of the SELFBALANCE opcode
sloadGas: 800
// Base fee of the SLOAD opcode
},
/**
. * SWAPN, DUPN and EXCHANGE instructions
. */
663: {
// gasPrices
dupnGas: 3,
// Base fee of the DUPN opcode
swapnGas: 3,
// Base fee of the SWAPN opcode
exchangeGas: 3
// Base fee of the EXCHANGE opcode
},
/**
. * Transient storage opcodes
. */
1153: {
// gasPrices
tstoreGas: 100,
// Base fee of the TSTORE opcode
tloadGas: 100
// Base fee of the TLOAD opcode
},
1559: {
elasticityMultiplier: 2
// Maximum block gas target elasticity
},
/**
. * ModExp gas cost
. */
2565: {
// gasPrices
modexpGquaddivisorGas: 3
// Gquaddivisor from modexp precompile for gas calculation
},
/**
* BLS12-381 precompiles
*/
2537: {
// gasPrices
bls12381G1AddGas: 500,
// Gas cost of a single BLS12-381 G1 addition precompile-call
bls12381G1MulGas: 12e3,
// Gas cost of a single BLS12-381 G1 multiplication precompile-call
bls12381G2AddGas: 800,
// Gas cost of a single BLS12-381 G2 addition precompile-call
bls12381G2MulGas: 45e3,
// Gas cost of a single BLS12-381 G2 multiplication precompile-call
bls12381PairingBaseGas: 65e3,
// Base gas cost of BLS12-381 pairing check
bls12381PairingPerPairGas: 43e3,
// Per-pair gas cost of BLS12-381 pairing check
bls12381MapG1Gas: 5500,
// Gas cost of BLS12-381 map field element to G1
bls12381MapG2Gas: 75e3
// Gas cost of BLS12-381 map field element to G2
},
/**
. * Gas cost increases for state access opcodes
. */
2929: {
// gasPrices
coldsloadGas: 2100,
// Gas cost of the first read of storage from a given location (per transaction)
coldaccountaccessGas: 2600,
// Gas cost of the first read of a given address (per transaction)
warmstoragereadGas: 100,
// Gas cost of reading storage locations which have already loaded 'cold'
sstoreCleanEIP2200Gas: 2900,
// Once per SSTORE operation from clean non-zero to something else
sstoreNoopEIP2200Gas: 100,
// Once per SSTORE operation if the value doesn't change
sstoreDirtyEIP2200Gas: 100,
// Once per SSTORE operation if a dirty value is changed
sstoreInitRefundEIP2200Gas: 19900,
// Once per SSTORE operation for resetting to the original zero value
sstoreCleanRefundEIP2200Gas: 4900,
// Once per SSTORE operation for resetting to the original non-zero value
callGas: 0,
// Base fee of the CALL opcode
callcodeGas: 0,
// Base fee of the CALLCODE opcode
delegatecallGas: 0,
// Base fee of the DELEGATECALL opcode
staticcallGas: 0,
// Base fee of the STATICCALL opcode
balanceGas: 0,
// Base fee of the BALANCE opcode
extcodesizeGas: 0,
// Base fee of the EXTCODESIZE opcode
extcodecopyGas: 0,
// Base fee of the EXTCODECOPY opcode
extcodehashGas: 0,
// Base fee of the EXTCODEHASH opcode
sloadGas: 0,
// Base fee of the SLOAD opcode
sstoreGas: 0
// Base fee of the SSTORE opcode
},
/**
* Save historical block hashes in state (Verkle related usage, UNSTABLE)
*/
2935: {
// evm
historyStorageAddress: "0x0aae40965e6800cd9b1f4b05ff21581047e3f91e",
// The address where the historical blockhashes are stored
historyServeWindow: 8192
// The amount of blocks to be served by the historical blockhash contract
},
/**
. * BASEFEE opcode
. */
3198: {
// gasPrices
basefeeGas: 2
// Gas cost of the BASEFEE opcode
},
/**
. * Reduction in refunds
. */
3529: {
// gasConfig
maxRefundQuotient: 5,
// Maximum refund quotient; max tx refund is min(tx.gasUsed/maxRefundQuotient, tx.gasRefund)
// gasPrices
selfdestructRefundGas: 0,
// Refunded following a selfdestruct operation
sstoreClearRefundEIP2200Gas: 4800
// Once per SSTORE operation for clearing an originally existing storage slot
},
/**
. * PUSH0 instruction
. */
3855: {
// gasPrices
push0Gas: 2
// Base fee of the PUSH0 opcode
},
/**
. * Limit and meter initcode
. */
3860: {
// gasPrices
initCodeWordGas: 2,
// Gas to pay for each word (32 bytes) of initcode when creating a contract
// vm
maxInitCodeSize: 49152
// Maximum length of initialization code when creating a contract
},
/**
* EOF - Static relative jumps
*/
4200: {
// gasPrices
rjumpGas: 2,
// Base fee of the RJUMP opcode
rjumpiGas: 4,
// Base fee of the RJUMPI opcode
rjumpvGas: 4
// Base fee of the RJUMPV opcode
},
/**
. * Supplant DIFFICULTY opcode with PREVRANDAO
. */
4399: {
// gasPrices
prevrandaoGas: 2
// Base fee of the PREVRANDAO opcode (previously DIFFICULTY)
},
/**
* EOF - Functions
*/
4750: {
// gasPrices
callfGas: 5,
// Base fee of the CALLF opcode
retfGas: 3
// Base fee of the RETF opcode
},
/**
. * Shard Blob Transactions
. */
4844: {
kzgPointEvaluationPrecompileGas: 5e4,
// The fee associated with the point evaluation precompile
blobhashGas: 3,
// Base fee of the BLOBHASH opcode
// sharding
blobCommitmentVersionKzg: 1,
// The number indicated a versioned hash is a KZG commitment
fieldElementsPerBlob: 4096
// The number of field elements allowed per blob
},
/**
* MCOPY - Memory copying instruction
*/
5656: {
// gasPrices
mcopyGas: 3
// Base fee of the MCOPY opcode
},
/**
* EOF - JUMPF and non-returning functions
*/
6206: {
// gasPrices
jumpfGas: 5
// Base fee of the JUMPF opcode
},
/**
* Ethereum state using a unified verkle tree (experimental)
*/
6800: {
// gasPrices
createGas: 1e3,
// Base fee of the CREATE opcode
coldsloadGas: 0
// Gas cost of the first read of storage from a given location (per transaction)
},
/**
. * Revamped CALL instructions
. */
7069: {
/* Note: per EIP these are the additionally required EIPs:
EIP 150 - This is the entire Tangerine Whistle hardfork
EIP 211 - (RETURNDATASIZE / RETURNDATACOPY) - Included in Byzantium
EIP 214 - (STATICCALL) - Included in Byzantium
*/
// gasPrices
extcallGas: 0,
// Base fee of the EXTCALL opcode
extdelegatecallGas: 0,
// Base fee of the EXTDELEGATECALL opcode
extstaticcallGas: 0,
// Base fee of the EXTSTATICCALL opcode
returndataloadGas: 3,
// Base fee of the RETURNDATALOAD opcode
minRetainedGas: 5e3,
// Minimum gas retained prior to executing an EXT*CALL opcode (this is the minimum gas available after performing the EXT*CALL)
minCalleeGas: 2300
//Minimum gas available to the the address called by an EXT*CALL opcode
},
/**
* EOF - Data section access instructions
*/
7480: {
// gasPrices
dataloadGas: 4,
// Base fee of the DATALOAD opcode
dataloadnGas: 3,
// Base fee of the DATALOADN opcode
datasizeGas: 2,
// Base fee of the DATASIZE opcode
datacopyGas: 3
// Base fee of the DATACOPY opcode
},
/**
. * BLOBBASEFEE opcode
. */
7516: {
// gasPrices
blobbasefeeGas: 2
// Gas cost of the BLOBBASEFEE opcode
},
/**
. * EOF Contract Creation
. */
7620: {
/* Note: per EIP these are the additionally required EIPs:
EIP 170 - (Max contract size) - Included in Spurious Dragon
*/
// gasPrices
eofcreateGas: 32e3,
// Base fee of the EOFCREATE opcode (Same as CREATE/CREATE2)
returncontractGas: 0
// Base fee of the RETURNCONTRACT opcode
}
};
const gasLimitCheck = (opts, gasUsed, pName) => {
if (opts._debug !== void 0) {
opts._debug(
`Run ${pName} precompile data=${short(opts.data)} length=${opts.data.length} gasLimit=${opts.gasLimit} gasUsed=${gasUsed}`
);
}
if (opts.gasLimit < gasUsed) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: OOG`);
}
return false;
}
return true;
};
const equalityLengthCheck = (opts, length, pName) => {
if (opts.data.length !== length) {
if (opts._debug !== void 0) {
opts._debug(
`${pName} failed: Invalid input length length=${opts.data.length} (expected: ${length})`
);
}
return false;
}
return true;
};
const moduloLengthCheck = (opts, length, pName) => {
if (opts.data.length % length !== 0) {
if (opts._debug !== void 0) {
opts._debug(
`${pName} failed: Invalid input length length=${opts.data.length} (expected: ${length}*k bytes)`
);
}
return false;
}
return true;
};
function precompile01(opts) {
const pName = getPrecompileName("01");
const ecrecoverFunction = opts.common.customCrypto.ecrecover ?? ecrecover;
const gasUsed = opts.common.param("ecRecoverGas");
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
const data = setLengthRight(opts.data, 128);
const msgHash = data.subarray(0, 32);
const v = data.subarray(32, 64);
const vBigInt = bytesToBigInt(v);
if (vBigInt !== BIGINT_27 && vBigInt !== BIGINT_28) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: v neither 27 nor 28`);
}
return {
executionGasUsed: gasUsed,
returnValue: new Uint8Array()
};
}
const r = data.subarray(64, 96);
const s = data.subarray(96, 128);
let publicKey;
try {
if (opts._debug !== void 0) {
opts._debug(
`${pName}: PK recovery with msgHash=${bytesToHex$1(msgHash)} v=${bytesToHex$1(
v
)} r=${bytesToHex$1(r)}s=${bytesToHex$1(s)}}`
);
}
publicKey = ecrecoverFunction(msgHash, bytesToBigInt(v), r, s);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: PK recovery failed`);
}
return {
executionGasUsed: gasUsed,
returnValue: new Uint8Array(0)
};
}
const address = setLengthLeft(publicToAddress(publicKey), 32);
if (opts._debug !== void 0) {
opts._debug(`${pName} return address=${bytesToHex$1(address)}`);
}
return {
executionGasUsed: gasUsed,
returnValue: address
};
}
function precompile02(opts) {
const pName = getPrecompileName("02");
const data = opts.data;
const sha256Function = opts.common.customCrypto.sha256 ?? sha256;
let gasUsed = opts.common.param("sha256Gas");
gasUsed += opts.common.param("sha256WordGas") * BigInt(Math.ceil(data.length / 32));
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
const hash2 = sha256Function(data);
if (opts._debug !== void 0) {
opts._debug(`${pName} return hash=${bytesToHex$1(hash2)}`);
}
return {
executionGasUsed: gasUsed,
returnValue: hash2
};
}
const Rho = /* @__PURE__ */ new Uint8Array([7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8]);
const Id = /* @__PURE__ */ new Uint8Array(new Array(16).fill(0).map((_, i) => i));
const Pi = /* @__PURE__ */ Id.map((i) => (9 * i + 5) % 16);
let idxL = [Id];
let idxR = [Pi];
for (let i = 0; i < 4; i++)
for (let j of [idxL, idxR])
j.push(j[i].map((k) => Rho[k]));
const shifts = /* @__PURE__ */ [
[11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
[12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
[13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
[14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
[15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5]
].map((i) => new Uint8Array(i));
const shiftsL = /* @__PURE__ */ idxL.map((idx, i) => idx.map((j) => shifts[i][j]));
const shiftsR = /* @__PURE__ */ idxR.map((idx, i) => idx.map((j) => shifts[i][j]));
const Kl = /* @__PURE__ */ new Uint32Array([
0,
1518500249,
1859775393,
2400959708,
2840853838
]);
const Kr = /* @__PURE__ */ new Uint32Array([
1352829926,
1548603684,
1836072691,
2053994217,
0
]);
function f(group, x, y, z) {
if (group === 0)
return x ^ y ^ z;
else if (group === 1)
return x & y | ~x & z;
else if (group === 2)
return (x | ~y) ^ z;
else if (group === 3)
return x & z | y & ~z;
else
return x ^ (y | ~z);
}
const R_BUF = /* @__PURE__ */ new Uint32Array(16);
class RIPEMD160 extends HashMD {
constructor() {
super(64, 20, 8, true);
this.h0 = 1732584193 | 0;
this.h1 = 4023233417 | 0;
this.h2 = 2562383102 | 0;
this.h3 = 271733878 | 0;
this.h4 = 3285377520 | 0;
}
get() {
const { h0, h1, h2, h3, h4 } = this;
return [h0, h1, h2, h3, h4];
}
set(h0, h1, h2, h3, h4) {
this.h0 = h0 | 0;
this.h1 = h1 | 0;
this.h2 = h2 | 0;
this.h3 = h3 | 0;
this.h4 = h4 | 0;
}
process(view, offset) {
for (let i = 0; i < 16; i++, offset += 4)
R_BUF[i] = view.getUint32(offset, true);
let al = this.h0 | 0, ar = al, bl = this.h1 | 0, br = bl, cl = this.h2 | 0, cr = cl, dl = this.h3 | 0, dr = dl, el = this.h4 | 0, er = el;
for (let group = 0; group < 5; group++) {
const rGroup = 4 - group;
const hbl = Kl[group], hbr = Kr[group];
const rl = idxL[group], rr = idxR[group];
const sl = shiftsL[group], sr = shiftsR[group];
for (let i = 0; i < 16; i++) {
const tl = rotl(al + f(group, bl, cl, dl) + R_BUF[rl[i]] + hbl, sl[i]) + el | 0;
al = el, el = dl, dl = rotl(cl, 10) | 0, cl = bl, bl = tl;
}
for (let i = 0; i < 16; i++) {
const tr = rotl(ar + f(rGroup, br, cr, dr) + R_BUF[rr[i]] + hbr, sr[i]) + er | 0;
ar = er, er = dr, dr = rotl(cr, 10) | 0, cr = br, br = tr;
}
}
this.set(this.h1 + cl + dr | 0, this.h2 + dl + er | 0, this.h3 + el + ar | 0, this.h4 + al + br | 0, this.h0 + bl + cr | 0);
}
roundClean() {
R_BUF.fill(0);
}
destroy() {
this.destroyed = true;
this.buffer.fill(0);
this.set(0, 0, 0, 0, 0);
}
}
const ripemd160$1 = /* @__PURE__ */ wrapConstructor(() => new RIPEMD160());
const ripemd160 = wrapHash(ripemd160$1);
function precompile03(opts) {
const pName = getPrecompileName("03");
const data = opts.data;
let gasUsed = opts.common.param("ripemd160Gas");
gasUsed += opts.common.param("ripemd160WordGas") * BigInt(Math.ceil(data.length / 32));
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
const hash2 = setLengthLeft(ripemd160(data), 32);
if (opts._debug !== void 0) {
opts._debug(`${pName} return hash=${bytesToHex$1(hash2)}`);
}
return {
executionGasUsed: gasUsed,
returnValue: setLengthLeft(ripemd160(data), 32)
};
}
function precompile04(opts) {
const pName = getPrecompileName("04");
const data = opts.data;
let gasUsed = opts.common.param("identityGas");
gasUsed += opts.common.param("identityWordGas") * BigInt(Math.ceil(data.length / 32));
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return data=${short(opts.data)}`);
}
return {
executionGasUsed: gasUsed,
returnValue: Uint8Array.from(data)
// Copy the memory (`Uint8Array.from()`)
};
}
const BIGINT_4 = BigInt(4);
const BIGINT_16 = BigInt(16);
const BIGINT_200 = BigInt(200);
const BIGINT_480 = BigInt(480);
const BIGINT_1024 = BigInt(1024);
const BIGINT_3072 = BigInt(3072);
const BIGINT_199680 = BigInt(199680);
const maxInt = BigInt(Number.MAX_SAFE_INTEGER);
const maxSize = BigInt(2147483647);
function multiplicationComplexity(x) {
let fac1;
let fac2;
if (x <= BIGINT_64) {
return x ** BIGINT_2;
} else if (x <= BIGINT_1024) {
fac1 = x ** BIGINT_2 / BIGINT_4;
fac2 = x * BIGINT_96;
return fac1 + fac2 - BIGINT_3072;
} else {
fac1 = x ** BIGINT_2 / BIGINT_16;
fac2 = x * BIGINT_480;
return fac1 + fac2 - BIGINT_199680;
}
}
function multiplicationComplexityEIP2565(x) {
const words = (x + BIGINT_7) / BIGINT_8;
return words * words;
}
function getAdjustedExponentLength(data) {
let expBytesStart;
try {
const baseLen = bytesToBigInt(data.subarray(0, 32));
expBytesStart = 96 + Number(baseLen);
} catch (e) {
expBytesStart = Number.MAX_SAFE_INTEGER - 32;
}
const expLen = bytesToBigInt(data.subarray(32, 64));
let firstExpBytes = data.subarray(expBytesStart, expBytesStart + 32);
firstExpBytes = setLengthRight(firstExpBytes, 32);
let firstExpBigInt = bytesToBigInt(firstExpBytes);
let max32expLen = 0;
if (expLen < BIGINT_32) {
max32expLen = 32 - Number(expLen);
}
firstExpBigInt = firstExpBigInt >> BIGINT_8 * BigInt(Math.max(max32expLen, 0));
let bitLen2 = -1;
while (firstExpBigInt > BIGINT_0) {
bitLen2 = bitLen2 + 1;
firstExpBigInt = firstExpBigInt >> BIGINT_1;
}
let expLenMinus32OrZero = expLen - BIGINT_32;
if (expLenMinus32OrZero < BIGINT_0) {
expLenMinus32OrZero = BIGINT_0;
}
const eightTimesExpLenMinus32OrZero = expLenMinus32OrZero * BIGINT_8;
let adjustedExpLen = eightTimesExpLenMinus32OrZero;
if (bitLen2 > 0) {
adjustedExpLen += BigInt(bitLen2);
}
return adjustedExpLen;
}
function expMod(a, power, modulo) {
if (power === BIGINT_0) {
return BIGINT_1 % modulo;
}
let res = BIGINT_1;
while (power > BIGINT_0) {
if (power & BIGINT_1) res = res * a % modulo;
a = a * a % modulo;
power >>= BIGINT_1;
}
return res;
}
function precompile05(opts) {
const pName = getPrecompileName("05");
const data = opts.data.length < 96 ? setLengthRight(opts.data, 96) : opts.data;
let adjustedELen = getAdjustedExponentLength(data);
if (adjustedELen < BIGINT_1) {
adjustedELen = BIGINT_1;
}
const bLen = bytesToBigInt(data.subarray(0, 32));
const eLen = bytesToBigInt(data.subarray(32, 64));
const mLen = bytesToBigInt(data.subarray(64, 96));
let maxLen = bLen;
if (maxLen < mLen) {
maxLen = mLen;
}
const Gquaddivisor = opts.common.param("modexpGquaddivisorGas");
let gasUsed;
const bStart = BIGINT_96;
const bEnd = bStart + bLen;
const eStart = bEnd;
const eEnd = eStart + eLen;
const mStart = eEnd;
const mEnd = mStart + mLen;
if (!opts.common.isActivatedEIP(2565)) {
gasUsed = adjustedELen * multiplicationComplexity(maxLen) / Gquaddivisor;
} else {
gasUsed = adjustedELen * multiplicationComplexityEIP2565(maxLen) / Gquaddivisor;
if (gasUsed < BIGINT_200) {
gasUsed = BIGINT_200;
}
}
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
if (bLen === BIGINT_0 && mLen === BIGINT_0) {
return {
executionGasUsed: gasUsed,
returnValue: new Uint8Array()
};
}
if (bLen > maxSize || eLen > maxSize || mLen > maxSize) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: OOG`);
}
return OOGResult(opts.gasLimit);
}
if (mEnd > maxInt) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: OOG`);
}
return OOGResult(opts.gasLimit);
}
const B = bytesToBigInt(setLengthRight(data.subarray(Number(bStart), Number(bEnd)), Number(bLen)));
const E = bytesToBigInt(setLengthRight(data.subarray(Number(eStart), Number(eEnd)), Number(eLen)));
const M = bytesToBigInt(setLengthRight(data.subarray(Number(mStart), Number(mEnd)), Number(mLen)));
let R2;
if (M === BIGINT_0) {
R2 = new Uint8Array();
} else {
R2 = expMod(B, E, M);
if (R2 === BIGINT_0) {
R2 = new Uint8Array();
} else {
R2 = bigIntToBytes(R2);
}
}
const res = setLengthLeft(R2, Number(mLen));
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(res)}`);
}
return {
executionGasUsed: gasUsed,
returnValue: res
};
}
function precompile06(opts) {
const pName = getPrecompileName("06");
const gasUsed = opts.common.param("bn254AddGas");
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
const input = setLengthRight(opts.data.subarray(0, 128), 128);
let returnData;
try {
returnData = opts._EVM["_bn254"].add(input);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: ${e.message}`);
}
return EvmErrorResult(e, opts.gasLimit);
}
if (returnData.length !== 64) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: OOG`);
}
return OOGResult(opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnData)}`);
}
return {
executionGasUsed: gasUsed,
returnValue: returnData
};
}
function precompile07(opts) {
const pName = getPrecompileName("07");
const gasUsed = opts.common.param("bn254MulGas");
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
const input = setLengthRight(opts.data.subarray(0, 128), 128);
let returnData;
try {
returnData = opts._EVM["_bn254"].mul(input);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: ${e.message}`);
}
return EvmErrorResult(e, opts.gasLimit);
}
if (returnData.length !== 64) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: OOG`);
}
return OOGResult(opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnData)}`);
}
return {
executionGasUsed: gasUsed,
returnValue: returnData
};
}
function precompile08(opts) {
const pName = getPrecompileName("08");
if (!moduloLengthCheck(opts, 192, pName)) {
return EvmErrorResult(new EvmError(ERROR.INVALID_INPUT_LENGTH), opts.gasLimit);
}
const inputDataSize = BigInt(Math.floor(opts.data.length / 192));
const gasUsed = opts.common.param("bn254PairingGas") + inputDataSize * opts.common.param("bn254PairingWordGas");
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
let returnData;
try {
returnData = opts._EVM["_bn254"].pairing(opts.data);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: ${e.message}`);
}
return EvmErrorResult(e, opts.gasLimit);
}
if (returnData.length !== 32) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: OOG`);
}
return OOGResult(opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnData)}`);
}
return {
executionGasUsed: gasUsed,
returnValue: returnData
};
}
function ADD64AA(v, a, b) {
const o0 = v[a] + v[b];
let o1 = v[a + 1] + v[b + 1];
if (o0 >= 4294967296) {
o1++;
}
v[a] = o0;
v[a + 1] = o1;
}
function ADD64AC(v, a, b0, b1) {
let o0 = v[a] + b0;
if (b0 < 0) {
o0 += 4294967296;
}
let o1 = v[a + 1] + b1;
if (o0 >= 4294967296) {
o1++;
}
v[a] = o0;
v[a + 1] = o1;
}
function B2B_G(v, mw, a, b, c, d, ix, iy) {
const x0 = mw[ix];
const x1 = mw[ix + 1];
const y0 = mw[iy];
const y1 = mw[iy + 1];
ADD64AA(v, a, b);
ADD64AC(v, a, x0, x1);
let xor0 = v[d] ^ v[a];
let xor1 = v[d + 1] ^ v[a + 1];
v[d] = xor1;
v[d + 1] = xor0;
ADD64AA(v, c, d);
xor0 = v[b] ^ v[c];
xor1 = v[b + 1] ^ v[c + 1];
v[b] = xor0 >>> 24 ^ xor1 << 8;
v[b + 1] = xor1 >>> 24 ^ xor0 << 8;
ADD64AA(v, a, b);
ADD64AC(v, a, y0, y1);
xor0 = v[d] ^ v[a];
xor1 = v[d + 1] ^ v[a + 1];
v[d] = xor0 >>> 16 ^ xor1 << 16;
v[d + 1] = xor1 >>> 16 ^ xor0 << 16;
ADD64AA(v, c, d);
xor0 = v[b] ^ v[c];
xor1 = v[b + 1] ^ v[c + 1];
v[b] = xor1 >>> 31 ^ xor0 << 1;
v[b + 1] = xor0 >>> 31 ^ xor1 << 1;
}
const BLAKE2B_IV32 = new Uint32Array([4089235720, 1779033703, 2227873595, 3144134277, 4271175723, 1013904242, 1595750129, 2773480762, 2917565137, 1359893119, 725511199, 2600822924, 4215389547, 528734635, 327033209, 1541459225]);
const SIGMA8 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3];
const SIGMA82 = new Uint8Array(
SIGMA8.map(function(x) {
return x * 2;
})
);
function F(h, m, t, f2, rounds) {
const v = new Uint32Array(32);
let i = 0;
for (i = 0; i < 16; i++) {
v[i] = h[i];
v[i + 16] = BLAKE2B_IV32[i];
}
v[24] = v[24] ^ t[0];
v[25] = v[25] ^ t[1];
v[26] = v[26] ^ t[2];
v[27] = v[27] ^ t[3];
if (f2) {
v[28] = ~v[28];
v[29] = ~v[29];
}
for (i = 0; i < rounds; i++) {
const ri = i % 10 * 16;
B2B_G(v, m, 0, 8, 16, 24, SIGMA82[ri + 0], SIGMA82[ri + 1]);
B2B_G(v, m, 2, 10, 18, 26, SIGMA82[ri + 2], SIGMA82[ri + 3]);
B2B_G(v, m, 4, 12, 20, 28, SIGMA82[ri + 4], SIGMA82[ri + 5]);
B2B_G(v, m, 6, 14, 22, 30, SIGMA82[ri + 6], SIGMA82[ri + 7]);
B2B_G(v, m, 0, 10, 20, 30, SIGMA82[ri + 8], SIGMA82[ri + 9]);
B2B_G(v, m, 2, 12, 22, 24, SIGMA82[ri + 10], SIGMA82[ri + 11]);
B2B_G(v, m, 4, 14, 16, 26, SIGMA82[ri + 12], SIGMA82[ri + 13]);
B2B_G(v, m, 6, 8, 18, 28, SIGMA82[ri + 14], SIGMA82[ri + 15]);
}
for (i = 0; i < 16; i++) {
h[i] = h[i] ^ v[i] ^ v[i + 16];
}
}
function precompile09(opts) {
const pName = getPrecompileName("09");
const data = opts.data;
if (data.length !== 213) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: OUT_OF_RANGE dataLength=${data.length}`);
}
return {
returnValue: new Uint8Array(0),
executionGasUsed: opts.gasLimit,
exceptionError: new EvmError(ERROR.OUT_OF_RANGE)
};
}
const lastByte = data.subarray(212, 213)[0];
if (lastByte !== 1 && lastByte !== 0) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: OUT_OF_RANGE lastByte=${lastByte}`);
}
return {
returnValue: new Uint8Array(0),
executionGasUsed: opts.gasLimit,
exceptionError: new EvmError(ERROR.OUT_OF_RANGE)
};
}
const rounds = new DataView(data.buffer, data.byteOffset).getUint32(0);
const hRaw = new DataView(data.buffer, data.byteOffset + 4, 64);
const mRaw = new DataView(data.buffer, data.byteOffset + 68, 128);
const tRaw = new DataView(data.buffer, data.byteOffset + 196, 16);
const f2 = lastByte === 1;
let gasUsed = opts.common.param("blake2RoundGas");
gasUsed *= BigInt(rounds);
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
const h = new Uint32Array(16);
for (let i = 0; i < 16; i++) {
h[i] = hRaw.getUint32(i * 4, true);
}
const m = new Uint32Array(32);
for (let i = 0; i < 32; i++) {
m[i] = mRaw.getUint32(i * 4, true);
}
const t = new Uint32Array(4);
for (let i = 0; i < 4; i++) {
t[i] = tRaw.getUint32(i * 4, true);
}
F(h, m, t, f2, rounds);
const output2 = new Uint8Array(64);
const outputView = new DataView(output2.buffer);
for (let i = 0; i < 16; i++) {
outputView.setUint32(i * 4, h[i], true);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return hash=${bytesToHex$1(output2)}`);
}
return {
executionGasUsed: gasUsed,
returnValue: output2
};
}
const BLS_MODULUS = BigInt(
"52435875175126190479447740508185965837690552500527637822603658699938581184513"
);
const modulusBuffer = setLengthLeft(bigIntToBytes(BLS_MODULUS), 32);
async function precompile0a(opts) {
var _a, _b, _c;
const pName = getPrecompileName("0a");
if (((_a = opts.common.customCrypto) == null ? void 0 : _a.kzg) === void 0) {
throw new Error("kzg not initialized");
}
const gasUsed = opts.common.param("kzgPointEvaluationPrecompileGas");
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
if (opts.data.length !== 192) {
return EvmErrorResult(new EvmError(ERROR.INVALID_INPUT_LENGTH), opts.gasLimit);
}
const version = Number(opts.common.param("blobCommitmentVersionKzg"));
const fieldElementsPerBlob = opts.common.param("fieldElementsPerBlob");
const versionedHash = opts.data.subarray(0, 32);
const z = opts.data.subarray(32, 64);
const y = opts.data.subarray(64, 96);
const commitment = opts.data.subarray(96, 144);
const kzgProof = opts.data.subarray(144, 192);
if (bytesToHex$1(computeVersionedHash(commitment, version)) !== bytesToHex$1(versionedHash)) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: INVALID_COMMITMENT`);
}
return EvmErrorResult(new EvmError(ERROR.INVALID_COMMITMENT), opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(
`${pName}: proof verification with commitment=${bytesToHex$1(
commitment
)} z=${bytesToHex$1(z)} y=${bytesToHex$1(y)} kzgProof=${bytesToHex$1(kzgProof)}`
);
}
try {
const res = (_c = (_b = opts.common.customCrypto) == null ? void 0 : _b.kzg) == null ? void 0 : _c.verifyKzgProof(commitment, z, y, kzgProof);
if (res === false) {
return EvmErrorResult(new EvmError(ERROR.INVALID_PROOF), opts.gasLimit);
}
} catch (err) {
if (err.message.includes("C_KZG_BADARGS") === true) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: INVALID_INPUTS`);
}
return EvmErrorResult(new EvmError(ERROR.INVALID_INPUTS), opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: Unknown error - ${err.message}`);
}
return EvmErrorResult(new EvmError(ERROR.REVERT), opts.gasLimit);
}
const fieldElementsBuffer = setLengthLeft(bigIntToBytes(fieldElementsPerBlob), 32);
if (opts._debug !== void 0) {
opts._debug(
`${pName} return fieldElements=${bytesToHex$1(
fieldElementsBuffer
)} modulus=${bytesToHex$1(modulusBuffer)}`
);
}
return {
executionGasUsed: gasUsed,
returnValue: concatBytes$1(fieldElementsBuffer, modulusBuffer)
};
}
const BLS_FIELD_MODULUS = BigInt(
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"
);
const BLS_G1_POINT_BYTE_LENGTH = 128;
const BLS_G2_POINT_BYTE_LENGTH = 256;
const BLS_G1_INFINITY_POINT_BYTES = new Uint8Array(BLS_G1_POINT_BYTE_LENGTH);
const BLS_G2_INFINITY_POINT_BYTES = new Uint8Array(BLS_G2_POINT_BYTE_LENGTH);
const BLS_ZERO_BUFFER = new Uint8Array(32);
const BLS_ONE_BUFFER = concatBytes$1(new Uint8Array(31), hexToBytes$1("0x01"));
const BLS_GAS_DISCOUNT_PAIRS = [
[1, 1200],
[2, 888],
[3, 764],
[4, 641],
[5, 594],
[6, 547],
[7, 500],
[8, 453],
[9, 438],
[10, 423],
[11, 408],
[12, 394],
[13, 379],
[14, 364],
[15, 349],
[16, 334],
[17, 330],
[18, 326],
[19, 322],
[20, 318],
[21, 314],
[22, 310],
[23, 306],
[24, 302],
[25, 298],
[26, 294],
[27, 289],
[28, 285],
[29, 281],
[30, 277],
[31, 273],
[32, 269],
[33, 268],
[34, 266],
[35, 265],
[36, 263],
[37, 262],
[38, 260],
[39, 259],
[40, 257],
[41, 256],
[42, 254],
[43, 253],
[44, 251],
[45, 250],
[46, 248],
[47, 247],
[48, 245],
[49, 244],
[50, 242],
[51, 241],
[52, 239],
[53, 238],
[54, 236],
[55, 235],
[56, 233],
[57, 232],
[58, 231],
[59, 229],
[60, 228],
[61, 226],
[62, 225],
[63, 223],
[64, 222],
[65, 221],
[66, 220],
[67, 219],
[68, 219],
[69, 218],
[70, 217],
[71, 216],
[72, 216],
[73, 215],
[74, 214],
[75, 213],
[76, 213],
[77, 212],
[78, 211],
[79, 211],
[80, 210],
[81, 209],
[82, 208],
[83, 208],
[84, 207],
[85, 206],
[86, 205],
[87, 205],
[88, 204],
[89, 203],
[90, 202],
[91, 202],
[92, 201],
[93, 200],
[94, 199],
[95, 199],
[96, 198],
[97, 197],
[98, 196],
[99, 196],
[100, 195],
[101, 194],
[102, 193],
[103, 193],
[104, 192],
[105, 191],
[106, 191],
[107, 190],
[108, 189],
[109, 188],
[110, 188],
[111, 187],
[112, 186],
[113, 185],
[114, 185],
[115, 184],
[116, 183],
[117, 182],
[118, 182],
[119, 181],
[120, 180],
[121, 179],
[122, 179],
[123, 178],
[124, 177],
[125, 176],
[126, 176],
[127, 175],
[128, 174]
];
function BLS12_381_ToG1Point$1(input, mcl, verifyOrder = true) {
if (equalsBytes(input, BLS_G1_INFINITY_POINT_BYTES)) {
return new mcl.G1();
}
const p_x = bytesToUnprefixedHex(input.subarray(16, BLS_G1_POINT_BYTE_LENGTH / 2));
const p_y = bytesToUnprefixedHex(input.subarray(80, BLS_G1_POINT_BYTE_LENGTH));
const G1 = new mcl.G1();
const Fp_X = new mcl.Fp();
const Fp_Y = new mcl.Fp();
const One = new mcl.Fp();
Fp_X.setStr(p_x, 16);
Fp_Y.setStr(p_y, 16);
One.setStr("1", 16);
G1.setX(Fp_X);
G1.setY(Fp_Y);
G1.setZ(One);
mcl.verifyOrderG1(verifyOrder);
if (verifyOrder && G1.isValidOrder() === false) {
throw new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE);
}
if (G1.isValid() === false) {
throw new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE);
}
return G1;
}
function BLS12_381_FromG1Point$1(input) {
const decodeStr = input.getStr(16);
const decoded = decodeStr.match(/"?[0-9a-f]+"?/g);
if (decodeStr === "0") {
return new Uint8Array(BLS_G1_POINT_BYTE_LENGTH);
}
const xBytes = setLengthLeft(unprefixedHexToBytes(decoded[1]), 64);
const yBytes = setLengthLeft(unprefixedHexToBytes(decoded[2]), 64);
return concatBytes$1(xBytes, yBytes);
}
function BLS12_381_ToG2Point$1(input, mcl, verifyOrder = true) {
if (equalsBytes(input, BLS_G2_INFINITY_POINT_BYTES)) {
return new mcl.G2();
}
const p_x_1 = input.subarray(0, 64);
const p_x_2 = input.subarray(64, BLS_G2_POINT_BYTE_LENGTH / 2);
const p_y_1 = input.subarray(128, 192);
const p_y_2 = input.subarray(192, BLS_G2_POINT_BYTE_LENGTH);
const Fp2X = BLS12_381_ToFp2Point$1(p_x_1, p_x_2, mcl);
const Fp2Y = BLS12_381_ToFp2Point$1(p_y_1, p_y_2, mcl);
const FpOne = new mcl.Fp();
FpOne.setStr("1", 16);
const FpZero = new mcl.Fp();
FpZero.setStr("0", 16);
const Fp2One = new mcl.Fp2();
Fp2One.set_a(FpOne);
Fp2One.set_b(FpZero);
const p = new mcl.G2();
p.setX(Fp2X);
p.setY(Fp2Y);
p.setZ(Fp2One);
mcl.verifyOrderG2(verifyOrder);
if (verifyOrder && p.isValidOrder() === false) {
throw new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE);
}
if (p.isValid() === false) {
throw new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE);
}
return p;
}
function BLS12_381_FromG2Point$1(input) {
const decodeStr = input.getStr(16);
if (decodeStr === "0") {
return new Uint8Array(BLS_G2_POINT_BYTE_LENGTH);
}
const decoded = decodeStr.match(/"?[0-9a-f]+"?/g);
const xBytes1 = setLengthLeft(unprefixedHexToBytes(decoded[1]), 64);
const xBytes2 = setLengthLeft(unprefixedHexToBytes(decoded[2]), 64);
const yBytes1 = setLengthLeft(unprefixedHexToBytes(decoded[3]), 64);
const yBytes2 = setLengthLeft(unprefixedHexToBytes(decoded[4]), 64);
return concatBytes$1(xBytes1, xBytes2, yBytes1, yBytes2);
}
function BLS12_381_ToFrPoint$1(input, mcl) {
const mclHex = mcl.fromHexStr(bytesToUnprefixedHex(input));
const Fr2 = new mcl.Fr();
Fr2.setBigEndianMod(mclHex);
return Fr2;
}
function BLS12_381_ToFpPoint$1(fpCoordinate, mcl) {
if (bytesToBigInt(fpCoordinate) >= BLS_FIELD_MODULUS) {
throw new EvmError(ERROR.BLS_12_381_FP_NOT_IN_FIELD);
}
const fp = new mcl.Fp();
fp.setBigEndianMod(mcl.fromHexStr(bytesToUnprefixedHex(fpCoordinate)));
return fp;
}
function BLS12_381_ToFp2Point$1(fpXCoordinate, fpYCoordinate, mcl) {
if (bytesToBigInt(fpXCoordinate) >= BLS_FIELD_MODULUS) {
throw new EvmError(ERROR.BLS_12_381_FP_NOT_IN_FIELD);
}
if (bytesToBigInt(fpYCoordinate) >= BLS_FIELD_MODULUS) {
throw new EvmError(ERROR.BLS_12_381_FP_NOT_IN_FIELD);
}
const fp_x = new mcl.Fp();
const fp_y = new mcl.Fp();
const fp2 = new mcl.Fp2();
fp_x.setStr(bytesToUnprefixedHex(fpXCoordinate.subarray(16)), 16);
fp_y.setStr(bytesToUnprefixedHex(fpYCoordinate.subarray(16)), 16);
fp2.set_a(fp_x);
fp2.set_b(fp_y);
return fp2;
}
class MCLBLS {
constructor(mcl) {
this._mcl = mcl;
}
init() {
this._mcl.setMapToMode(this._mcl.IRTF);
this._mcl.verifyOrderG1(true);
this._mcl.verifyOrderG2(true);
}
addG1(input) {
const p1 = BLS12_381_ToG1Point$1(input.subarray(0, BLS_G1_POINT_BYTE_LENGTH), this._mcl, false);
const p2 = BLS12_381_ToG1Point$1(
input.subarray(BLS_G1_POINT_BYTE_LENGTH, BLS_G1_POINT_BYTE_LENGTH * 2),
this._mcl,
false
);
const result = this._mcl.add(p1, p2);
return BLS12_381_FromG1Point$1(result);
}
mulG1(input) {
const p = BLS12_381_ToG1Point$1(input.subarray(0, BLS_G1_POINT_BYTE_LENGTH), this._mcl);
const frPoint = BLS12_381_ToFrPoint$1(input.subarray(BLS_G1_POINT_BYTE_LENGTH, 160), this._mcl);
const result = this._mcl.mul(p, frPoint);
return BLS12_381_FromG1Point$1(result);
}
addG2(input) {
const p1 = BLS12_381_ToG2Point$1(input.subarray(0, BLS_G2_POINT_BYTE_LENGTH), this._mcl, false);
const p2 = BLS12_381_ToG2Point$1(
input.subarray(BLS_G2_POINT_BYTE_LENGTH, BLS_G2_POINT_BYTE_LENGTH * 2),
this._mcl,
false
);
const result = this._mcl.add(p1, p2);
return BLS12_381_FromG2Point$1(result);
}
mulG2(input) {
const p = BLS12_381_ToG2Point$1(input.subarray(0, BLS_G2_POINT_BYTE_LENGTH), this._mcl);
const frPoint = BLS12_381_ToFrPoint$1(input.subarray(BLS_G2_POINT_BYTE_LENGTH, 288), this._mcl);
const result = this._mcl.mul(p, frPoint);
return BLS12_381_FromG2Point$1(result);
}
mapFPtoG1(input) {
const Fp1Point = BLS12_381_ToFpPoint$1(input.subarray(0, 64), this._mcl);
const result = Fp1Point.mapToG1();
return BLS12_381_FromG1Point$1(result);
}
mapFP2toG2(input) {
const Fp2Point = BLS12_381_ToFp2Point$1(input.subarray(0, 64), input.subarray(64, 128), this._mcl);
const result = Fp2Point.mapToG2();
return BLS12_381_FromG2Point$1(result);
}
msmG1(input) {
const pairLength = 160;
const numPairs = input.length / pairLength;
const G1Array = [];
const FrArray = [];
for (let k = 0; k < numPairs; k++) {
const pairStart = pairLength * k;
const G1 = BLS12_381_ToG1Point$1(
input.subarray(pairStart, pairStart + BLS_G1_POINT_BYTE_LENGTH),
this._mcl
);
const Fr2 = BLS12_381_ToFrPoint$1(
input.subarray(pairStart + BLS_G1_POINT_BYTE_LENGTH, pairStart + pairLength),
this._mcl
);
G1Array.push(G1);
FrArray.push(Fr2);
}
const result = this._mcl.mulVec(G1Array, FrArray);
return BLS12_381_FromG1Point$1(result);
}
msmG2(input) {
const pairLength = 288;
const numPairs = input.length / pairLength;
const G2Array = [];
const FrArray = [];
for (let k = 0; k < numPairs; k++) {
const pairStart = pairLength * k;
const G2 = BLS12_381_ToG2Point$1(
input.subarray(pairStart, pairStart + BLS_G2_POINT_BYTE_LENGTH),
this._mcl
);
const Fr2 = BLS12_381_ToFrPoint$1(
input.subarray(pairStart + BLS_G2_POINT_BYTE_LENGTH, pairStart + pairLength),
this._mcl
);
G2Array.push(G2);
FrArray.push(Fr2);
}
const result = this._mcl.mulVec(G2Array, FrArray);
return BLS12_381_FromG2Point$1(result);
}
pairingCheck(input) {
const pairLength = 384;
const pairs = [];
for (let k = 0; k < input.length / pairLength; k++) {
const pairStart = pairLength * k;
const G1 = BLS12_381_ToG1Point$1(
input.subarray(pairStart, pairStart + BLS_G1_POINT_BYTE_LENGTH),
this._mcl
);
const g2start = pairStart + BLS_G1_POINT_BYTE_LENGTH;
const G2 = BLS12_381_ToG2Point$1(
input.subarray(g2start, g2start + BLS_G2_POINT_BYTE_LENGTH),
this._mcl
);
pairs.push([G1, G2]);
}
let GT;
for (let index = 0; index < pairs.length; index++) {
const pair = pairs[index];
const G1 = pair[0];
const G2 = pair[1];
if (index === 0) {
GT = this._mcl.millerLoop(G1, G2);
} else {
GT = this._mcl.mul(GT, this._mcl.millerLoop(G1, G2));
}
}
GT = this._mcl.finalExp(GT);
if (GT.isOne() === true) {
return BLS_ONE_BUFFER;
} else {
return BLS_ZERO_BUFFER;
}
}
}
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const _0n$2 = BigInt(0), _1n$3 = BigInt(1), _2n$3 = BigInt(2), _3n$3 = BigInt(3);
function NAfDecomposition(a) {
const res = [];
for (; a > _1n$3; a >>= _1n$3) {
if ((a & _1n$3) === _0n$2)
res.unshift(0);
else if ((a & _3n$3) === _3n$3) {
res.unshift(-1);
a += _1n$3;
} else
res.unshift(1);
}
return res;
}
function bls(CURVE) {
const { Fp: Fp3, Fr: Fr2, Fp2: Fp22, Fp6: Fp62, Fp12: Fp122 } = CURVE.fields;
const BLS_X_IS_NEGATIVE = CURVE.params.xNegative;
const TWIST = CURVE.params.twistType;
const G1_ = weierstrassPoints({ n: Fr2.ORDER, ...CURVE.G1 });
const G1 = Object.assign(G1_, createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, {
...CURVE.htfDefaults,
...CURVE.G1.htfDefaults
}));
const G2_ = weierstrassPoints({ n: Fr2.ORDER, ...CURVE.G2 });
const G2 = Object.assign(G2_, createHasher(G2_.ProjectivePoint, CURVE.G2.mapToCurve, {
...CURVE.htfDefaults,
...CURVE.G2.htfDefaults
}));
let lineFunction;
if (TWIST === "multiplicative") {
lineFunction = (c0, c1, c2, f2, Px, Py) => Fp122.mul014(f2, c0, Fp22.mul(c1, Px), Fp22.mul(c2, Py));
} else if (TWIST === "divisive") {
lineFunction = (c0, c1, c2, f2, Px, Py) => Fp122.mul034(f2, Fp22.mul(c2, Py), Fp22.mul(c1, Px), c0);
} else
throw new Error("bls: unknown twist type");
const Fp2div2 = Fp22.div(Fp22.ONE, Fp22.mul(Fp22.ONE, _2n$3));
function pointDouble(ell, Rx, Ry, Rz) {
const t0 = Fp22.sqr(Ry);
const t1 = Fp22.sqr(Rz);
const t2 = Fp22.mulByB(Fp22.mul(t1, _3n$3));
const t3 = Fp22.mul(t2, _3n$3);
const t4 = Fp22.sub(Fp22.sub(Fp22.sqr(Fp22.add(Ry, Rz)), t1), t0);
const c0 = Fp22.sub(t2, t0);
const c1 = Fp22.mul(Fp22.sqr(Rx), _3n$3);
const c2 = Fp22.neg(t4);
ell.push([c0, c1, c2]);
Rx = Fp22.mul(Fp22.mul(Fp22.mul(Fp22.sub(t0, t3), Rx), Ry), Fp2div2);
Ry = Fp22.sub(Fp22.sqr(Fp22.mul(Fp22.add(t0, t3), Fp2div2)), Fp22.mul(Fp22.sqr(t2), _3n$3));
Rz = Fp22.mul(t0, t4);
return { Rx, Ry, Rz };
}
function pointAdd(ell, Rx, Ry, Rz, Qx, Qy) {
const t0 = Fp22.sub(Ry, Fp22.mul(Qy, Rz));
const t1 = Fp22.sub(Rx, Fp22.mul(Qx, Rz));
const c0 = Fp22.sub(Fp22.mul(t0, Qx), Fp22.mul(t1, Qy));
const c1 = Fp22.neg(t0);
const c2 = t1;
ell.push([c0, c1, c2]);
const t2 = Fp22.sqr(t1);
const t3 = Fp22.mul(t2, t1);
const t4 = Fp22.mul(t2, Rx);
const t5 = Fp22.add(Fp22.sub(t3, Fp22.mul(t4, _2n$3)), Fp22.mul(Fp22.sqr(t0), Rz));
Rx = Fp22.mul(t1, t5);
Ry = Fp22.sub(Fp22.mul(Fp22.sub(t4, t5), t0), Fp22.mul(t3, Ry));
Rz = Fp22.mul(Rz, t3);
return { Rx, Ry, Rz };
}
const ATE_NAF = NAfDecomposition(CURVE.params.ateLoopSize);
const calcPairingPrecomputes = memoized((point) => {
const p = point;
const { x, y } = p.toAffine();
const Qx = x, Qy = y, negQy = Fp22.neg(y);
let Rx = Qx, Ry = Qy, Rz = Fp22.ONE;
const ell = [];
for (const bit of ATE_NAF) {
const cur = [];
({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz));
if (bit)
({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy));
ell.push(cur);
}
if (CURVE.postPrecompute) {
const last = ell[ell.length - 1];
CURVE.postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last));
}
return ell;
});
function millerLoopBatch(pairs, withFinalExponent = false) {
let f12 = Fp122.ONE;
if (pairs.length) {
const ellLen = pairs[0][0].length;
for (let i = 0; i < ellLen; i++) {
f12 = Fp122.sqr(f12);
for (const [ell, Px, Py] of pairs) {
for (const [c0, c1, c2] of ell[i])
f12 = lineFunction(c0, c1, c2, f12, Px, Py);
}
}
}
if (BLS_X_IS_NEGATIVE)
f12 = Fp122.conjugate(f12);
return withFinalExponent ? Fp122.finalExponentiate(f12) : f12;
}
function pairingBatch(pairs, withFinalExponent = true) {
const res = [];
G1.ProjectivePoint.normalizeZ(pairs.map(({ g1 }) => g1));
G2.ProjectivePoint.normalizeZ(pairs.map(({ g2 }) => g2));
for (const { g1, g2 } of pairs) {
if (g1.equals(G1.ProjectivePoint.ZERO) || g2.equals(G2.ProjectivePoint.ZERO))
throw new Error("pairing is not available for ZERO point");
g1.assertValidity();
g2.assertValidity();
const Qa = g1.toAffine();
res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]);
}
return millerLoopBatch(res, withFinalExponent);
}
function pairing(Q, P, withFinalExponent = true) {
return pairingBatch([{ g1: Q, g2: P }], withFinalExponent);
}
const utils = {
randomPrivateKey: () => {
const length = getMinHashLength(Fr2.ORDER);
return mapHashToField(CURVE.randomBytes(length), Fr2.ORDER);
},
calcPairingPrecomputes
};
const { ShortSignature } = CURVE.G1;
const { Signature } = CURVE.G2;
function normP1(point) {
return point instanceof G1.ProjectivePoint ? point : G1.ProjectivePoint.fromHex(point);
}
function normP1Hash(point, htfOpts) {
return point instanceof G1.ProjectivePoint ? point : G1.hashToCurve(ensureBytes("point", point), htfOpts);
}
function normP2(point) {
return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point);
}
function normP2Hash(point, htfOpts) {
return point instanceof G2.ProjectivePoint ? point : G2.hashToCurve(ensureBytes("point", point), htfOpts);
}
function getPublicKey(privateKey) {
return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true);
}
function getPublicKeyForShortSignatures(privateKey) {
return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true);
}
function sign(message, privateKey, htfOpts) {
const msgPoint = normP2Hash(message, htfOpts);
msgPoint.assertValidity();
const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey));
if (message instanceof G2.ProjectivePoint)
return sigPoint;
return Signature.toRawBytes(sigPoint);
}
function signShortSignature(message, privateKey, htfOpts) {
const msgPoint = normP1Hash(message, htfOpts);
msgPoint.assertValidity();
const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey));
if (message instanceof G1.ProjectivePoint)
return sigPoint;
return ShortSignature.toRawBytes(sigPoint);
}
function verify(signature, message, publicKey, htfOpts) {
const P = normP1(publicKey);
const Hm = normP2Hash(message, htfOpts);
const G = G1.ProjectivePoint.BASE;
const S = normP2(signature);
const exp = pairingBatch([
{ g1: P.negate(), g2: Hm },
// ePHM = pairing(P.negate(), Hm, false);
{ g1: G, g2: S }
// eGS = pairing(G, S, false);
]);
return Fp122.eql(exp, Fp122.ONE);
}
function verifyShortSignature(signature, message, publicKey, htfOpts) {
const P = normP2(publicKey);
const Hm = normP1Hash(message, htfOpts);
const G = G2.ProjectivePoint.BASE;
const S = normP1(signature);
const exp = pairingBatch([
{ g1: Hm, g2: P },
// eHmP = pairing(Hm, P, false);
{ g1: S, g2: G.negate() }
// eSG = pairing(S, G.negate(), false);
]);
return Fp122.eql(exp, Fp122.ONE);
}
function aggregatePublicKeys(publicKeys) {
if (!publicKeys.length)
throw new Error("Expected non-empty array");
const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO);
const aggAffine = agg;
if (publicKeys[0] instanceof G1.ProjectivePoint) {
aggAffine.assertValidity();
return aggAffine;
}
return aggAffine.toRawBytes(true);
}
function aggregateSignatures(signatures) {
if (!signatures.length)
throw new Error("Expected non-empty array");
const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO);
const aggAffine = agg;
if (signatures[0] instanceof G2.ProjectivePoint) {
aggAffine.assertValidity();
return aggAffine;
}
return Signature.toRawBytes(aggAffine);
}
function aggregateShortSignatures(signatures) {
if (!signatures.length)
throw new Error("Expected non-empty array");
const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO);
const aggAffine = agg;
if (signatures[0] instanceof G1.ProjectivePoint) {
aggAffine.assertValidity();
return aggAffine;
}
return ShortSignature.toRawBytes(aggAffine);
}
function verifyBatch(signature, messages, publicKeys, htfOpts) {
if (!messages.length)
throw new Error("Expected non-empty messages array");
if (publicKeys.length !== messages.length)
throw new Error("Pubkey count should equal msg count");
const sig = normP2(signature);
const nMessages = messages.map((i) => normP2Hash(i, htfOpts));
const nPublicKeys = publicKeys.map(normP1);
const messagePubKeyMap = /* @__PURE__ */ new Map();
for (let i = 0; i < nPublicKeys.length; i++) {
const pub = nPublicKeys[i];
const msg = nMessages[i];
let keys = messagePubKeyMap.get(msg);
if (keys === void 0) {
keys = [];
messagePubKeyMap.set(msg, keys);
}
keys.push(pub);
}
const paired = [];
try {
for (const [msg, keys] of messagePubKeyMap) {
const groupPublicKey = keys.reduce((acc, msg2) => acc.add(msg2));
paired.push({ g1: groupPublicKey, g2: msg });
}
paired.push({ g1: G1.ProjectivePoint.BASE.negate(), g2: sig });
return Fp122.eql(pairingBatch(paired), Fp122.ONE);
} catch {
return false;
}
}
G1.ProjectivePoint.BASE._setWindowSize(4);
return {
getPublicKey,
getPublicKeyForShortSignatures,
sign,
signShortSignature,
verify,
verifyBatch,
verifyShortSignature,
aggregatePublicKeys,
aggregateSignatures,
aggregateShortSignatures,
millerLoopBatch,
pairing,
pairingBatch,
G1,
G2,
Signature,
ShortSignature,
fields: {
Fr: Fr2,
Fp: Fp3,
Fp2: Fp22,
Fp6: Fp62,
Fp12: Fp122
},
params: {
ateLoopSize: CURVE.params.ateLoopSize,
r: CURVE.params.r,
G1b: CURVE.G1.b,
G2b: CURVE.G2.b
},
utils
};
}
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const _0n$1 = BigInt(0), _1n$2 = BigInt(1), _2n$2 = BigInt(2), _3n$2 = BigInt(3);
function calcFrobeniusCoefficients(Fp3, nonResidue, modulus, degree, num = 1, divisor) {
const _divisor = BigInt(divisor === void 0 ? degree : divisor);
const towerModulus = modulus ** BigInt(degree);
const res = [];
for (let i = 0; i < num; i++) {
const a = BigInt(i + 1);
const powers = [];
for (let j = 0, qPower = _1n$2; j < degree; j++) {
const power = (a * qPower - a) / _divisor % towerModulus;
powers.push(Fp3.pow(nonResidue, power));
qPower *= modulus;
}
res.push(powers);
}
return res;
}
function psiFrobenius(Fp3, Fp22, base) {
const PSI_X = Fp22.pow(base, (Fp3.ORDER - _1n$2) / _3n$2);
const PSI_Y = Fp22.pow(base, (Fp3.ORDER - _1n$2) / _2n$2);
function psi2(x, y) {
const x2 = Fp22.mul(Fp22.frobeniusMap(x, 1), PSI_X);
const y2 = Fp22.mul(Fp22.frobeniusMap(y, 1), PSI_Y);
return [x2, y2];
}
const PSI2_X = Fp22.pow(base, (Fp3.ORDER ** _2n$2 - _1n$2) / _3n$2);
const PSI2_Y = Fp22.pow(base, (Fp3.ORDER ** _2n$2 - _1n$2) / _2n$2);
if (!Fp22.eql(PSI2_Y, Fp22.neg(Fp22.ONE)))
throw new Error("psiFrobenius: PSI2_Y!==-1");
function psi22(x, y) {
return [Fp22.mul(x, PSI2_X), Fp22.neg(y)];
}
const mapAffine = (fn) => (c, P) => {
const affine = P.toAffine();
const p = fn(affine.x, affine.y);
return c.fromAffine({ x: p[0], y: p[1] });
};
const G2psi3 = mapAffine(psi2);
const G2psi22 = mapAffine(psi22);
return { psi: psi2, psi2: psi22, G2psi: G2psi3, G2psi2: G2psi22, PSI_X, PSI_Y, PSI2_X, PSI2_Y };
}
function tower12(opts) {
const { ORDER } = opts;
const Fp3 = Field(ORDER);
const FpNONRESIDUE = Fp3.create(opts.NONRESIDUE || BigInt(-1));
const FpLegendre$1 = FpLegendre(ORDER);
const Fpdiv2 = Fp3.div(Fp3.ONE, _2n$2);
const FP2_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp3, FpNONRESIDUE, Fp3.ORDER, 2)[0];
const Fp2Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
c0: Fp3.add(c0, r0),
c1: Fp3.add(c1, r1)
});
const Fp2Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
c0: Fp3.sub(c0, r0),
c1: Fp3.sub(c1, r1)
});
const Fp2Multiply = ({ c0, c1 }, rhs) => {
if (typeof rhs === "bigint")
return { c0: Fp3.mul(c0, rhs), c1: Fp3.mul(c1, rhs) };
const { c0: r0, c1: r1 } = rhs;
let t1 = Fp3.mul(c0, r0);
let t2 = Fp3.mul(c1, r1);
const o0 = Fp3.sub(t1, t2);
const o1 = Fp3.sub(Fp3.mul(Fp3.add(c0, c1), Fp3.add(r0, r1)), Fp3.add(t1, t2));
return { c0: o0, c1: o1 };
};
const Fp2Square = ({ c0, c1 }) => {
const a = Fp3.add(c0, c1);
const b = Fp3.sub(c0, c1);
const c = Fp3.add(c0, c0);
return { c0: Fp3.mul(a, b), c1: Fp3.mul(c, c1) };
};
const Fp2fromBigTuple = (tuple) => {
if (tuple.length !== 2)
throw new Error("Invalid tuple");
const fps = tuple.map((n) => Fp3.create(n));
return { c0: fps[0], c1: fps[1] };
};
const FP2_ORDER = ORDER * ORDER;
const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE);
const Fp22 = {
ORDER: FP2_ORDER,
NONRESIDUE: Fp2Nonresidue,
BITS: bitLen(FP2_ORDER),
BYTES: Math.ceil(bitLen(FP2_ORDER) / 8),
MASK: bitMask(bitLen(FP2_ORDER)),
ZERO: { c0: Fp3.ZERO, c1: Fp3.ZERO },
ONE: { c0: Fp3.ONE, c1: Fp3.ZERO },
create: (num) => num,
isValid: ({ c0, c1 }) => typeof c0 === "bigint" && typeof c1 === "bigint",
is0: ({ c0, c1 }) => Fp3.is0(c0) && Fp3.is0(c1),
eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp3.eql(c0, r0) && Fp3.eql(c1, r1),
neg: ({ c0, c1 }) => ({ c0: Fp3.neg(c0), c1: Fp3.neg(c1) }),
pow: (num, power) => FpPow(Fp22, num, power),
invertBatch: (nums) => FpInvertBatch(Fp22, nums),
// Normalized
add: Fp2Add,
sub: Fp2Subtract,
mul: Fp2Multiply,
sqr: Fp2Square,
// NonNormalized stuff
addN: Fp2Add,
subN: Fp2Subtract,
mulN: Fp2Multiply,
sqrN: Fp2Square,
// Why inversion for bigint inside Fp instead of Fp2? it is even used in that context?
div: (lhs, rhs) => Fp22.mul(lhs, typeof rhs === "bigint" ? Fp3.inv(Fp3.create(rhs)) : Fp22.inv(rhs)),
inv: ({ c0: a, c1: b }) => {
const factor = Fp3.inv(Fp3.create(a * a + b * b));
return { c0: Fp3.mul(factor, Fp3.create(a)), c1: Fp3.mul(factor, Fp3.create(-b)) };
},
sqrt: (num) => {
if (opts.Fp2sqrt)
return opts.Fp2sqrt(num);
const { c0, c1 } = num;
if (Fp3.is0(c1)) {
if (Fp3.eql(FpLegendre$1(Fp3, c0), Fp3.ONE))
return Fp22.create({ c0: Fp3.sqrt(c0), c1: Fp3.ZERO });
else
return Fp22.create({ c0: Fp3.ZERO, c1: Fp3.sqrt(Fp3.div(c0, FpNONRESIDUE)) });
}
const a = Fp3.sqrt(Fp3.sub(Fp3.sqr(c0), Fp3.mul(Fp3.sqr(c1), FpNONRESIDUE)));
let d = Fp3.mul(Fp3.add(a, c0), Fpdiv2);
const legendre = FpLegendre$1(Fp3, d);
if (!Fp3.is0(legendre) && !Fp3.eql(legendre, Fp3.ONE))
d = Fp3.sub(d, a);
const a0 = Fp3.sqrt(d);
const candidateSqrt = Fp22.create({ c0: a0, c1: Fp3.div(Fp3.mul(c1, Fpdiv2), a0) });
if (!Fp22.eql(Fp22.sqr(candidateSqrt), num))
throw new Error("Cannot find square root");
const x1 = candidateSqrt;
const x2 = Fp22.neg(x1);
const { re: re1, im: im1 } = Fp22.reim(x1);
const { re: re2, im: im2 } = Fp22.reim(x2);
if (im1 > im2 || im1 === im2 && re1 > re2)
return x1;
return x2;
},
// Same as sgn0_m_eq_2 in RFC 9380
isOdd: (x) => {
const { re: x0, im: x1 } = Fp22.reim(x);
const sign_0 = x0 % _2n$2;
const zero_0 = x0 === _0n$1;
const sign_1 = x1 % _2n$2;
return BigInt(sign_0 || zero_0 && sign_1) == _1n$2;
},
// Bytes util
fromBytes(b) {
if (b.length !== Fp22.BYTES)
throw new Error(`fromBytes wrong length=${b.length}`);
return { c0: Fp3.fromBytes(b.subarray(0, Fp3.BYTES)), c1: Fp3.fromBytes(b.subarray(Fp3.BYTES)) };
},
toBytes: ({ c0, c1 }) => concatBytes$2(Fp3.toBytes(c0), Fp3.toBytes(c1)),
cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({
c0: Fp3.cmov(c0, r0, c),
c1: Fp3.cmov(c1, r1, c)
}),
reim: ({ c0, c1 }) => ({ re: c0, im: c1 }),
// multiply by u + 1
mulByNonresidue: ({ c0, c1 }) => Fp22.mul({ c0, c1 }, Fp2Nonresidue),
mulByB: opts.Fp2mulByB,
fromBigTuple: Fp2fromBigTuple,
frobeniusMap: ({ c0, c1 }, power) => ({
c0,
c1: Fp3.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2])
})
};
const Fp6Add = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({
c0: Fp22.add(c0, r0),
c1: Fp22.add(c1, r1),
c2: Fp22.add(c2, r2)
});
const Fp6Subtract = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({
c0: Fp22.sub(c0, r0),
c1: Fp22.sub(c1, r1),
c2: Fp22.sub(c2, r2)
});
const Fp6Multiply = ({ c0, c1, c2 }, rhs) => {
if (typeof rhs === "bigint") {
return {
c0: Fp22.mul(c0, rhs),
c1: Fp22.mul(c1, rhs),
c2: Fp22.mul(c2, rhs)
};
}
const { c0: r0, c1: r1, c2: r2 } = rhs;
const t0 = Fp22.mul(c0, r0);
const t1 = Fp22.mul(c1, r1);
const t2 = Fp22.mul(c2, r2);
return {
// t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1)
c0: Fp22.add(t0, Fp22.mulByNonresidue(Fp22.sub(Fp22.mul(Fp22.add(c1, c2), Fp22.add(r1, r2)), Fp22.add(t1, t2)))),
// (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1)
c1: Fp22.add(Fp22.sub(Fp22.mul(Fp22.add(c0, c1), Fp22.add(r0, r1)), Fp22.add(t0, t1)), Fp22.mulByNonresidue(t2)),
// T1 + (c0 + c2) * (r0 + r2) - T0 + T2
c2: Fp22.sub(Fp22.add(t1, Fp22.mul(Fp22.add(c0, c2), Fp22.add(r0, r2))), Fp22.add(t0, t2))
};
};
const Fp6Square = ({ c0, c1, c2 }) => {
let t0 = Fp22.sqr(c0);
let t1 = Fp22.mul(Fp22.mul(c0, c1), _2n$2);
let t3 = Fp22.mul(Fp22.mul(c1, c2), _2n$2);
let t4 = Fp22.sqr(c2);
return {
c0: Fp22.add(Fp22.mulByNonresidue(t3), t0),
// T3 * (u + 1) + T0
c1: Fp22.add(Fp22.mulByNonresidue(t4), t1),
// T4 * (u + 1) + T1
// T1 + (c0 - c1 + c2)² + T3 - T0 - T4
c2: Fp22.sub(Fp22.sub(Fp22.add(Fp22.add(t1, Fp22.sqr(Fp22.add(Fp22.sub(c0, c1), c2))), t3), t0), t4)
};
};
const [FP6_FROBENIUS_COEFFICIENTS_1, FP6_FROBENIUS_COEFFICIENTS_2] = calcFrobeniusCoefficients(Fp22, Fp2Nonresidue, Fp3.ORDER, 6, 2, 3);
const Fp62 = {
ORDER: Fp22.ORDER,
// TODO: unused, but need to verify
BITS: 3 * Fp22.BITS,
BYTES: 3 * Fp22.BYTES,
MASK: bitMask(3 * Fp22.BITS),
ZERO: { c0: Fp22.ZERO, c1: Fp22.ZERO, c2: Fp22.ZERO },
ONE: { c0: Fp22.ONE, c1: Fp22.ZERO, c2: Fp22.ZERO },
create: (num) => num,
isValid: ({ c0, c1, c2 }) => Fp22.isValid(c0) && Fp22.isValid(c1) && Fp22.isValid(c2),
is0: ({ c0, c1, c2 }) => Fp22.is0(c0) && Fp22.is0(c1) && Fp22.is0(c2),
neg: ({ c0, c1, c2 }) => ({ c0: Fp22.neg(c0), c1: Fp22.neg(c1), c2: Fp22.neg(c2) }),
eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => Fp22.eql(c0, r0) && Fp22.eql(c1, r1) && Fp22.eql(c2, r2),
sqrt: notImplemented,
// Do we need division by bigint at all? Should be done via order:
div: (lhs, rhs) => Fp62.mul(lhs, typeof rhs === "bigint" ? Fp3.inv(Fp3.create(rhs)) : Fp62.inv(rhs)),
pow: (num, power) => FpPow(Fp62, num, power),
invertBatch: (nums) => FpInvertBatch(Fp62, nums),
// Normalized
add: Fp6Add,
sub: Fp6Subtract,
mul: Fp6Multiply,
sqr: Fp6Square,
// NonNormalized stuff
addN: Fp6Add,
subN: Fp6Subtract,
mulN: Fp6Multiply,
sqrN: Fp6Square,
inv: ({ c0, c1, c2 }) => {
let t0 = Fp22.sub(Fp22.sqr(c0), Fp22.mulByNonresidue(Fp22.mul(c2, c1)));
let t1 = Fp22.sub(Fp22.mulByNonresidue(Fp22.sqr(c2)), Fp22.mul(c0, c1));
let t2 = Fp22.sub(Fp22.sqr(c1), Fp22.mul(c0, c2));
let t4 = Fp22.inv(Fp22.add(Fp22.mulByNonresidue(Fp22.add(Fp22.mul(c2, t1), Fp22.mul(c1, t2))), Fp22.mul(c0, t0)));
return { c0: Fp22.mul(t4, t0), c1: Fp22.mul(t4, t1), c2: Fp22.mul(t4, t2) };
},
// Bytes utils
fromBytes: (b) => {
if (b.length !== Fp62.BYTES)
throw new Error(`fromBytes wrong length=${b.length}`);
return {
c0: Fp22.fromBytes(b.subarray(0, Fp22.BYTES)),
c1: Fp22.fromBytes(b.subarray(Fp22.BYTES, 2 * Fp22.BYTES)),
c2: Fp22.fromBytes(b.subarray(2 * Fp22.BYTES))
};
},
toBytes: ({ c0, c1, c2 }) => concatBytes$2(Fp22.toBytes(c0), Fp22.toBytes(c1), Fp22.toBytes(c2)),
cmov: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) => ({
c0: Fp22.cmov(c0, r0, c),
c1: Fp22.cmov(c1, r1, c),
c2: Fp22.cmov(c2, r2, c)
}),
fromBigSix: (t) => {
if (!Array.isArray(t) || t.length !== 6)
throw new Error("Invalid Fp6 usage");
return {
c0: Fp22.fromBigTuple(t.slice(0, 2)),
c1: Fp22.fromBigTuple(t.slice(2, 4)),
c2: Fp22.fromBigTuple(t.slice(4, 6))
};
},
frobeniusMap: ({ c0, c1, c2 }, power) => ({
c0: Fp22.frobeniusMap(c0, power),
c1: Fp22.mul(Fp22.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]),
c2: Fp22.mul(Fp22.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6])
}),
mulByFp2: ({ c0, c1, c2 }, rhs) => ({
c0: Fp22.mul(c0, rhs),
c1: Fp22.mul(c1, rhs),
c2: Fp22.mul(c2, rhs)
}),
mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp22.mulByNonresidue(c2), c1: c0, c2: c1 }),
// Sparse multiplication
mul1: ({ c0, c1, c2 }, b1) => ({
c0: Fp22.mulByNonresidue(Fp22.mul(c2, b1)),
c1: Fp22.mul(c0, b1),
c2: Fp22.mul(c1, b1)
}),
// Sparse multiplication
mul01({ c0, c1, c2 }, b0, b1) {
let t0 = Fp22.mul(c0, b0);
let t1 = Fp22.mul(c1, b1);
return {
// ((c1 + c2) * b1 - T1) * (u + 1) + T0
c0: Fp22.add(Fp22.mulByNonresidue(Fp22.sub(Fp22.mul(Fp22.add(c1, c2), b1), t1)), t0),
// (b0 + b1) * (c0 + c1) - T0 - T1
c1: Fp22.sub(Fp22.sub(Fp22.mul(Fp22.add(b0, b1), Fp22.add(c0, c1)), t0), t1),
// (c0 + c2) * b0 - T0 + T1
c2: Fp22.add(Fp22.sub(Fp22.mul(Fp22.add(c0, c2), b0), t0), t1)
};
}
};
const FP12_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp22, Fp2Nonresidue, Fp3.ORDER, 12, 1, 6)[0];
const Fp12Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
c0: Fp62.add(c0, r0),
c1: Fp62.add(c1, r1)
});
const Fp12Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({
c0: Fp62.sub(c0, r0),
c1: Fp62.sub(c1, r1)
});
const Fp12Multiply = ({ c0, c1 }, rhs) => {
if (typeof rhs === "bigint")
return { c0: Fp62.mul(c0, rhs), c1: Fp62.mul(c1, rhs) };
let { c0: r0, c1: r1 } = rhs;
let t1 = Fp62.mul(c0, r0);
let t2 = Fp62.mul(c1, r1);
return {
c0: Fp62.add(t1, Fp62.mulByNonresidue(t2)),
// T1 + T2 * v
// (c0 + c1) * (r0 + r1) - (T1 + T2)
c1: Fp62.sub(Fp62.mul(Fp62.add(c0, c1), Fp62.add(r0, r1)), Fp62.add(t1, t2))
};
};
const Fp12Square = ({ c0, c1 }) => {
let ab = Fp62.mul(c0, c1);
return {
// (c1 * v + c0) * (c0 + c1) - AB - AB * v
c0: Fp62.sub(Fp62.sub(Fp62.mul(Fp62.add(Fp62.mulByNonresidue(c1), c0), Fp62.add(c0, c1)), ab), Fp62.mulByNonresidue(ab)),
c1: Fp62.add(ab, ab)
};
};
function Fp4Square2(a, b) {
const a2 = Fp22.sqr(a);
const b2 = Fp22.sqr(b);
return {
first: Fp22.add(Fp22.mulByNonresidue(b2), a2),
// b² * Nonresidue + a²
second: Fp22.sub(Fp22.sub(Fp22.sqr(Fp22.add(a, b)), a2), b2)
// (a + b)² - a² - b²
};
}
const Fp122 = {
ORDER: Fp22.ORDER,
// TODO: unused, but need to verify
BITS: 2 * Fp22.BITS,
BYTES: 2 * Fp22.BYTES,
MASK: bitMask(2 * Fp22.BITS),
ZERO: { c0: Fp62.ZERO, c1: Fp62.ZERO },
ONE: { c0: Fp62.ONE, c1: Fp62.ZERO },
create: (num) => num,
isValid: ({ c0, c1 }) => Fp62.isValid(c0) && Fp62.isValid(c1),
is0: ({ c0, c1 }) => Fp62.is0(c0) && Fp62.is0(c1),
neg: ({ c0, c1 }) => ({ c0: Fp62.neg(c0), c1: Fp62.neg(c1) }),
eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp62.eql(c0, r0) && Fp62.eql(c1, r1),
sqrt: notImplemented,
inv: ({ c0, c1 }) => {
let t = Fp62.inv(Fp62.sub(Fp62.sqr(c0), Fp62.mulByNonresidue(Fp62.sqr(c1))));
return { c0: Fp62.mul(c0, t), c1: Fp62.neg(Fp62.mul(c1, t)) };
},
div: (lhs, rhs) => Fp122.mul(lhs, typeof rhs === "bigint" ? Fp3.inv(Fp3.create(rhs)) : Fp122.inv(rhs)),
pow: (num, power) => FpPow(Fp122, num, power),
invertBatch: (nums) => FpInvertBatch(Fp122, nums),
// Normalized
add: Fp12Add,
sub: Fp12Subtract,
mul: Fp12Multiply,
sqr: Fp12Square,
// NonNormalized stuff
addN: Fp12Add,
subN: Fp12Subtract,
mulN: Fp12Multiply,
sqrN: Fp12Square,
// Bytes utils
fromBytes: (b) => {
if (b.length !== Fp122.BYTES)
throw new Error(`fromBytes wrong length=${b.length}`);
return {
c0: Fp62.fromBytes(b.subarray(0, Fp62.BYTES)),
c1: Fp62.fromBytes(b.subarray(Fp62.BYTES))
};
},
toBytes: ({ c0, c1 }) => concatBytes$2(Fp62.toBytes(c0), Fp62.toBytes(c1)),
cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({
c0: Fp62.cmov(c0, r0, c),
c1: Fp62.cmov(c1, r1, c)
}),
// Utils
// toString() {
// return `Fp12(${this.c0} + ${this.c1} * w)`;
// },
// fromTuple(c: [Fp6, Fp6]) {
// return new Fp12(...c);
// }
fromBigTwelve: (t) => ({
c0: Fp62.fromBigSix(t.slice(0, 6)),
c1: Fp62.fromBigSix(t.slice(6, 12))
}),
// Raises to q**i -th power
frobeniusMap(lhs, power) {
const { c0, c1, c2 } = Fp62.frobeniusMap(lhs.c1, power);
const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12];
return {
c0: Fp62.frobeniusMap(lhs.c0, power),
c1: Fp62.create({
c0: Fp22.mul(c0, coeff),
c1: Fp22.mul(c1, coeff),
c2: Fp22.mul(c2, coeff)
})
};
},
mulByFp2: ({ c0, c1 }, rhs) => ({
c0: Fp62.mulByFp2(c0, rhs),
c1: Fp62.mulByFp2(c1, rhs)
}),
conjugate: ({ c0, c1 }) => ({ c0, c1: Fp62.neg(c1) }),
// Sparse multiplication
mul014: ({ c0, c1 }, o0, o1, o4) => {
let t0 = Fp62.mul01(c0, o0, o1);
let t1 = Fp62.mul1(c1, o4);
return {
c0: Fp62.add(Fp62.mulByNonresidue(t1), t0),
// T1 * v + T0
// (c1 + c0) * [o0, o1+o4] - T0 - T1
c1: Fp62.sub(Fp62.sub(Fp62.mul01(Fp62.add(c1, c0), o0, Fp22.add(o1, o4)), t0), t1)
};
},
mul034: ({ c0, c1 }, o0, o3, o4) => {
const a = Fp62.create({
c0: Fp22.mul(c0.c0, o0),
c1: Fp22.mul(c0.c1, o0),
c2: Fp22.mul(c0.c2, o0)
});
const b = Fp62.mul01(c1, o3, o4);
const e = Fp62.mul01(Fp62.add(c0, c1), Fp22.add(o0, o3), o4);
return {
c0: Fp62.add(Fp62.mulByNonresidue(b), a),
c1: Fp62.sub(e, Fp62.add(a, b))
};
},
// A cyclotomic group is a subgroup of Fp^n defined by
// GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1}
// The result of any pairing is in a cyclotomic subgroup
// https://eprint.iacr.org/2009/565.pdf
_cyclotomicSquare: opts.Fp12cyclotomicSquare,
_cyclotomicExp: opts.Fp12cyclotomicExp,
// https://eprint.iacr.org/2010/354.pdf
// https://eprint.iacr.org/2009/565.pdf
finalExponentiate: opts.Fp12finalExponentiate
};
return { Fp: Fp3, Fp2: Fp22, Fp6: Fp62, Fp4Square: Fp4Square2, Fp12: Fp122 };
}
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const _0n = BigInt(0), _1n$1 = BigInt(1), _2n$1 = BigInt(2), _3n$1 = BigInt(3), _4n = BigInt(4);
const BLS_X = BigInt("0xd201000000010000");
const BLS_X_LEN = bitLen(BLS_X);
const { Fp: Fp$1, Fp2: Fp2$1, Fp6: Fp6$1, Fp4Square: Fp4Square$1, Fp12: Fp12$1 } = tower12({
// Order of Fp
ORDER: BigInt("0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"),
// Finite extension field over irreducible polynominal.
// Fp(u) / (u² - β) where β = -1
FP2_NONRESIDUE: [_1n$1, _1n$1],
Fp2mulByB: ({ c0, c1 }) => {
const t0 = Fp$1.mul(c0, _4n);
const t1 = Fp$1.mul(c1, _4n);
return { c0: Fp$1.sub(t0, t1), c1: Fp$1.add(t0, t1) };
},
// Fp12
// A cyclotomic group is a subgroup of Fp^n defined by
// GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1}
// The result of any pairing is in a cyclotomic subgroup
// https://eprint.iacr.org/2009/565.pdf
Fp12cyclotomicSquare: ({ c0, c1 }) => {
const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0;
const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1;
const { first: t3, second: t4 } = Fp4Square$1(c0c0, c1c1);
const { first: t5, second: t6 } = Fp4Square$1(c1c0, c0c2);
const { first: t7, second: t8 } = Fp4Square$1(c0c1, c1c2);
const t9 = Fp2$1.mulByNonresidue(t8);
return {
c0: Fp6$1.create({
c0: Fp2$1.add(Fp2$1.mul(Fp2$1.sub(t3, c0c0), _2n$1), t3),
// 2 * (T3 - c0c0) + T3
c1: Fp2$1.add(Fp2$1.mul(Fp2$1.sub(t5, c0c1), _2n$1), t5),
// 2 * (T5 - c0c1) + T5
c2: Fp2$1.add(Fp2$1.mul(Fp2$1.sub(t7, c0c2), _2n$1), t7)
}),
// 2 * (T7 - c0c2) + T7
c1: Fp6$1.create({
c0: Fp2$1.add(Fp2$1.mul(Fp2$1.add(t9, c1c0), _2n$1), t9),
// 2 * (T9 + c1c0) + T9
c1: Fp2$1.add(Fp2$1.mul(Fp2$1.add(t4, c1c1), _2n$1), t4),
// 2 * (T4 + c1c1) + T4
c2: Fp2$1.add(Fp2$1.mul(Fp2$1.add(t6, c1c2), _2n$1), t6)
})
};
},
Fp12cyclotomicExp(num, n) {
let z = Fp12$1.ONE;
for (let i = BLS_X_LEN - 1; i >= 0; i--) {
z = Fp12$1._cyclotomicSquare(z);
if (bitGet(n, i))
z = Fp12$1.mul(z, num);
}
return z;
},
// https://eprint.iacr.org/2010/354.pdf
// https://eprint.iacr.org/2009/565.pdf
Fp12finalExponentiate: (num) => {
const x = BLS_X;
const t0 = Fp12$1.div(Fp12$1.frobeniusMap(num, 6), num);
const t1 = Fp12$1.mul(Fp12$1.frobeniusMap(t0, 2), t0);
const t2 = Fp12$1.conjugate(Fp12$1._cyclotomicExp(t1, x));
const t3 = Fp12$1.mul(Fp12$1.conjugate(Fp12$1._cyclotomicSquare(t1)), t2);
const t4 = Fp12$1.conjugate(Fp12$1._cyclotomicExp(t3, x));
const t5 = Fp12$1.conjugate(Fp12$1._cyclotomicExp(t4, x));
const t6 = Fp12$1.mul(Fp12$1.conjugate(Fp12$1._cyclotomicExp(t5, x)), Fp12$1._cyclotomicSquare(t2));
const t7 = Fp12$1.conjugate(Fp12$1._cyclotomicExp(t6, x));
const t2_t5_pow_q2 = Fp12$1.frobeniusMap(Fp12$1.mul(t2, t5), 2);
const t4_t1_pow_q3 = Fp12$1.frobeniusMap(Fp12$1.mul(t4, t1), 3);
const t6_t1c_pow_q1 = Fp12$1.frobeniusMap(Fp12$1.mul(t6, Fp12$1.conjugate(t1)), 1);
const t7_t3c_t1 = Fp12$1.mul(Fp12$1.mul(t7, Fp12$1.conjugate(t3)), t1);
return Fp12$1.mul(Fp12$1.mul(Fp12$1.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1);
}
});
const Fr$1 = Field(BigInt("0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"));
const isogenyMapG2 = isogenyMap(Fp2$1, [
// xNum
[
[
"0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6",
"0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6"
],
[
"0x0",
"0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a"
],
[
"0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e",
"0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d"
],
[
"0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1",
"0x0"
]
],
// xDen
[
[
"0x0",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63"
],
[
"0xc",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f"
],
["0x1", "0x0"]
// LAST 1
],
// yNum
[
[
"0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706",
"0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706"
],
[
"0x0",
"0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be"
],
[
"0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c",
"0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f"
],
[
"0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10",
"0x0"
]
],
// yDen
[
[
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb"
],
[
"0x0",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3"
],
[
"0x12",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99"
],
["0x1", "0x0"]
// LAST 1
]
].map((i) => i.map((pair) => Fp2$1.fromBigTuple(pair.map(BigInt)))));
const isogenyMapG1 = isogenyMap(Fp$1, [
// xNum
[
"0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7",
"0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb",
"0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0",
"0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861",
"0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9",
"0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983",
"0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84",
"0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e",
"0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317",
"0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e",
"0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b",
"0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229"
],
// xDen
[
"0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c",
"0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff",
"0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19",
"0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8",
"0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e",
"0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5",
"0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a",
"0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e",
"0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641",
"0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a",
"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"
// LAST 1
],
// yNum
[
"0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33",
"0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696",
"0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6",
"0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb",
"0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb",
"0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0",
"0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2",
"0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29",
"0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587",
"0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30",
"0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132",
"0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e",
"0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8",
"0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133",
"0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b",
"0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604"
],
// yDen
[
"0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1",
"0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d",
"0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2",
"0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416",
"0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d",
"0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac",
"0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c",
"0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9",
"0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a",
"0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55",
"0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8",
"0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092",
"0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc",
"0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7",
"0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f",
"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"
// LAST 1
]
].map((i) => i.map((j) => BigInt(j))));
const G2_SWU = mapToCurveSimpleSWU(Fp2$1, {
A: Fp2$1.create({ c0: Fp$1.create(_0n), c1: Fp$1.create(BigInt(240)) }),
// A' = 240 * I
B: Fp2$1.create({ c0: Fp$1.create(BigInt(1012)), c1: Fp$1.create(BigInt(1012)) }),
// B' = 1012 * (1 + I)
Z: Fp2$1.create({ c0: Fp$1.create(BigInt(-2)), c1: Fp$1.create(BigInt(-1)) })
// Z: -(2 + I)
});
const G1_SWU = mapToCurveSimpleSWU(Fp$1, {
A: Fp$1.create(BigInt("0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d")),
B: Fp$1.create(BigInt("0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0")),
Z: Fp$1.create(BigInt(11))
});
const { G2psi: G2psi$1, G2psi2 } = psiFrobenius(Fp$1, Fp2$1, Fp2$1.div(Fp2$1.ONE, Fp2$1.NONRESIDUE));
const htfDefaults$1 = Object.freeze({
// DST: a domain separation tag
// defined in section 2.2.5
// Use utils.getDSTLabel(), utils.setDSTLabel(value)
DST: "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_",
encodeDST: "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_",
// p: the characteristic of F
// where F is a finite field of characteristic p and order q = p^m
p: Fp$1.ORDER,
// m: the extension degree of F, m >= 1
// where F is a finite field of characteristic p and order q = p^m
m: 2,
// k: the target security level for the suite in bits
// defined in section 5.1
k: 128,
// option to use a message that has already been processed by
// expand_message_xmd
expand: "xmd",
// Hash functions for: expand_message_xmd is appropriate for use with a
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
hash: sha256$1
});
const COMPRESSED_ZERO = setMask(Fp$1.toBytes(_0n), { infinity: true, compressed: true });
function parseMask(bytes2) {
bytes2 = bytes2.slice();
const mask = bytes2[0] & 224;
const compressed = !!(mask >> 7 & 1);
const infinity = !!(mask >> 6 & 1);
const sort = !!(mask >> 5 & 1);
bytes2[0] &= 31;
return { compressed, infinity, sort, value: bytes2 };
}
function setMask(bytes2, mask) {
if (bytes2[0] & 224)
throw new Error("setMask: non-empty mask");
if (mask.compressed)
bytes2[0] |= 128;
if (mask.infinity)
bytes2[0] |= 64;
if (mask.sort)
bytes2[0] |= 32;
return bytes2;
}
function signatureG1ToRawBytes(point) {
point.assertValidity();
const isZero = point.equals(bls12_381.G1.ProjectivePoint.ZERO);
const { x, y } = point.toAffine();
if (isZero)
return COMPRESSED_ZERO.slice();
const P = Fp$1.ORDER;
const sort = Boolean(y * _2n$1 / P);
return setMask(numberToBytesBE(x, Fp$1.BYTES), { compressed: true, sort });
}
function signatureG2ToRawBytes(point) {
point.assertValidity();
const len = Fp$1.BYTES;
if (point.equals(bls12_381.G2.ProjectivePoint.ZERO))
return concatBytes$2(COMPRESSED_ZERO, numberToBytesBE(_0n, len));
const { x, y } = point.toAffine();
const { re: x0, im: x1 } = Fp2$1.reim(x);
const { re: y0, im: y1 } = Fp2$1.reim(y);
const tmp = y1 > _0n ? y1 * _2n$1 : y0 * _2n$1;
const sort = Boolean(tmp / Fp$1.ORDER & _1n$1);
const z2 = x0;
return concatBytes$2(setMask(numberToBytesBE(x1, len), { sort, compressed: true }), numberToBytesBE(z2, len));
}
const bls12_381 = bls({
// Fields
fields: {
Fp: Fp$1,
Fp2: Fp2$1,
Fp6: Fp6$1,
Fp12: Fp12$1,
Fr: Fr$1
},
// G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where
// characteristic; z + (z⁴ - z² + 1)(z - 1)²/3
G1: {
Fp: Fp$1,
// cofactor; (z - 1)²/3
h: BigInt("0x396c8c005555e1568c00aaab0000aaab"),
// generator's coordinates
// x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
// y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
Gx: BigInt("0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"),
Gy: BigInt("0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"),
a: Fp$1.ZERO,
b: _4n,
htfDefaults: { ...htfDefaults$1, m: 1, DST: "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_" },
wrapPrivateKey: true,
allowInfinityPoint: true,
// Checks is the point resides in prime-order subgroup.
// point.isTorsionFree() should return true for valid points
// It returns false for shitty points.
// https://eprint.iacr.org/2021/1130.pdf
isTorsionFree: (c, point) => {
const cubicRootOfUnityModP = BigInt("0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe");
const phi = new c(Fp$1.mul(point.px, cubicRootOfUnityModP), point.py, point.pz);
const xP = point.multiplyUnsafe(BLS_X).negate();
const u2P = xP.multiplyUnsafe(BLS_X);
return u2P.equals(phi);
},
// Clear cofactor of G1
// https://eprint.iacr.org/2019/403
clearCofactor: (_c, point) => {
return point.multiplyUnsafe(BLS_X).add(point);
},
mapToCurve: (scalars) => {
const { x, y } = G1_SWU(Fp$1.create(scalars[0]));
return isogenyMapG1(x, y);
},
fromBytes: (bytes2) => {
const { compressed, infinity, sort, value } = parseMask(bytes2);
if (value.length === 48 && compressed) {
const P = Fp$1.ORDER;
const compressedValue = bytesToNumberBE(value);
const x = Fp$1.create(compressedValue & Fp$1.MASK);
if (infinity) {
if (x !== _0n)
throw new Error("G1: non-empty compressed point at infinity");
return { x: _0n, y: _0n };
}
const right = Fp$1.add(Fp$1.pow(x, _3n$1), Fp$1.create(bls12_381.params.G1b));
let y = Fp$1.sqrt(right);
if (!y)
throw new Error("Invalid compressed G1 point");
if (y * _2n$1 / P !== BigInt(sort))
y = Fp$1.neg(y);
return { x: Fp$1.create(x), y: Fp$1.create(y) };
} else if (value.length === 96 && !compressed) {
const x = bytesToNumberBE(value.subarray(0, Fp$1.BYTES));
const y = bytesToNumberBE(value.subarray(Fp$1.BYTES));
if (infinity) {
if (x !== _0n || y !== _0n)
throw new Error("G1: non-empty point at infinity");
return bls12_381.G1.ProjectivePoint.ZERO.toAffine();
}
return { x: Fp$1.create(x), y: Fp$1.create(y) };
} else {
throw new Error("Invalid point G1, expected 48/96 bytes");
}
},
toBytes: (c, point, isCompressed) => {
const isZero = point.equals(c.ZERO);
const { x, y } = point.toAffine();
if (isCompressed) {
if (isZero)
return COMPRESSED_ZERO.slice();
const P = Fp$1.ORDER;
const sort = Boolean(y * _2n$1 / P);
return setMask(numberToBytesBE(x, Fp$1.BYTES), { compressed: true, sort });
} else {
if (isZero) {
const x2 = concatBytes$2(new Uint8Array([64]), new Uint8Array(2 * Fp$1.BYTES - 1));
return x2;
} else {
return concatBytes$2(numberToBytesBE(x, Fp$1.BYTES), numberToBytesBE(y, Fp$1.BYTES));
}
}
},
ShortSignature: {
fromHex(hex) {
const { infinity, sort, value } = parseMask(ensureBytes("signatureHex", hex, 48));
const P = Fp$1.ORDER;
const compressedValue = bytesToNumberBE(value);
if (infinity)
return bls12_381.G1.ProjectivePoint.ZERO;
const x = Fp$1.create(compressedValue & Fp$1.MASK);
const right = Fp$1.add(Fp$1.pow(x, _3n$1), Fp$1.create(bls12_381.params.G1b));
let y = Fp$1.sqrt(right);
if (!y)
throw new Error("Invalid compressed G1 point");
const aflag = BigInt(sort);
if (y * _2n$1 / P !== aflag)
y = Fp$1.neg(y);
const point = bls12_381.G1.ProjectivePoint.fromAffine({ x, y });
point.assertValidity();
return point;
},
toRawBytes(point) {
return signatureG1ToRawBytes(point);
},
toHex(point) {
return bytesToHex$2(signatureG1ToRawBytes(point));
}
}
},
// G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1),
// where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where
// G² - 1
// h2q
G2: {
Fp: Fp2$1,
// cofactor
h: BigInt("0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5"),
Gx: Fp2$1.fromBigTuple([
BigInt("0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8"),
BigInt("0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e")
]),
// y =
// 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582,
// 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905
Gy: Fp2$1.fromBigTuple([
BigInt("0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801"),
BigInt("0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be")
]),
a: Fp2$1.ZERO,
b: Fp2$1.fromBigTuple([_4n, _4n]),
hEff: BigInt("0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551"),
htfDefaults: { ...htfDefaults$1 },
wrapPrivateKey: true,
allowInfinityPoint: true,
mapToCurve: (scalars) => {
const { x, y } = G2_SWU(Fp2$1.fromBigTuple(scalars));
return isogenyMapG2(x, y);
},
// Checks is the point resides in prime-order subgroup.
// point.isTorsionFree() should return true for valid points
// It returns false for shitty points.
// https://eprint.iacr.org/2021/1130.pdf
isTorsionFree: (c, P) => {
return P.multiplyUnsafe(BLS_X).negate().equals(G2psi$1(c, P));
},
// Maps the point into the prime-order subgroup G2.
// clear_cofactor_bls12381_g2 from cfrg-hash-to-curve-11
// https://eprint.iacr.org/2017/419.pdf
// prettier-ignore
clearCofactor: (c, P) => {
const x = BLS_X;
let t1 = P.multiplyUnsafe(x).negate();
let t2 = G2psi$1(c, P);
let t3 = P.double();
t3 = G2psi2(c, t3);
t3 = t3.subtract(t2);
t2 = t1.add(t2);
t2 = t2.multiplyUnsafe(x).negate();
t3 = t3.add(t2);
t3 = t3.subtract(t1);
const Q = t3.subtract(P);
return Q;
},
fromBytes: (bytes2) => {
const { compressed, infinity, sort, value } = parseMask(bytes2);
if (!compressed && !infinity && sort || // 00100000
!compressed && infinity && sort || // 01100000
sort && infinity && compressed) {
throw new Error("Invalid encoding flag: " + (bytes2[0] & 224));
}
const L = Fp$1.BYTES;
const slc = (b, from, to) => bytesToNumberBE(b.slice(from, to));
if (value.length === 96 && compressed) {
const b = bls12_381.params.G2b;
const P = Fp$1.ORDER;
if (infinity) {
if (value.reduce((p, c) => p !== 0 ? c + 1 : c, 0) > 0) {
throw new Error("Invalid compressed G2 point");
}
return { x: Fp2$1.ZERO, y: Fp2$1.ZERO };
}
const x_1 = slc(value, 0, L);
const x_0 = slc(value, L, 2 * L);
const x = Fp2$1.create({ c0: Fp$1.create(x_0), c1: Fp$1.create(x_1) });
const right = Fp2$1.add(Fp2$1.pow(x, _3n$1), b);
let y = Fp2$1.sqrt(right);
const Y_bit = y.c1 === _0n ? y.c0 * _2n$1 / P : y.c1 * _2n$1 / P ? _1n$1 : _0n;
y = sort && Y_bit > 0 ? y : Fp2$1.neg(y);
return { x, y };
} else if (value.length === 192 && !compressed) {
if (infinity) {
if (value.reduce((p, c) => p !== 0 ? c + 1 : c, 0) > 0) {
throw new Error("Invalid uncompressed G2 point");
}
return { x: Fp2$1.ZERO, y: Fp2$1.ZERO };
}
const x1 = slc(value, 0, L);
const x0 = slc(value, L, 2 * L);
const y1 = slc(value, 2 * L, 3 * L);
const y0 = slc(value, 3 * L, 4 * L);
return { x: Fp2$1.fromBigTuple([x0, x1]), y: Fp2$1.fromBigTuple([y0, y1]) };
} else {
throw new Error("Invalid point G2, expected 96/192 bytes");
}
},
toBytes: (c, point, isCompressed) => {
const { BYTES: len, ORDER: P } = Fp$1;
const isZero = point.equals(c.ZERO);
const { x, y } = point.toAffine();
if (isCompressed) {
if (isZero)
return concatBytes$2(COMPRESSED_ZERO, numberToBytesBE(_0n, len));
const flag = Boolean(y.c1 === _0n ? y.c0 * _2n$1 / P : y.c1 * _2n$1 / P);
return concatBytes$2(setMask(numberToBytesBE(x.c1, len), { compressed: true, sort: flag }), numberToBytesBE(x.c0, len));
} else {
if (isZero)
return concatBytes$2(new Uint8Array([64]), new Uint8Array(4 * len - 1));
const { re: x0, im: x1 } = Fp2$1.reim(x);
const { re: y0, im: y1 } = Fp2$1.reim(y);
return concatBytes$2(numberToBytesBE(x1, len), numberToBytesBE(x0, len), numberToBytesBE(y1, len), numberToBytesBE(y0, len));
}
},
Signature: {
// TODO: Optimize, it's very slow because of sqrt.
fromHex(hex) {
const { infinity, sort, value } = parseMask(ensureBytes("signatureHex", hex));
const P = Fp$1.ORDER;
const half = value.length / 2;
if (half !== 48 && half !== 96)
throw new Error("Invalid compressed signature length, must be 96 or 192");
const z1 = bytesToNumberBE(value.slice(0, half));
const z2 = bytesToNumberBE(value.slice(half));
if (infinity)
return bls12_381.G2.ProjectivePoint.ZERO;
const x1 = Fp$1.create(z1 & Fp$1.MASK);
const x2 = Fp$1.create(z2);
const x = Fp2$1.create({ c0: x2, c1: x1 });
const y2 = Fp2$1.add(Fp2$1.pow(x, _3n$1), bls12_381.params.G2b);
let y = Fp2$1.sqrt(y2);
if (!y)
throw new Error("Failed to find a square root");
const { re: y0, im: y1 } = Fp2$1.reim(y);
const aflag1 = BigInt(sort);
const isGreater = y1 > _0n && y1 * _2n$1 / P !== aflag1;
const isZero = y1 === _0n && y0 * _2n$1 / P !== aflag1;
if (isGreater || isZero)
y = Fp2$1.neg(y);
const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y });
point.assertValidity();
return point;
},
toRawBytes(point) {
return signatureG2ToRawBytes(point);
},
toHex(point) {
return bytesToHex$2(signatureG2ToRawBytes(point));
}
}
},
params: {
ateLoopSize: BLS_X,
// The BLS parameter x for BLS12-381
r: Fr$1.ORDER,
// order; z⁴ − z² + 1; CURVE.n from other curves
xNegative: true,
twistType: "multiplicative"
},
htfDefaults: htfDefaults$1,
hash: sha256$1,
randomBytes
});
const G1_ZERO = bls12_381.G1.ProjectivePoint.ZERO;
const G2_ZERO = bls12_381.G2.ProjectivePoint.ZERO;
function BLS12_381_ToG1Point(input, verifyOrder = true) {
if (equalsBytes(input, BLS_G1_INFINITY_POINT_BYTES)) {
return G1_ZERO;
}
const x = bytesToBigInt(input.subarray(16, BLS_G1_POINT_BYTE_LENGTH / 2));
const y = bytesToBigInt(input.subarray(80, BLS_G1_POINT_BYTE_LENGTH));
const G1 = bls12_381.G1.ProjectivePoint.fromAffine({
x,
y
});
try {
G1.assertValidity();
} catch (e) {
if (verifyOrder || e.message !== "bad point: not in prime-order subgroup")
throw new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE);
}
return G1;
}
function BLS12_381_FromG1Point(input) {
const xBytes = setLengthLeft(bigIntToBytes(input.x), 64);
const yBytes = setLengthLeft(bigIntToBytes(input.y), 64);
return concatBytes$1(xBytes, yBytes);
}
function BLS12_381_ToG2Point(input, verifyOrder = true) {
if (equalsBytes(input, BLS_G2_INFINITY_POINT_BYTES)) {
return G2_ZERO;
}
const p_x_1 = input.subarray(0, 64);
const p_x_2 = input.subarray(64, BLS_G2_POINT_BYTE_LENGTH / 2);
const p_y_1 = input.subarray(128, 192);
const p_y_2 = input.subarray(192, BLS_G2_POINT_BYTE_LENGTH);
const Fp2X = BLS12_381_ToFp2Point(p_x_1, p_x_2);
const Fp2Y = BLS12_381_ToFp2Point(p_y_1, p_y_2);
const pG2 = bls12_381.G2.ProjectivePoint.fromAffine({
x: Fp2X,
y: Fp2Y
});
try {
pG2.assertValidity();
} catch (e) {
if (verifyOrder || e.message !== "bad point: not in prime-order subgroup")
throw new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE);
}
return pG2;
}
function BLS12_381_FromG2Point(input) {
const xBytes1 = setLengthLeft(bigIntToBytes(input.x.c0), 64);
const xBytes2 = setLengthLeft(bigIntToBytes(input.x.c1), 64);
const yBytes1 = setLengthLeft(bigIntToBytes(input.y.c0), 64);
const yBytes2 = setLengthLeft(bigIntToBytes(input.y.c1), 64);
return concatBytes$1(xBytes1, xBytes2, yBytes1, yBytes2);
}
function BLS12_381_ToFrPoint(input) {
const Fr2 = bls12_381.fields.Fr.fromBytes(input);
return bls12_381.fields.Fr.create(Fr2);
}
function BLS12_381_ToFpPoint(fpCoordinate) {
if (bytesToBigInt(fpCoordinate) >= BLS_FIELD_MODULUS) {
throw new EvmError(ERROR.BLS_12_381_FP_NOT_IN_FIELD);
}
const FP = bls12_381.fields.Fp.fromBytes(fpCoordinate.slice(16));
return FP;
}
function BLS12_381_ToFp2Point(fpXCoordinate, fpYCoordinate) {
if (bytesToBigInt(fpXCoordinate) >= BLS_FIELD_MODULUS) {
throw new EvmError(ERROR.BLS_12_381_FP_NOT_IN_FIELD);
}
if (bytesToBigInt(fpYCoordinate) >= BLS_FIELD_MODULUS) {
throw new EvmError(ERROR.BLS_12_381_FP_NOT_IN_FIELD);
}
const fpBytes = concatBytes$1(fpXCoordinate.subarray(16), fpYCoordinate.subarray(16));
const FP = bls12_381.fields.Fp2.fromBytes(fpBytes);
return FP;
}
class NobleBLS {
addG1(input) {
const p1 = BLS12_381_ToG1Point(input.subarray(0, BLS_G1_POINT_BYTE_LENGTH), false);
const p2 = BLS12_381_ToG1Point(
input.subarray(BLS_G1_POINT_BYTE_LENGTH, BLS_G1_POINT_BYTE_LENGTH * 2),
false
);
const p = p1.add(p2);
const result = BLS12_381_FromG1Point(p);
return result;
}
mulG1(input) {
const p = BLS12_381_ToG1Point(input.subarray(0, BLS_G1_POINT_BYTE_LENGTH));
const scalar = BLS12_381_ToFrPoint(input.subarray(BLS_G1_POINT_BYTE_LENGTH, 160));
if (scalar === BIGINT_0) {
return BLS_G1_INFINITY_POINT_BYTES;
}
const result = p.multiplyUnsafe(scalar);
return BLS12_381_FromG1Point(result);
}
addG2(input) {
const p1 = BLS12_381_ToG2Point(input.subarray(0, BLS_G2_POINT_BYTE_LENGTH), false);
const p2 = BLS12_381_ToG2Point(
input.subarray(BLS_G2_POINT_BYTE_LENGTH, BLS_G2_POINT_BYTE_LENGTH * 2),
false
);
const p = p1.add(p2);
const result = BLS12_381_FromG2Point(p);
return result;
}
mulG2(input) {
const p = BLS12_381_ToG2Point(input.subarray(0, BLS_G2_POINT_BYTE_LENGTH));
const scalar = BLS12_381_ToFrPoint(input.subarray(BLS_G2_POINT_BYTE_LENGTH, 288));
if (scalar === BIGINT_0) {
return BLS_G2_INFINITY_POINT_BYTES;
}
const result = p.multiplyUnsafe(scalar);
return BLS12_381_FromG2Point(result);
}
mapFPtoG1(input) {
const FP = BLS12_381_ToFpPoint(input.subarray(0, 64));
const result = bls12_381.G1.mapToCurve([FP]).toAffine();
const resultBytes = BLS12_381_FromG1Point(result);
return resultBytes;
}
mapFP2toG2(input) {
const Fp2Point = BLS12_381_ToFp2Point(input.subarray(0, 64), input.subarray(64, 128));
const result = bls12_381.G2.mapToCurve([Fp2Point.c0, Fp2Point.c1]).toAffine();
const resultBytes = BLS12_381_FromG2Point(result);
return resultBytes;
}
msmG1(input) {
const pairLength = 160;
const numPairs = input.length / pairLength;
let pRes = G1_ZERO;
for (let k = 0; k < numPairs; k++) {
const pairStart = pairLength * k;
const G1 = BLS12_381_ToG1Point(
input.subarray(pairStart, pairStart + BLS_G1_POINT_BYTE_LENGTH)
);
const Fr2 = BLS12_381_ToFrPoint(
input.subarray(pairStart + BLS_G1_POINT_BYTE_LENGTH, pairStart + pairLength)
);
let pMul;
if (Fr2 === BIGINT_0) {
pMul = G1_ZERO;
} else {
pMul = G1.multiplyUnsafe(Fr2);
}
pRes = pRes.add(pMul);
}
return BLS12_381_FromG1Point(pRes);
}
msmG2(input) {
const pairLength = 288;
const numPairs = input.length / pairLength;
let pRes = G2_ZERO;
for (let k = 0; k < numPairs; k++) {
const pairStart = pairLength * k;
const G2 = BLS12_381_ToG2Point(
input.subarray(pairStart, pairStart + BLS_G2_POINT_BYTE_LENGTH)
);
const Fr2 = BLS12_381_ToFrPoint(
input.subarray(pairStart + BLS_G2_POINT_BYTE_LENGTH, pairStart + pairLength)
);
let pMul;
if (Fr2 === BIGINT_0) {
pMul = G2_ZERO;
} else {
pMul = G2.multiplyUnsafe(Fr2);
}
pRes = pRes.add(pMul);
}
return BLS12_381_FromG2Point(pRes);
}
pairingCheck(input) {
const pairLength = 384;
const pairs = [];
for (let k = 0; k < input.length / pairLength; k++) {
const pairStart = pairLength * k;
const G1 = BLS12_381_ToG1Point(
input.subarray(pairStart, pairStart + BLS_G1_POINT_BYTE_LENGTH)
);
const g2start = pairStart + BLS_G1_POINT_BYTE_LENGTH;
const G2 = BLS12_381_ToG2Point(input.subarray(g2start, g2start + BLS_G2_POINT_BYTE_LENGTH));
pairs.push({ g1: G1, g2: G2 });
}
for (const { g1, g2 } of pairs) {
const _g2 = g2;
if (g1.equals(G1_ZERO) || _g2.equals(G2_ZERO)) {
return BLS_ONE_BUFFER;
}
}
const FP12 = bls12_381.pairingBatch(pairs, true);
if (bls12_381.fields.Fp12.eql(FP12, bls12_381.fields.Fp12.ONE)) {
return BLS_ONE_BUFFER;
} else {
return BLS_ZERO_BUFFER;
}
}
}
const ZERO_BYTES_16 = new Uint8Array(16);
const msmGasUsed = (numPairs, gasUsedPerPair) => {
const gasDiscountMax = BLS_GAS_DISCOUNT_PAIRS[BLS_GAS_DISCOUNT_PAIRS.length - 1][1];
let gasDiscountMultiplier;
if (numPairs <= BLS_GAS_DISCOUNT_PAIRS.length) {
if (numPairs === 0) {
gasDiscountMultiplier = 0;
} else {
gasDiscountMultiplier = BLS_GAS_DISCOUNT_PAIRS[numPairs - 1][1];
}
} else {
gasDiscountMultiplier = gasDiscountMax;
}
return BigInt(numPairs) * gasUsedPerPair * BigInt(gasDiscountMultiplier) / BigInt(1e3);
};
const leading16ZeroBytesCheck = (opts, zeroByteRanges, pName, pairStart = 0) => {
for (const index in zeroByteRanges) {
const slicedBuffer = opts.data.subarray(
zeroByteRanges[index][0] + pairStart,
zeroByteRanges[index][1] + pairStart
);
if (!(equalsBytes(slicedBuffer, ZERO_BYTES_16) === true)) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: Point not on curve`);
}
return false;
}
}
return true;
};
async function precompile0b(opts) {
const pName = getPrecompileName("0b");
const bls2 = opts._EVM._bls;
const gasUsed = opts.common.paramByEIP("bls12381G1AddGas", 2537) ?? BigInt(0);
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
if (!equalityLengthCheck(opts, 256, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit);
}
const zeroByteRanges = [
[0, 16],
[64, 80],
[128, 144],
[192, 208]
];
if (!leading16ZeroBytesCheck(opts, zeroByteRanges, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit);
}
let returnValue;
try {
returnValue = bls2.addG1(opts.data);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: ${e.message}`);
}
return EvmErrorResult(e, opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnValue)}`);
}
return {
executionGasUsed: gasUsed,
returnValue
};
}
async function precompile0c(opts) {
const pName = getPrecompileName("0c");
const bls2 = opts._EVM._bls;
const gasUsed = opts.common.paramByEIP("bls12381G1MulGas", 2537) ?? BigInt(0);
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
if (!equalityLengthCheck(opts, 160, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit);
}
const zeroByteRanges = [
[0, 16],
[64, 80]
];
if (!leading16ZeroBytesCheck(opts, zeroByteRanges, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit);
}
let returnValue;
try {
returnValue = bls2.mulG1(opts.data);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: ${e.message}`);
}
return EvmErrorResult(e, opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnValue)}`);
}
return {
executionGasUsed: gasUsed,
returnValue
};
}
async function precompile0d(opts) {
const pName = getPrecompileName("0d");
const bls2 = opts._EVM._bls;
const inputData = opts.data;
if (inputData.length === 0) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: Empty input`);
}
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INPUT_EMPTY), opts.gasLimit);
}
const numPairs = Math.floor(inputData.length / 160);
const gasUsedPerPair = opts.common.paramByEIP("bls12381G1MulGas", 2537) ?? BigInt(0);
const gasUsed = msmGasUsed(numPairs, gasUsedPerPair);
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
if (inputData.length % 160 !== 0) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: Invalid input length length=${inputData.length}`);
}
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit);
}
if (!moduloLengthCheck(opts, 160, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit);
}
const zeroByteRanges = [
[0, 16],
[64, 80]
];
for (let k = 0; k < numPairs; k++) {
const pairStart = 160 * k;
if (!leading16ZeroBytesCheck(opts, zeroByteRanges, pName, pairStart)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit);
}
}
let returnValue;
try {
returnValue = bls2.msmG1(opts.data);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: ${e.message}`);
}
return EvmErrorResult(e, opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnValue)}`);
}
return {
executionGasUsed: gasUsed,
returnValue
};
}
async function precompile0e(opts) {
const pName = getPrecompileName("0e");
const bls2 = opts._EVM._bls;
const gasUsed = opts.common.paramByEIP("bls12381G2AddGas", 2537) ?? BigInt(0);
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
if (!equalityLengthCheck(opts, 512, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit);
}
const zeroByteRanges = [
[0, 16],
[64, 80],
[128, 144],
[192, 208],
[256, 272],
[320, 336],
[384, 400],
[448, 464]
];
if (!leading16ZeroBytesCheck(opts, zeroByteRanges, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit);
}
let returnValue;
try {
returnValue = bls2.addG2(opts.data);
} catch (e) {
return EvmErrorResult(e, opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnValue)}`);
}
return {
executionGasUsed: gasUsed,
returnValue
};
}
async function precompile0f(opts) {
const pName = getPrecompileName("0f");
const bls2 = opts._EVM._bls;
const gasUsed = opts.common.paramByEIP("bls12381G2MulGas", 2537) ?? BigInt(0);
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
if (!equalityLengthCheck(opts, 288, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit);
}
const zeroByteRanges = [
[0, 16],
[64, 80],
[128, 144],
[192, 208]
];
if (!leading16ZeroBytesCheck(opts, zeroByteRanges, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit);
}
let returnValue;
try {
returnValue = bls2.mulG2(opts.data);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: ${e.message}`);
}
return EvmErrorResult(e, opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnValue)}`);
}
return {
executionGasUsed: gasUsed,
returnValue
};
}
async function precompile10(opts) {
const pName = getPrecompileName("10");
const bls2 = opts._EVM._bls;
if (opts.data.length === 0) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: Empty input`);
}
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INPUT_EMPTY), opts.gasLimit);
}
const numPairs = Math.floor(opts.data.length / 288);
const gasUsedPerPair = opts.common.paramByEIP("bls12381G2MulGas", 2537) ?? BigInt(0);
const gasUsed = msmGasUsed(numPairs, gasUsedPerPair);
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
if (!moduloLengthCheck(opts, 288, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit);
}
const zeroByteRanges = [
[0, 16],
[64, 80],
[128, 144],
[192, 208]
];
for (let k = 0; k < numPairs; k++) {
const pairStart = 288 * k;
if (!leading16ZeroBytesCheck(opts, zeroByteRanges, pName, pairStart)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit);
}
}
let returnValue;
try {
returnValue = bls2.msmG2(opts.data);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: ${e.message}`);
}
return EvmErrorResult(e, opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnValue)}`);
}
return {
executionGasUsed: gasUsed,
returnValue
};
}
async function precompile11(opts) {
const pName = getPrecompileName("11");
const bls2 = opts._EVM._bls;
const baseGas = opts.common.paramByEIP("bls12381PairingBaseGas", 2537) ?? BigInt(0);
if (opts.data.length === 0) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: Empty input`);
}
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INPUT_EMPTY), opts.gasLimit);
}
const gasUsedPerPair = opts.common.paramByEIP("bls12381PairingPerPairGas", 2537) ?? BigInt(0);
if (!moduloLengthCheck(opts, 384, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit);
}
const gasUsed = baseGas + gasUsedPerPair * BigInt(Math.floor(opts.data.length / 384));
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
const zeroByteRanges = [
[0, 16],
[64, 80],
[128, 144],
[192, 208],
[256, 272],
[320, 336]
];
for (let k = 0; k < opts.data.length / 384; k++) {
const pairStart = 384 * k;
if (!leading16ZeroBytesCheck(opts, zeroByteRanges, pName, pairStart)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit);
}
}
let returnValue;
try {
returnValue = bls2.pairingCheck(opts.data);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: ${e.message}`);
}
return EvmErrorResult(e, opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnValue)}`);
}
return {
executionGasUsed: gasUsed,
returnValue
};
}
async function precompile12(opts) {
const pName = getPrecompileName("12");
const bls2 = opts._EVM._bls;
const gasUsed = opts.common.paramByEIP("bls12381MapG1Gas", 2537) ?? BigInt(0);
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
if (!equalityLengthCheck(opts, 64, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit);
}
const zeroByteRanges = [[0, 16]];
if (!leading16ZeroBytesCheck(opts, zeroByteRanges, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit);
}
let returnValue;
try {
returnValue = bls2.mapFPtoG1(opts.data);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: ${e.message}`);
}
return EvmErrorResult(e, opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnValue)}`);
}
return {
executionGasUsed: gasUsed,
returnValue
};
}
async function precompile13(opts) {
const pName = getPrecompileName("13");
const bls2 = opts._EVM._bls;
const gasUsed = opts.common.paramByEIP("bls12381MapG2Gas", 2537) ?? BigInt(0);
if (!gasLimitCheck(opts, gasUsed, pName)) {
return OOGResult(opts.gasLimit);
}
if (!equalityLengthCheck(opts, 128, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_INVALID_INPUT_LENGTH), opts.gasLimit);
}
const zeroByteRanges = [
[0, 16],
[64, 80]
];
if (!leading16ZeroBytesCheck(opts, zeroByteRanges, pName)) {
return EvmErrorResult(new EvmError(ERROR.BLS_12_381_POINT_NOT_ON_CURVE), opts.gasLimit);
}
let returnValue;
try {
returnValue = bls2.mapFP2toG2(opts.data);
} catch (e) {
if (opts._debug !== void 0) {
opts._debug(`${pName} failed: ${e.message}`);
}
return EvmErrorResult(e, opts.gasLimit);
}
if (opts._debug !== void 0) {
opts._debug(`${pName} return value=${bytesToHex$1(returnValue)}`);
}
return {
executionGasUsed: gasUsed,
returnValue
};
}
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
const _6n = BigInt(6);
const BN_X = BigInt("4965661367192848881");
const BN_X_LEN = bitLen(BN_X);
const SIX_X_SQUARED = _6n * BN_X ** _2n;
const Fr = Field(BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
const Fp2B = {
c0: BigInt("19485874751759354771024239261021720505790618469301721065564631296452457478373"),
c1: BigInt("266929791119991161246907387137283842545076965332900288569378510910307636690")
};
const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({
ORDER: BigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583"),
FP2_NONRESIDUE: [BigInt(9), _1n],
Fp2mulByB: (num) => Fp2.mul(num, Fp2B),
// The result of any pairing is in a cyclotomic subgroup
// https://eprint.iacr.org/2009/565.pdf
Fp12cyclotomicSquare: ({ c0, c1 }) => {
const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0;
const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1;
const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1);
const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2);
const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2);
let t9 = Fp2.mulByNonresidue(t8);
return {
c0: Fp6.create({
c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3),
// 2 * (T3 - c0c0) + T3
c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5),
// 2 * (T5 - c0c1) + T5
c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7)
}),
// 2 * (T7 - c0c2) + T7
c1: Fp6.create({
c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9),
// 2 * (T9 + c1c0) + T9
c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4),
// 2 * (T4 + c1c1) + T4
c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6)
})
};
},
Fp12cyclotomicExp(num, n) {
let z = Fp12.ONE;
for (let i = BN_X_LEN - 1; i >= 0; i--) {
z = Fp12._cyclotomicSquare(z);
if (bitGet(n, i))
z = Fp12.mul(z, num);
}
return z;
},
// https://eprint.iacr.org/2010/354.pdf
// https://eprint.iacr.org/2009/565.pdf
Fp12finalExponentiate: (num) => {
const powMinusX = (num2) => Fp12.conjugate(Fp12._cyclotomicExp(num2, BN_X));
const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num));
const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0);
const y1 = Fp12._cyclotomicSquare(powMinusX(r));
const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1);
const y4 = powMinusX(y2);
const y6 = powMinusX(Fp12._cyclotomicSquare(y4));
const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2));
const y9 = Fp12.mul(y8, y1);
return Fp12.mul(Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), Fp12.mul(Fp12.frobeniusMap(y8, 2), Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r))));
}
});
const { G2psi, psi } = psiFrobenius(Fp, Fp2, Fp2.NONRESIDUE);
const htfDefaults = Object.freeze({
// DST: a domain separation tag defined in section 2.2.5
DST: "BN254G2_XMD:SHA-256_SVDW_RO_",
encodeDST: "BN254G2_XMD:SHA-256_SVDW_RO_",
p: Fp.ORDER,
m: 2,
k: 128,
expand: "xmd",
hash: sha256$1
});
const bn254 = bls({
// Fields
fields: { Fp, Fp2, Fp6, Fp12, Fr },
G1: {
Fp,
h: BigInt(1),
Gx: BigInt(1),
Gy: BigInt(2),
a: Fp.ZERO,
b: _3n,
htfDefaults: { ...htfDefaults, m: 1, DST: "BN254G2_XMD:SHA-256_SVDW_RO_" },
wrapPrivateKey: true,
allowInfinityPoint: true,
mapToCurve: notImplemented,
fromBytes: notImplemented,
toBytes: notImplemented,
ShortSignature: {
fromHex: notImplemented,
toRawBytes: notImplemented,
toHex: notImplemented
}
},
G2: {
Fp: Fp2,
// cofactor: (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1
h: BigInt("21888242871839275222246405745257275088844257914179612981679871602714643921549"),
Gx: Fp2.fromBigTuple([
BigInt("10857046999023057135944570762232829481370756359578518086990519993285655852781"),
BigInt("11559732032986387107991004021392285783925812861821192530917403151452391805634")
]),
Gy: Fp2.fromBigTuple([
BigInt("8495653923123431417604973247489272438418190587263600148770280649306958101930"),
BigInt("4082367875863433681332203403145435568316851327593401208105741076214120093531")
]),
a: Fp2.ZERO,
b: Fp2B,
hEff: BigInt("21888242871839275222246405745257275088844257914179612981679871602714643921549"),
htfDefaults: { ...htfDefaults },
wrapPrivateKey: true,
allowInfinityPoint: true,
isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)),
// [p]P = [6X^2]P
mapToCurve: notImplemented,
fromBytes: notImplemented,
toBytes: notImplemented,
Signature: {
fromHex: notImplemented,
toRawBytes: notImplemented,
toHex: notImplemented
}
},
params: {
ateLoopSize: BN_X * _6n + _2n,
r: Fr.ORDER,
xNegative: false,
twistType: "divisive"
},
htfDefaults,
hash: sha256$1,
randomBytes,
postPrecompute: (Rx, Ry, Rz, Qx, Qy, pointAdd) => {
const q = psi(Qx, Qy);
({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1]));
const q2 = psi(q[0], q[1]);
pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1]));
}
});
weierstrass({
a: BigInt(0),
b: BigInt(3),
Fp,
n: BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"),
Gx: BigInt(1),
Gy: BigInt(2),
h: BigInt(1),
...getHash(sha256$1)
});
const G1_INFINITY_POINT_BYTES = new Uint8Array(64);
const G2_INFINITY_POINT_BYTES = new Uint8Array(128);
const G1_POINT_BYTE_LENGTH = 64;
const G1_ELEMENT_BYTE_LENGTH = 32;
const G2_POINT_BYTE_LENGTH = 128;
const ZERO_BUFFER = new Uint8Array(32);
const ONE_BUFFER = concatBytes$1(new Uint8Array(31), hexToBytes$1("0x01"));
function toG1Point(input) {
if (equalsBytes(input, G1_INFINITY_POINT_BYTES)) {
return bn254.G1.ProjectivePoint.ZERO;
}
const x = bytesToBigInt(input.subarray(0, G1_ELEMENT_BYTE_LENGTH));
const y = bytesToBigInt(input.subarray(G1_ELEMENT_BYTE_LENGTH, G1_POINT_BYTE_LENGTH));
const G1 = bn254.G1.ProjectivePoint.fromAffine({
x,
y
});
G1.assertValidity();
return G1;
}
function fromG1Point(input) {
const xBytes = setLengthLeft(bigIntToBytes(input.x), G1_ELEMENT_BYTE_LENGTH);
const yBytes = setLengthLeft(bigIntToBytes(input.y), G1_ELEMENT_BYTE_LENGTH);
return concatBytes$1(xBytes, yBytes);
}
function toFrPoint(input) {
const Fr2 = bn254.fields.Fr.fromBytes(input);
if (Fr2 >= bn254.fields.Fr.ORDER) {
return Fr2 % bn254.fields.Fr.ORDER;
}
return Fr2;
}
function toG2Point(input) {
if (equalsBytes(input, G2_INFINITY_POINT_BYTES)) {
return bn254.G2.ProjectivePoint.ZERO;
}
const p_x_2 = input.subarray(0, G1_ELEMENT_BYTE_LENGTH);
const p_x_1 = input.subarray(G1_ELEMENT_BYTE_LENGTH, G1_ELEMENT_BYTE_LENGTH * 2);
const start2 = G1_ELEMENT_BYTE_LENGTH * 2;
const p_y_2 = input.subarray(start2, start2 + G1_ELEMENT_BYTE_LENGTH);
const p_y_1 = input.subarray(start2 + G1_ELEMENT_BYTE_LENGTH, start2 + G1_ELEMENT_BYTE_LENGTH * 2);
for (const p of [p_x_1, p_x_2, p_y_1, p_y_2]) {
const pB = bytesToBigInt(p);
if (bn254.fields.Fp.create(pB) !== pB) {
throw new EvmError(ERROR.BN254_FP_NOT_IN_FIELD);
}
}
const Fp2X = toFp2Point(p_x_1, p_x_2);
const Fp2Y = toFp2Point(p_y_1, p_y_2);
const pG2 = bn254.G2.ProjectivePoint.fromAffine({
x: Fp2X,
y: Fp2Y
});
pG2.assertValidity();
return pG2;
}
function toFp2Point(fpXCoordinate, fpYCoordinate) {
if (bytesToBigInt(fpXCoordinate) >= bn254.fields.Fp2.ORDER) {
throw new EvmError(ERROR.BN254_FP_NOT_IN_FIELD);
}
if (bytesToBigInt(fpYCoordinate) >= bn254.fields.Fp2.ORDER) {
throw new EvmError(ERROR.BN254_FP_NOT_IN_FIELD);
}
const fpBytes = concatBytes$1(fpXCoordinate, fpYCoordinate);
const FP = bn254.fields.Fp2.fromBytes(fpBytes);
return FP;
}
class NobleBN254 {
add(input) {
const p1 = toG1Point(input.slice(0, G1_POINT_BYTE_LENGTH));
const p2 = toG1Point(input.slice(G1_POINT_BYTE_LENGTH, G1_POINT_BYTE_LENGTH * 2));
const result = fromG1Point(p1.add(p2));
return result;
}
mul(input) {
const p1 = toG1Point(input.slice(0, G1_POINT_BYTE_LENGTH));
const scalar = toFrPoint(input.slice(G1_POINT_BYTE_LENGTH, 96));
if (scalar === BIGINT_0) {
return G1_INFINITY_POINT_BYTES;
}
const result = fromG1Point(p1.multiply(scalar));
return result;
}
pairing(input) {
const pairLength = 192;
const pairs = [];
for (let k = 0; k < input.length / pairLength; k++) {
const pairStart = pairLength * k;
const G1 = toG1Point(input.subarray(pairStart, pairStart + G1_POINT_BYTE_LENGTH));
const g2start = pairStart + G1_POINT_BYTE_LENGTH;
const G2 = toG2Point(input.subarray(g2start, g2start + G2_POINT_BYTE_LENGTH));
if (G1 === bn254.G1.ProjectivePoint.ZERO || G2 === bn254.G2.ProjectivePoint.ZERO) {
continue;
}
pairs.push({ g1: G1, g2: G2 });
}
const res = bn254.pairingBatch(pairs);
if (bn254.fields.Fp12.eql(res, bn254.fields.Fp12.ONE) === true) {
return ONE_BUFFER;
} else {
return ZERO_BUFFER;
}
}
}
class RustBN254 {
constructor(rustbn) {
this._rustbn = rustbn;
}
add(input) {
const inputStr = bytesToUnprefixedHex(input);
return hexToBytes$1(this._rustbn.ec_add(inputStr));
}
mul(input) {
const inputHex = bytesToUnprefixedHex(input);
return hexToBytes$1(this._rustbn.ec_mul(inputHex));
}
pairing(input) {
const inputStr = bytesToUnprefixedHex(input);
return hexToBytes$1(this._rustbn.ec_pairing(inputStr));
}
}
const BYTES_19 = "00000000000000000000000000000000000000";
const precompileEntries = [
{
address: BYTES_19 + "01",
check: {
type: 1,
param: Hardfork.Chainstart
},
precompile: precompile01,
name: "ECRECOVER (0x01)"
},
{
address: BYTES_19 + "02",
check: {
type: 1,
param: Hardfork.Chainstart
},
precompile: precompile02,
name: "SHA256 (0x02)"
},
{
address: BYTES_19 + "03",
check: {
type: 1,
param: Hardfork.Chainstart
},
precompile: precompile03,
name: "RIPEMD160 (0x03)"
},
{
address: BYTES_19 + "04",
check: {
type: 1,
param: Hardfork.Chainstart
},
precompile: precompile04,
name: "IDENTITY (0x04)"
},
{
address: BYTES_19 + "05",
check: {
type: 1,
param: Hardfork.Byzantium
},
precompile: precompile05,
name: "MODEXP (0x05)"
},
{
address: BYTES_19 + "06",
check: {
type: 1,
param: Hardfork.Byzantium
},
precompile: precompile06,
name: "BN254_ADD (0x06)"
},
{
address: BYTES_19 + "07",
check: {
type: 1,
param: Hardfork.Byzantium
},
precompile: precompile07,
name: "BN254_MUL (0x07)"
},
{
address: BYTES_19 + "08",
check: {
type: 1,
param: Hardfork.Byzantium
},
precompile: precompile08,
name: "BN254_PAIRING (0x08)"
},
{
address: BYTES_19 + "09",
check: {
type: 1,
param: Hardfork.Istanbul
},
precompile: precompile09,
name: "BLAKE2f (0x09)"
},
{
address: BYTES_19 + "0a",
check: {
type: 0,
param: 4844
},
precompile: precompile0a,
name: "KZG_POINT_EVALUATION (0x0a)"
},
{
address: BYTES_19 + "0b",
check: {
type: 0,
param: 2537
},
precompile: precompile0b,
name: "BLS12_G1ADD (0x0b)"
},
{
address: BYTES_19 + "0c",
check: {
type: 0,
param: 2537
},
precompile: precompile0c,
name: "BLS12_G1MUL (0x0c)"
},
{
address: BYTES_19 + "0d",
check: {
type: 0,
param: 2537
},
precompile: precompile0d,
name: "BLS12_G1MSM (0x0d)"
},
{
address: BYTES_19 + "0e",
check: {
type: 0,
param: 2537
},
precompile: precompile0e,
name: "BLS12_G2ADD (0x0e)"
},
{
address: BYTES_19 + "0f",
check: {
type: 0,
param: 2537
},
precompile: precompile0f,
name: "BLS12_G2MUL (0x0f)"
},
{
address: BYTES_19 + "10",
check: {
type: 0,
param: 2537
},
precompile: precompile10,
name: "BLS12_G2MSM (0x10)"
},
{
address: BYTES_19 + "11",
check: {
type: 0,
param: 2537
},
precompile: precompile11,
name: "BLS12_PAIRING (0x11)"
},
{
address: BYTES_19 + "12",
check: {
type: 0,
param: 2537
},
precompile: precompile12,
name: "BLS12_MAP_FP_TO_G1 (0x12)"
},
{
address: BYTES_19 + "13",
check: {
type: 0,
param: 2537
},
precompile: precompile13,
name: "BLS12_MAP_FP2_TO_G2 (0x13)"
}
];
function getActivePrecompiles(common2, customPrecompiles) {
const precompileMap = /* @__PURE__ */ new Map();
if (customPrecompiles) {
for (const precompile of customPrecompiles) {
precompileMap.set(
bytesToUnprefixedHex(precompile.address.bytes),
"function" in precompile ? precompile.function : void 0
);
}
}
for (const entry of precompileEntries) {
if (precompileMap.has(entry.address)) {
continue;
}
const type = entry.check.type;
if (type === 1 && common2.gteHardfork(entry.check.param) || entry.check.type === 0 && common2.isActivatedEIP(entry.check.param)) {
precompileMap.set(entry.address, entry.precompile);
}
}
return precompileMap;
}
function getPrecompileName(addressUnprefixedStr) {
if (addressUnprefixedStr.length < 40) {
addressUnprefixedStr = addressUnprefixedStr.padStart(40, "0");
}
for (const entry of precompileEntries) {
if (entry.address === addressUnprefixedStr) {
return entry.name;
}
}
return "";
}
class TransientStorage {
constructor() {
this._storage = /* @__PURE__ */ new Map();
this._changeJournal = [];
this._indices = [0];
}
/**
* Get the value for the given address and key
* @param addr the address for which transient storage is accessed
* @param key the key of the address to get
*/
get(addr, key) {
const map = this._storage.get(addr.toString());
if (!map) {
return new Uint8Array(32);
}
const value = map.get(bytesToHex$1(key));
if (!value) {
return new Uint8Array(32);
}
return value;
}
/**
* Put the given value for the address and key
* @param addr the address of the contract for which the key is being set
* @param key the slot to set for the address
* @param value the new value of the transient storage slot to set
*/
put(addr, key, value) {
if (key.length !== 32) {
throw new Error("Transient storage key must be 32 bytes long");
}
if (value.length > 32) {
throw new Error("Transient storage value cannot be longer than 32 bytes");
}
const addrString = addr.toString();
if (!this._storage.has(addrString)) {
this._storage.set(addrString, /* @__PURE__ */ new Map());
}
const map = this._storage.get(addrString);
const keyStr = bytesToHex$1(key);
const prevValue = map.get(keyStr) ?? new Uint8Array(32);
this._changeJournal.push({
addr: addrString,
key: keyStr,
prevValue
});
map.set(keyStr, value);
}
/**
* Commit all the changes since the last checkpoint
*/
commit() {
if (this._indices.length === 0) throw new Error("Nothing to commit");
this._indices.pop();
}
/**
* To be called whenever entering a new context. If revert is called after checkpoint, all changes after the latest checkpoint are reverted.
*/
checkpoint() {
this._indices.push(this._changeJournal.length);
}
/**
* Revert transient storage to the last checkpoint
*/
revert() {
const lastCheckpoint = this._indices.pop();
if (typeof lastCheckpoint === "undefined") throw new Error("Nothing to revert");
for (let i = this._changeJournal.length - 1; i >= lastCheckpoint; i--) {
const { key, prevValue, addr } = this._changeJournal[i];
this._storage.get(addr).set(key, prevValue);
}
this._changeJournal.splice(lastCheckpoint, this._changeJournal.length - lastCheckpoint);
}
/**
* Create a JSON representation of the current transient storage state
*/
toJSON() {
const result = {};
for (const [address, map] of this._storage.entries()) {
result[address] = {};
for (const [key, value] of map.entries()) {
result[address][key] = bytesToHex$1(value);
}
}
return result;
}
/**
* Clear transient storage state.
*/
clear() {
this._storage = /* @__PURE__ */ new Map();
this._changeJournal = [];
}
}
const debug = debugDefault("evm:evm");
const debugGas = debugDefault("evm:gas");
const debugPrecompiles = debugDefault("evm:precompiles");
const _EVM = class _EVM {
/**
*
* Creates new EVM object
*
* @deprecated The direct usage of this constructor is replaced since
* non-finalized async initialization lead to side effects. Please
* use the async {@link createEVM} constructor instead (same API).
*
* @param opts The EVM options
* @param bn128 Initialized bn128 WASM object for precompile usage (internal)
*/
constructor(opts) {
var _a, _b, _c, _d;
this.DEBUG = false;
this.common = opts.common;
this.blockchain = opts.blockchain;
this.stateManager = opts.stateManager;
if (this.common.isActivatedEIP(6800)) {
const mandatory = ["checkChunkWitnessPresent"];
for (const m of mandatory) {
if (!(m in this.stateManager)) {
throw new Error(
`State manager used must implement ${m} if Verkle (EIP-6800) is activated`
);
}
}
}
this.events = new AsyncEventEmitter();
this._optsCached = opts;
const supportedEIPs = [
663,
1153,
1559,
2537,
2565,
2718,
2929,
2930,
2935,
3198,
3529,
3540,
3541,
3607,
3651,
3670,
3855,
3860,
4200,
4399,
4750,
4788,
4844,
4895,
5133,
5450,
5656,
6110,
6206,
6780,
6800,
7002,
7069,
7251,
7480,
7516,
7620,
7685,
7692,
7698,
7702,
7709
];
for (const eip of this.common.eips()) {
if (!supportedEIPs.includes(eip)) {
throw new Error(`EIP-${eip} is not supported by the EVM`);
}
}
if (!_EVM.supportedHardforks.includes(this.common.hardfork())) {
throw new Error(
`Hardfork ${this.common.hardfork()} not set as supported in supportedHardforks`
);
}
this.common.updateParams(opts.params ?? paramsEVM);
this.allowUnlimitedContractSize = opts.allowUnlimitedContractSize ?? false;
this.allowUnlimitedInitCodeSize = opts.allowUnlimitedInitCodeSize ?? false;
this._customOpcodes = opts.customOpcodes;
this._customPrecompiles = opts.customPrecompiles;
this.journal = new Journal(this.stateManager, this.common);
this.transientStorage = new TransientStorage();
this.common.events.on("hardforkChanged", () => {
this.getActiveOpcodes();
this._precompiles = getActivePrecompiles(this.common, this._customPrecompiles);
});
this.getActiveOpcodes();
this._precompiles = getActivePrecompiles(this.common, this._customPrecompiles);
if (this.common.isActivatedEIP(2537)) {
this._bls = opts.bls ?? new NobleBLS();
(_b = (_a = this._bls).init) == null ? void 0 : _b.call(_a);
}
this._bn254 = opts.bn254;
this._emit = async (topic, data) => {
return new Promise((resolve) => this.events.emit(topic, data, resolve));
};
this.performanceLogger = new EVMPerformanceLogger();
this.DEBUG = typeof window === "undefined" ? ((_d = (_c = process == null ? void 0 : process.env) == null ? void 0 : _c.DEBUG) == null ? void 0 : _d.includes("ethjs")) ?? false : false;
}
get precompiles() {
return this._precompiles;
}
get opcodes() {
return this._opcodes;
}
/**
* Returns a list with the currently activated opcodes
* available for EVM execution
*/
getActiveOpcodes() {
const data = getOpcodesForHF(this.common, this._customOpcodes);
this._opcodes = data.opcodes;
this._dynamicGasHandlers = data.dynamicGasHandlers;
this._handlers = data.handlers;
this._opcodeMap = data.opcodeMap;
return data.opcodes;
}
async _executeCall(message) {
var _a, _b;
let gasLimit = message.gasLimit;
const fromAddress = message.caller;
if (this.common.isActivatedEIP(6800)) {
const sendsValue = message.value !== BIGINT_0;
if (message.depth === 0) {
const originAccessGas = message.accessWitness.touchTxOriginAndComputeGas(fromAddress);
debugGas(`originAccessGas=${originAccessGas} waived off for origin at depth=0`);
const destAccessGas = message.accessWitness.touchTxTargetAndComputeGas(message.to, {
sendsValue
});
debugGas(`destAccessGas=${destAccessGas} waived off for target at depth=0`);
}
let callAccessGas = message.accessWitness.touchAndChargeMessageCall(message.to);
if (sendsValue) {
callAccessGas += message.accessWitness.touchAndChargeValueTransfer(fromAddress, message.to);
}
gasLimit -= callAccessGas;
if (gasLimit < BIGINT_0) {
if (this.DEBUG) {
debugGas(`callAccessGas charged(${callAccessGas}) caused OOG (-> ${gasLimit})`);
}
return { execResult: OOGResult(message.gasLimit) };
} else {
if (this.DEBUG) {
debugGas(`callAccessGas used (${callAccessGas} gas (-> ${gasLimit}))`);
}
}
}
let account = await this.stateManager.getAccount(fromAddress);
if (!account) {
account = new Account();
}
let errorMessage;
if (!message.delegatecall) {
try {
await this._reduceSenderBalance(account, message);
} catch (e) {
errorMessage = e;
}
}
let toAccount = await this.stateManager.getAccount(message.to);
if (!toAccount) {
if (this.common.isActivatedEIP(6800)) {
const absenceProofAccessGas = message.accessWitness.touchAndChargeProofOfAbsence(
message.to
);
gasLimit -= absenceProofAccessGas;
if (gasLimit < BIGINT_0) {
if (this.DEBUG) {
debugGas(
`Proof of absence access charged(${absenceProofAccessGas}) caused OOG (-> ${gasLimit})`
);
}
return { execResult: OOGResult(message.gasLimit) };
} else {
if (this.DEBUG) {
debugGas(`Proof of absence access used (${absenceProofAccessGas} gas (-> ${gasLimit}))`);
}
}
}
toAccount = new Account();
}
if (!message.delegatecall) {
try {
await this._addToBalance(toAccount, message);
} catch (e) {
errorMessage = e;
}
}
await this._loadCode(message);
let exit = false;
if (!message.code || typeof message.code !== "function" && message.code.length === 0) {
exit = true;
if (this.DEBUG) {
debug(`Exit early on no code (CALL)`);
}
}
if (errorMessage !== void 0) {
exit = true;
if (this.DEBUG) {
debug(`Exit early on value transfer overflowed (CALL)`);
}
}
if (exit) {
return {
execResult: {
gasRefund: message.gasRefund,
executionGasUsed: message.gasLimit - gasLimit,
exceptionError: errorMessage,
// Only defined if addToBalance failed
returnValue: new Uint8Array(0)
}
};
}
let result;
if (message.isCompiled) {
let timer;
let callTimer;
let target;
if (((_a = this._optsCached.profiler) == null ? void 0 : _a.enabled) === true) {
target = bytesToUnprefixedHex(message.codeAddress.bytes);
target = getPrecompileName(target) ?? target.slice(20);
if (this.performanceLogger.hasTimer()) {
callTimer = this.performanceLogger.pauseTimer();
}
timer = this.performanceLogger.startTimer(target);
}
result = await this.runPrecompile(message.code, message.data, gasLimit);
if (((_b = this._optsCached.profiler) == null ? void 0 : _b.enabled) === true) {
this.performanceLogger.stopTimer(timer, Number(result.executionGasUsed), "precompiles");
if (callTimer !== void 0) {
this.performanceLogger.unpauseTimer(callTimer);
}
}
result.gasRefund = message.gasRefund;
} else {
if (this.DEBUG) {
debug(`Start bytecode processing...`);
}
result = await this.runInterpreter({ ...message, gasLimit });
}
if (message.depth === 0) {
this.postMessageCleanup();
}
result.executionGasUsed += message.gasLimit - gasLimit;
return {
execResult: result
};
}
async _executeCreate(message) {
let gasLimit = message.gasLimit;
const fromAddress = message.caller;
if (this.common.isActivatedEIP(6800)) {
if (message.depth === 0) {
const originAccessGas = message.accessWitness.touchTxOriginAndComputeGas(fromAddress);
debugGas(`originAccessGas=${originAccessGas} waived off for origin at depth=0`);
}
}
let account = await this.stateManager.getAccount(message.caller);
if (!account) {
account = new Account();
}
await this._reduceSenderBalance(account, message);
if (this.common.isActivatedEIP(3860)) {
if (message.data.length > Number(this.common.param("maxInitCodeSize")) && !this.allowUnlimitedInitCodeSize) {
return {
createdAddress: message.to,
execResult: {
returnValue: new Uint8Array(0),
exceptionError: new EvmError(ERROR.INITCODE_SIZE_VIOLATION),
executionGasUsed: message.gasLimit
}
};
}
}
message.code = message.data;
message.data = message.eofCallData ?? new Uint8Array();
message.to = await this._generateAddress(message);
if (this.common.isActivatedEIP(6780)) {
message.createdAddresses.add(message.to.toString());
}
if (this.DEBUG) {
debug(`Generated CREATE contract address ${message.to}`);
}
let toAccount = await this.stateManager.getAccount(message.to);
if (!toAccount) {
toAccount = new Account();
}
if (this.common.isActivatedEIP(6800)) {
const contractCreateAccessGas = message.accessWitness.touchAndChargeContractCreateInit(
message.to
);
gasLimit -= contractCreateAccessGas;
if (gasLimit < BIGINT_0) {
if (this.DEBUG) {
debugGas(
`ContractCreateInit charge(${contractCreateAccessGas}) caused OOG (-> ${gasLimit})`
);
}
return { execResult: OOGResult(message.gasLimit) };
} else {
if (this.DEBUG) {
debugGas(`ContractCreateInit charged (${contractCreateAccessGas} gas (-> ${gasLimit}))`);
}
}
}
if (toAccount.nonce && toAccount.nonce > BIGINT_0 || !(equalsBytes(toAccount.codeHash, KECCAK256_NULL) === true) || // See EIP 7610 and the discussion `https://ethereum-magicians.org/t/eip-7610-revert-creation-in-case-of-non-empty-storage`
!(equalsBytes(toAccount.storageRoot, KECCAK256_RLP) === true)) {
if (this.DEBUG) {
debug(`Returning on address collision`);
}
return {
createdAddress: message.to,
execResult: {
returnValue: new Uint8Array(0),
exceptionError: new EvmError(ERROR.CREATE_COLLISION),
executionGasUsed: message.gasLimit
}
};
}
await this.journal.putAccount(message.to, toAccount);
await this.stateManager.clearStorage(message.to);
const newContractEvent = {
address: message.to,
code: message.code
};
await this._emit("newContract", newContractEvent);
toAccount = await this.stateManager.getAccount(message.to);
if (!toAccount) {
toAccount = new Account();
}
if (this.common.gteHardfork(Hardfork.SpuriousDragon)) {
toAccount.nonce += BIGINT_1;
}
let errorMessage;
try {
await this._addToBalance(toAccount, message);
} catch (e) {
errorMessage = e;
}
let exit = false;
if (message.code === void 0 || typeof message.code !== "function" && message.code.length === 0) {
exit = true;
if (this.DEBUG) {
debug(`Exit early on no code (CREATE)`);
}
}
if (errorMessage !== void 0) {
exit = true;
if (this.DEBUG) {
debug(`Exit early on value transfer overflowed (CREATE)`);
}
}
if (exit) {
if (this.common.isActivatedEIP(6800)) {
const createCompleteAccessGas = message.accessWitness.touchAndChargeContractCreateCompleted(message.to);
gasLimit -= createCompleteAccessGas;
if (gasLimit < BIGINT_0) {
if (this.DEBUG) {
debug(
`ContractCreateComplete access gas (${createCompleteAccessGas}) caused OOG (-> ${gasLimit})`
);
}
return { execResult: OOGResult(message.gasLimit) };
} else {
debug(
`ContractCreateComplete access used (${createCompleteAccessGas}) gas (-> ${gasLimit})`
);
}
}
return {
createdAddress: message.to,
execResult: {
executionGasUsed: message.gasLimit - gasLimit,
gasRefund: message.gasRefund,
exceptionError: errorMessage,
// only defined if addToBalance failed
returnValue: new Uint8Array(0)
}
};
}
if (this.DEBUG) {
debug(`Start bytecode processing...`);
}
let result = await this.runInterpreter({ ...message, gasLimit, isCreate: true });
result.executionGasUsed += message.gasLimit - gasLimit;
let totalGas = result.executionGasUsed;
let returnFee = BIGINT_0;
if (!result.exceptionError && !this.common.isActivatedEIP(6800)) {
returnFee = BigInt(result.returnValue.length) * BigInt(this.common.param("createDataGas"));
totalGas = totalGas + returnFee;
if (this.DEBUG) {
debugGas(`Add return value size fee (${returnFee} to gas used (-> ${totalGas}))`);
}
}
let allowedCodeSize = true;
if (!result.exceptionError && this.common.gteHardfork(Hardfork.SpuriousDragon) && result.returnValue.length > Number(this.common.param("maxCodeSize"))) {
allowedCodeSize = false;
}
let CodestoreOOG = false;
if (totalGas <= message.gasLimit && (this.allowUnlimitedContractSize || allowedCodeSize)) {
if (this.common.isActivatedEIP(3541) && result.returnValue[0] === FORMAT) {
if (!this.common.isActivatedEIP(3540)) {
result = { ...result, ...INVALID_BYTECODE_RESULT(message.gasLimit) };
} else if (
// TODO check if this is correct
// Also likely cleanup this eofCallData stuff
/*(message.depth > 0 && message.eofCallData === undefined) ||
(message.depth === 0 && !isEOF(message.code))*/
!isEOF(message.code)
) {
result = { ...result, ...INVALID_BYTECODE_RESULT(message.gasLimit) };
} else {
result.executionGasUsed = totalGas;
}
} else {
result.executionGasUsed = totalGas;
}
} else {
if (this.common.gteHardfork(Hardfork.Homestead)) {
if (!allowedCodeSize) {
if (this.DEBUG) {
debug(`Code size exceeds maximum code size (>= SpuriousDragon)`);
}
result = { ...result, ...CodesizeExceedsMaximumError(message.gasLimit) };
} else {
if (this.DEBUG) {
debug(`Contract creation: out of gas`);
}
result = { ...result, ...OOGResult(message.gasLimit) };
}
} else {
if (totalGas - returnFee <= message.gasLimit) {
if (this.DEBUG) {
debug(`Not enough gas to pay the code deposit fee (Frontier)`);
}
result = { ...result, ...COOGResult(totalGas - returnFee) };
CodestoreOOG = true;
} else {
if (this.DEBUG) {
debug(`Contract creation: out of gas`);
}
result = { ...result, ...OOGResult(message.gasLimit) };
}
}
}
gasLimit = message.gasLimit - result.executionGasUsed;
if (!result.exceptionError && this.common.isActivatedEIP(6800)) {
const createCompleteAccessGas = message.accessWitness.touchAndChargeContractCreateCompleted(
message.to
);
gasLimit -= createCompleteAccessGas;
if (gasLimit < BIGINT_0) {
if (this.DEBUG) {
debug(
`ContractCreateComplete access gas (${createCompleteAccessGas}) caused OOG (-> ${gasLimit})`
);
}
result = { ...result, ...OOGResult(message.gasLimit) };
} else {
debug(
`ContractCreateComplete access used (${createCompleteAccessGas}) gas (-> ${gasLimit})`
);
result.executionGasUsed += createCompleteAccessGas;
}
}
if (!result.exceptionError && result.returnValue !== void 0 && result.returnValue.length !== 0) {
if (this.common.isActivatedEIP(6800)) {
const byteCodeWriteAccessfee = message.accessWitness.touchCodeChunksRangeOnWriteAndChargeGas(
message.to,
0,
result.returnValue.length - 1
);
gasLimit -= byteCodeWriteAccessfee;
if (gasLimit < BIGINT_0) {
if (this.DEBUG) {
debug(
`byteCodeWrite access gas (${byteCodeWriteAccessfee}) caused OOG (-> ${gasLimit})`
);
}
result = { ...result, ...OOGResult(message.gasLimit) };
} else {
debug(`byteCodeWrite access used (${byteCodeWriteAccessfee}) gas (-> ${gasLimit})`);
result.executionGasUsed += byteCodeWriteAccessfee;
}
}
await this.stateManager.putCode(message.to, result.returnValue);
if (this.DEBUG) {
debug(`Code saved on new contract creation`);
}
} else if (CodestoreOOG) {
if (!this.common.gteHardfork(Hardfork.Homestead)) {
const account2 = await this.stateManager.getAccount(message.to);
await this.journal.putAccount(message.to, account2 ?? new Account());
}
}
if (message.depth === 0) {
this.postMessageCleanup();
}
return {
createdAddress: message.to,
execResult: result
};
}
/**
* Starts the actual bytecode processing for a CALL or CREATE
*/
async runInterpreter(message, opts = {}) {
var _a;
let contract = await this.stateManager.getAccount(message.to ?? createZeroAddress());
if (!contract) {
contract = new Account();
}
const env = {
address: message.to ?? createZeroAddress(),
caller: message.caller ?? createZeroAddress(),
callData: message.data ?? Uint8Array.from([0]),
callValue: message.value ?? BIGINT_0,
code: message.code,
isStatic: message.isStatic ?? false,
isCreate: message.isCreate ?? false,
depth: message.depth ?? 0,
gasPrice: this._tx.gasPrice,
origin: this._tx.origin ?? message.caller ?? createZeroAddress(),
block: this._block ?? defaultBlock(),
contract,
codeAddress: message.codeAddress,
gasRefund: message.gasRefund,
chargeCodeAccesses: message.chargeCodeAccesses,
blobVersionedHashes: message.blobVersionedHashes ?? [],
accessWitness: message.accessWitness,
createdAddresses: message.createdAddresses
};
const interpreter = new Interpreter(
this,
this.stateManager,
this.blockchain,
env,
message.gasLimit,
this.journal,
this.performanceLogger,
this._optsCached.profiler
);
if (message.selfdestruct) {
interpreter._result.selfdestruct = message.selfdestruct;
}
if (message.createdAddresses) {
interpreter._result.createdAddresses = message.createdAddresses;
}
const interpreterRes = await interpreter.run(message.code, opts);
let result = interpreter._result;
let gasUsed = message.gasLimit - interpreterRes.runState.gasLeft;
if (interpreterRes.exceptionError) {
if (interpreterRes.exceptionError.error !== ERROR.REVERT && interpreterRes.exceptionError.error !== ERROR.INVALID_EOF_FORMAT) {
gasUsed = message.gasLimit;
}
result = {
...result,
logs: [],
selfdestruct: /* @__PURE__ */ new Set(),
createdAddresses: /* @__PURE__ */ new Set()
};
}
return {
...result,
runState: {
...interpreterRes.runState,
...result,
...interpreter._env
},
exceptionError: interpreterRes.exceptionError,
gas: (_a = interpreterRes.runState) == null ? void 0 : _a.gasLeft,
executionGasUsed: gasUsed,
gasRefund: interpreterRes.runState.gasRefund,
returnValue: result.returnValue ? result.returnValue : new Uint8Array(0)
};
}
/**
* Executes an EVM message, determining whether it's a call or create
* based on the `to` address. It checkpoints the state and reverts changes
* if an exception happens during the message execution.
*/
async runCall(opts) {
var _a, _b;
let timer;
if ((opts.depth === 0 || opts.message === void 0) && ((_a = this._optsCached.profiler) == null ? void 0 : _a.enabled) === true) {
timer = this.performanceLogger.startTimer("Initialization");
}
let message = opts.message;
let callerAccount;
if (!message) {
this._block = opts.block ?? defaultBlock();
this._tx = {
gasPrice: opts.gasPrice ?? BIGINT_0,
origin: opts.origin ?? opts.caller ?? createZeroAddress()
};
const caller = opts.caller ?? createZeroAddress();
const value = opts.value ?? BIGINT_0;
if (opts.skipBalance === true) {
callerAccount = await this.stateManager.getAccount(caller);
if (!callerAccount) {
callerAccount = new Account();
}
if (callerAccount.balance < value) {
callerAccount.balance = value;
await this.journal.putAccount(caller, callerAccount);
}
}
message = new Message({
caller,
gasLimit: opts.gasLimit ?? BigInt(16777215),
to: opts.to,
value,
data: opts.data,
code: opts.code,
depth: opts.depth,
isCompiled: opts.isCompiled,
isStatic: opts.isStatic,
salt: opts.salt,
selfdestruct: opts.selfdestruct ?? /* @__PURE__ */ new Set(),
createdAddresses: opts.createdAddresses ?? /* @__PURE__ */ new Set(),
delegatecall: opts.delegatecall,
blobVersionedHashes: opts.blobVersionedHashes,
accessWitness: opts.accessWitness
});
}
if (message.depth === 0) {
if (!callerAccount) {
callerAccount = await this.stateManager.getAccount(message.caller);
}
if (!callerAccount) {
callerAccount = new Account();
}
callerAccount.nonce++;
await this.journal.putAccount(message.caller, callerAccount);
if (this.DEBUG) {
debug(`Update fromAccount (caller) nonce (-> ${callerAccount.nonce}))`);
}
}
await this._emit("beforeMessage", message);
if (!message.to && this.common.isActivatedEIP(2929)) {
message.code = message.data;
this.journal.addWarmedAddress((await this._generateAddress(message)).bytes);
}
await this.journal.checkpoint();
if (this.common.isActivatedEIP(1153)) this.transientStorage.checkpoint();
if (this.DEBUG) {
debug("-".repeat(100));
debug(`message checkpoint`);
}
let result;
if (this.DEBUG) {
const { caller, gasLimit, to, value, delegatecall } = message;
debug(
`New message caller=${caller} gasLimit=${gasLimit} to=${(to == null ? void 0 : to.toString()) ?? "none"} value=${value} delegatecall=${delegatecall ? "yes" : "no"}`
);
}
if (message.to) {
if (this.DEBUG) {
debug(`Message CALL execution (to: ${message.to})`);
}
result = await this._executeCall(message);
} else {
if (this.DEBUG) {
debug(`Message CREATE execution (to undefined)`);
}
result = await this._executeCreate(message);
}
if (this.DEBUG) {
const { executionGasUsed, exceptionError, returnValue } = result.execResult;
debug(
`Received message execResult: [ gasUsed=${executionGasUsed} exceptionError=${exceptionError ? `'${exceptionError.error}'` : "none"} returnValue=${short(returnValue)} gasRefund=${result.execResult.gasRefund ?? 0} ]`
);
}
const err = result.execResult.exceptionError;
if (err && err.error !== ERROR.CODESTORE_OUT_OF_GAS) {
result.execResult.selfdestruct = /* @__PURE__ */ new Set();
result.execResult.createdAddresses = /* @__PURE__ */ new Set();
result.execResult.gasRefund = BIGINT_0;
}
if (err && !(this.common.hardfork() === Hardfork.Chainstart && err.error === ERROR.CODESTORE_OUT_OF_GAS)) {
result.execResult.logs = [];
await this.journal.revert();
if (this.common.isActivatedEIP(1153)) this.transientStorage.revert();
if (this.DEBUG) {
debug(`message checkpoint reverted`);
}
} else {
await this.journal.commit();
if (this.common.isActivatedEIP(1153)) this.transientStorage.commit();
if (this.DEBUG) {
debug(`message checkpoint committed`);
}
}
await this._emit("afterMessage", result);
if (message.depth === 0 && ((_b = this._optsCached.profiler) == null ? void 0 : _b.enabled) === true) {
this.performanceLogger.stopTimer(timer, 0);
}
return result;
}
/**
* Bound to the global VM and therefore
* shouldn't be used directly from the evm class
*/
async runCode(opts) {
this._block = opts.block ?? defaultBlock();
this._tx = {
gasPrice: opts.gasPrice ?? BIGINT_0,
origin: opts.origin ?? opts.caller ?? createZeroAddress()
};
const message = new Message({
code: opts.code,
data: opts.data,
gasLimit: opts.gasLimit ?? BigInt(16777215),
to: opts.to ?? createZeroAddress(),
caller: opts.caller,
value: opts.value,
depth: opts.depth,
selfdestruct: opts.selfdestruct ?? /* @__PURE__ */ new Set(),
isStatic: opts.isStatic,
blobVersionedHashes: opts.blobVersionedHashes
});
return this.runInterpreter(message, { pc: opts.pc });
}
/**
* Returns code for precompile at the given address, or undefined
* if no such precompile exists.
*/
getPrecompile(address) {
return this.precompiles.get(bytesToUnprefixedHex(address.bytes));
}
/**
* Executes a precompiled contract with given data and gas limit.
*/
runPrecompile(code, data, gasLimit) {
if (typeof code !== "function") {
throw new Error("Invalid precompile");
}
const opts = {
data,
gasLimit,
common: this.common,
_EVM: this,
_debug: this.DEBUG ? debugPrecompiles : void 0,
stateManager: this.stateManager
};
return code(opts);
}
async _loadCode(message) {
if (!message.code) {
const precompile = this.getPrecompile(message.codeAddress);
if (precompile) {
message.code = precompile;
message.isCompiled = true;
} else {
message.code = await this.stateManager.getCode(message.codeAddress);
if (this.common.isActivatedEIP(7702) && equalsBytes(message.code.slice(0, 3), DELEGATION_7702_FLAG)) {
const address = new Address(message.code.slice(3, 24));
message.code = await this.stateManager.getCode(address);
if (message.depth === 0) {
this.journal.addAlwaysWarmAddress(address.toString());
}
}
message.isCompiled = false;
message.chargeCodeAccesses = true;
}
}
}
async _generateAddress(message) {
let addr;
if (message.salt) {
addr = generateAddress2(message.caller.bytes, message.salt, message.code);
} else {
let acc = await this.stateManager.getAccount(message.caller);
if (!acc) {
acc = new Account();
}
const newNonce = acc.nonce - BIGINT_1;
addr = generateAddress(message.caller.bytes, bigIntToBytes(newNonce));
}
return new Address(addr);
}
async _reduceSenderBalance(account, message) {
account.balance -= message.value;
if (account.balance < BIGINT_0) {
throw new EvmError(ERROR.INSUFFICIENT_BALANCE);
}
const result = this.journal.putAccount(message.caller, account);
if (this.DEBUG) {
debug(`Reduced sender (${message.caller}) balance (-> ${account.balance})`);
}
return result;
}
async _addToBalance(toAccount, message) {
const newBalance = toAccount.balance + message.value;
if (newBalance > MAX_INTEGER) {
throw new EvmError(ERROR.VALUE_OVERFLOW);
}
toAccount.balance = newBalance;
const result = this.journal.putAccount(message.to, toAccount);
if (this.DEBUG) {
debug(`Added toAccount (${message.to}) balance (-> ${toAccount.balance})`);
}
return result;
}
/**
* Once the interpreter has finished depth 0, a post-message cleanup should be done
*/
postMessageCleanup() {
if (this.common.isActivatedEIP(1153)) this.transientStorage.clear();
}
/**
* This method copies the EVM, current HF and EIP settings
* and returns a new EVM instance.
*
* Note: this is only a shallow copy and both EVM instances
* will point to the same underlying state DB.
*
* @returns EVM
*/
shallowCopy() {
const common2 = this.common.copy();
common2.setHardfork(this.common.hardfork());
const opts = {
...this._optsCached,
common: common2,
stateManager: this.stateManager.shallowCopy()
};
opts.stateManager.common = common2;
return new _EVM(opts);
}
getPerformanceLogs() {
return this.performanceLogger.getLogs();
}
clearPerformanceLogs() {
this.performanceLogger.clear();
}
};
_EVM.supportedHardforks = [
Hardfork.Chainstart,
Hardfork.Homestead,
Hardfork.Dao,
Hardfork.TangerineWhistle,
Hardfork.SpuriousDragon,
Hardfork.Byzantium,
Hardfork.Constantinople,
Hardfork.Petersburg,
Hardfork.Istanbul,
Hardfork.MuirGlacier,
Hardfork.Berlin,
Hardfork.London,
Hardfork.ArrowGlacier,
Hardfork.GrayGlacier,
Hardfork.MergeForkIdTransition,
Hardfork.Paris,
Hardfork.Shanghai,
Hardfork.Cancun,
Hardfork.Prague,
Hardfork.Osaka
];
let EVM = _EVM;
function OOGResult(gasLimit) {
return {
returnValue: new Uint8Array(0),
executionGasUsed: gasLimit,
exceptionError: new EvmError(ERROR.OUT_OF_GAS)
};
}
function COOGResult(gasUsedCreateCode) {
return {
returnValue: new Uint8Array(0),
executionGasUsed: gasUsedCreateCode,
exceptionError: new EvmError(ERROR.CODESTORE_OUT_OF_GAS)
};
}
function INVALID_BYTECODE_RESULT(gasLimit) {
return {
returnValue: new Uint8Array(0),
executionGasUsed: gasLimit,
exceptionError: new EvmError(ERROR.INVALID_BYTECODE_RESULT)
};
}
function CodesizeExceedsMaximumError(gasUsed) {
return {
returnValue: new Uint8Array(0),
executionGasUsed: gasUsed,
exceptionError: new EvmError(ERROR.CODESIZE_EXCEEDS_MAXIMUM)
};
}
function EvmErrorResult(error, gasUsed) {
return {
returnValue: new Uint8Array(0),
executionGasUsed: gasUsed,
exceptionError: error
};
}
function defaultBlock() {
return {
header: {
number: BIGINT_0,
coinbase: createZeroAddress(),
timestamp: BIGINT_0,
difficulty: BIGINT_0,
prevRandao: zeros(32),
gasLimit: BIGINT_0,
baseFeePerGas: void 0,
getBlobGasPrice: () => void 0
}
};
}
class OriginalStorageCache {
constructor(getStorage) {
this.map = /* @__PURE__ */ new Map();
this.getStorage = getStorage;
}
async get(address, key) {
const addressHex = bytesToUnprefixedHex(address.bytes);
const map = this.map.get(addressHex);
if (map !== void 0) {
const keyHex = bytesToUnprefixedHex(key);
const value2 = map.get(keyHex);
if (value2 !== void 0) {
return value2;
}
}
const value = await this.getStorage(address, key);
this.put(address, key, value);
return value;
}
put(address, key, value) {
const addressHex = bytesToUnprefixedHex(address.bytes);
let map = this.map.get(addressHex);
if (map === void 0) {
map = /* @__PURE__ */ new Map();
this.map.set(addressHex, map);
}
const keyHex = bytesToUnprefixedHex(key);
if (map.has(keyHex) === false) {
map.set(keyHex, value);
}
}
clear() {
this.map = /* @__PURE__ */ new Map();
}
}
async function modifyAccountFields(stateManager, address, accountFields) {
const account = await stateManager.getAccount(address) ?? new Account();
account.nonce = accountFields.nonce ?? account.nonce;
account.balance = accountFields.balance ?? account.balance;
account.storageRoot = accountFields.storageRoot ?? account.storageRoot;
account.codeHash = accountFields.codeHash ?? account.codeHash;
account.codeSize = accountFields.codeSize ?? account.codeSize;
await stateManager.putAccount(address, account);
}
class SimpleStateManager {
constructor(opts = {}) {
this.accountStack = [];
this.codeStack = [];
this.storageStack = [];
this.checkpointSync();
this.originalStorageCache = new OriginalStorageCache(this.getStorage.bind(this));
this.common = opts.common;
}
topAccountStack() {
return this.accountStack[this.accountStack.length - 1];
}
topCodeStack() {
return this.codeStack[this.codeStack.length - 1];
}
topStorageStack() {
return this.storageStack[this.storageStack.length - 1];
}
// Synchronous version of checkpoint() to allow to call from constructor
checkpointSync() {
const newTopA = new Map(this.topAccountStack());
for (const [address, account] of newTopA) {
const accountCopy = account !== void 0 ? Object.assign(Object.create(Object.getPrototypeOf(account)), account) : void 0;
newTopA.set(address, accountCopy);
}
this.accountStack.push(newTopA);
this.codeStack.push(new Map(this.topCodeStack()));
this.storageStack.push(new Map(this.topStorageStack()));
}
async getAccount(address) {
return this.topAccountStack().get(address.toString());
}
async putAccount(address, account) {
this.topAccountStack().set(address.toString(), account);
}
async deleteAccount(address) {
this.topAccountStack().set(address.toString(), void 0);
}
async modifyAccountFields(address, accountFields) {
await modifyAccountFields(this, address, accountFields);
}
async getCode(address) {
return this.topCodeStack().get(address.toString()) ?? new Uint8Array(0);
}
async putCode(address, value) {
var _a;
this.topCodeStack().set(address.toString(), value);
if (await this.getAccount(address) === void 0) {
await this.putAccount(address, new Account());
}
await this.modifyAccountFields(address, {
codeHash: (((_a = this.common) == null ? void 0 : _a.customCrypto.keccak256) ?? keccak256)(value)
});
}
async getCodeSize(address) {
const contractCode = await this.getCode(address);
return contractCode.length;
}
async getStorage(address, key) {
return this.topStorageStack().get(`${address.toString()}_${bytesToHex$1(key)}`) ?? new Uint8Array(0);
}
async putStorage(address, key, value) {
this.topStorageStack().set(`${address.toString()}_${bytesToHex$1(key)}`, value);
}
async clearStorage() {
}
async checkpoint() {
this.checkpointSync();
}
async commit() {
this.accountStack.splice(-2, 1);
this.codeStack.splice(-2, 1);
this.storageStack.splice(-2, 1);
}
async revert() {
this.accountStack.pop();
this.codeStack.pop();
this.storageStack.pop();
}
async flush() {
}
clearCaches() {
}
shallowCopy() {
const copy = new SimpleStateManager({ common: this.common });
for (let i = 0; i < this.accountStack.length; i++) {
copy.accountStack.push(new Map(this.accountStack[i]));
copy.codeStack.push(new Map(this.codeStack[i]));
copy.storageStack.push(new Map(this.storageStack[i]));
}
return copy;
}
// State root functionality not implemented
getStateRoot() {
throw new Error("Method not implemented.");
}
setStateRoot() {
throw new Error("Method not implemented.");
}
hasStateRoot() {
throw new Error("Method not implemented.");
}
}
async function createEVM(createOpts) {
const opts = createOpts ?? {};
opts.bn254 = new NobleBN254();
if (opts.common === void 0) {
opts.common = new Common({ chain: Mainnet });
}
if (opts.blockchain === void 0) {
opts.blockchain = new EVMMockBlockchain();
}
if (opts.stateManager === void 0) {
opts.stateManager = new SimpleStateManager();
}
return new EVM(opts);
}
export {
EOFContainer,
EVM,
ERROR as EVMErrorMessage,
EVMMockBlockchain,
EVMPerformanceLogger,
EvmError,
MCLBLS,
Message,
NobleBLS,
NobleBN254,
RustBN254,
Timer,
createEVM,
getActivePrecompiles,
getOpcodesForHF,
paramsEVM,
validateEOF
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment