(instructions: Array<AuthenticationInstruction | undefined>)
| 319 | }; |
| 320 | |
| 321 | const calculateCleanupSize = (instructions: Array<AuthenticationInstruction | undefined>): number => { |
| 322 | // OP_NIP (or OP_DROP/OP_2DROP in optimised bytecode) is used for cleanup at the end of a function, |
| 323 | // OP_ENDIF and OP_ELSE are the end of branches. We need to remove all of these to get to the actual last |
| 324 | // executed instruction of a function |
| 325 | // Note that in the case where we re-add OP_1 because we cannot optimise the final explicit VERIFY into an implicit one |
| 326 | // (like when dealing with if-statements, or with CHECKLOCKTIMEVERIFY), it is impossible to run into an implicit final |
| 327 | // verify failure. That is why OP_1 does not need to be included in the cleanup opcodes. |
| 328 | // TODO: Perhaps we also do not need to add OP_DROP/OP_2DROP either, because they only occur together with OP_1 |
| 329 | const cleanupOpcodes = [Op.OP_ENDIF, Op.OP_NIP, Op.OP_ELSE, Op.OP_DROP, Op.OP_2DROP]; |
| 330 | |
| 331 | let cleanupSize = 0; |
| 332 | for (const instruction of [...instructions].reverse()) { |
| 333 | // The instructions array may contain undefined elements for the final executed debug steps that are not |
| 334 | // technically instructions (e.g. the final *implicit* verify). We still want to get rid of these in the cleanup |
| 335 | if (!instruction || cleanupOpcodes.includes(instruction.opcode)) { |
| 336 | cleanupSize++; |
| 337 | } else { |
| 338 | break; |
| 339 | } |
| 340 | } |
| 341 | |
| 342 | return cleanupSize; |
| 343 | }; |
| 344 | |
| 345 | // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 346 | const logDebugSteps = ( |
no outgoing calls
no test coverage detected