OP_EXEC
Execute a script that is provided as stack data
Syntax and Stack
code param1...paramN N_Params M_Returns OP_EXEC => ret1..retN?
- code: The subscript to be executed
- param1...paramN: These stack items are moved to the subscript's stack
- N_Params: The number of stack items (params) to move.
- M_Returns: The number of items to copy from the subscript's stack.
Binary representation
OP_EXEC is defined as the single byte 0xed.
Operation
OP_EXEC executes a subscript that is presented as data in a script. This subscript is executed in an isolated stack environment -- it can neither read nor modify elements on the main or alt stacks. Any illegal operation fails validation of the entire script (T.o1). A zero length stack element is a valid script (that does nothing) (T.o2). As with any scripts, any pops of an empty subscript stack fail, which fails the entire script (T.o3).
Operation proceeds as follows:
- M_Returns and N_Params are popped from the stack.
- Param1..ParamN (N total items, N>=0) are popped from the stack and copied to the subscript stack, in the same order.
- code is popped from the stack.
- code is executed
- M items (M>=0) are popped from the subscript stack and pushed onto the main stack, maintaining the same order.
Note that implementations MUST manage the stack as specified to ensure that when the subscript is executed all implementations have a consistent available stack space (T.o4).
Limits
T.L1: The number of items in every in-use stack MUST never exceed the maximum stack size consensus parameter. Put another way, the execution of the entire program, including every subscript must "fit" in the existing stack and altstack.
T.L2: Operations in subscripts MUST count toward all consensus limits (eg number of operations and sigchecks).
T.L3: OP_EXEC MUST fail validation if called recursively more than MAX_EXEC_DEPTH = 3 times. This number may be increased so script authors MUST not rely on this rule to fail script validation.
T.L4: OP_EXEC MUST fail validation if called more than MAX_OP_EXEC = 20 times in total, including calls executed by subscripts. This number may be increased so script authors MUST not rely on this rule to fail script validation.
Implementation notes
Note that a space-efficient implementation does not need to recursively start another script machine instance with new stack objects. It can execute the subscript on the existing main and altstack, with the addition of a barrier to ensure that the subscript does not access (read, write, or pop) more than the provided N params.
Design considerations
In Bitcoin validation, the 3 script sources (template, constraint, and satisfier?) are antagonistic -- the satisfier script author seeks to spend in any way (including exploiting bugs in the constraint and template scripts). The constraint script author seeks to add constraints to and/or prevent permissions (code paths) offered by the template script.
The satisfier and constraint scripts may be providing code that is executed with OP_EXEC. It is therefore important that this code executes on an isolated stack. Otherwise, for example, a constraint script could be written that manipulates portions of the stack beyond what is intended. For example, it could change values provided by the satisfier script to prevent the satisfier from executing code paths in the template.