(opcodes: Op[])
| 22 | |
| 23 | // Split opcodes into consecutive runs that are either all pushes or all non-pushes. |
| 24 | function groupByPushRun(opcodes: Op[]): Op[][] { |
| 25 | return opcodes.reduce<Op[][]>((opcodeRuns, opcode) => { |
| 26 | const lastOpcodeRun = opcodeRuns.at(-1); |
| 27 | |
| 28 | // If there are no runs yet, start a new run with the current opcode |
| 29 | if (!lastOpcodeRun) return [[opcode]]; |
| 30 | |
| 31 | // If the last run is the same type of opcode as the current opcode, add the current opcode to the last run |
| 32 | // Else, start a new run with the current opcode |
| 33 | if (isPushOpcode(lastOpcodeRun[0]) === isPushOpcode(opcode)) { |
| 34 | lastOpcodeRun.push(opcode); |
| 35 | } else { |
| 36 | opcodeRuns.push([opcode]); |
| 37 | } |
| 38 | |
| 39 | return opcodeRuns; |
| 40 | }, []); |
| 41 | } |
| 42 | |
| 43 | // Compute the SHA256 fingerprint of the normalized bytecode pattern, returned as hex. |
| 44 | export function computeBytecodeFingerprint(bytecode: Uint8Array): string { |
no test coverage detected