Skip to content

Introduce VM macros and opcode/scanner refactor — fixes #30#40

Open
snakedye wants to merge 14 commits intomainfrom
30-macros
Open

Introduce VM macros and opcode/scanner refactor — fixes #30#40
snakedye wants to merge 14 commits intomainfrom
30-macros

Conversation

@snakedye
Copy link
Owner

@snakedye snakedye commented Mar 15, 2026

Summary

This PR brings the 30-macros branch into main and implements VM-level macros along with a substantial refactor of opcodes, the scanner, and execution logic. These changes implement the design described in #30 and add a number of ergonomics and correctness improvements to the VM.

Key changes

  • Add helm-core/src/vm/macros.rs and a macro-aware Scanner that yields Expr values. Macros supported include:
    • OP_CLONE — repeat an opcode N times
    • OP_PRAGMA / OP_ENDPRAGMA — embed a pre-encoded sequence to be re-scanned
    • OP_VERIFYSIG — convenience macro to expand the common signature verification sequence
  • Scanner now produces macro expressions and the VM flattens them before execution. This enables static sequences and small expansion-time macros (reduces repetition in common scripts).
  • Reworked opcode definitions (helm-core/src/vm/op.rs):
    • OutAmt, OutData, OutComm are now zero-argument opcodes that pop the output index at runtime (previously they carried an immediate operand).
    • Added OutCount opcode (pushes number of outputs in the tx).
    • Introduced OP_ERR, OP_VERIFYSIG, OP_PRAGMA, OP_ENDPRAGMA, OP_CLONE and associated Op variants.
    • Removed the False/True Op variants in favor of OP_PUSH_BYTE uses.
  • VM executor refactor (helm-core/src/vm/mod.rs):
    • VM accepts a flattened iterator of Op (macros are flattened before exec).
    • Added pop_stack helper to centralize stack pop + error handling.
    • Many stack-manipulating ops refactored to use pop_stack and to pop indices at runtime for Out* ops.
    • Introduced OP_ERR handling as a runtime verification error.
    • check_sig_script() now returns the OP_VERIFYSIG macro sequence.
  • Scanner implementation (helm-core/src/vm/scanner.rs) rewritten to support macros and safer byte parsing (no index arithmetic). Several new tests for macro scanning were added.
  • Updated tests across the VM and transaction modules to reflect API/behavior changes (notably: push-index-then-call for Out* ops, OP_VERIFYSIG expansion and OP_ERR expectations).
  • Minor transaction updates: imports adjusted to use the new macros and helper functions.

Migration notes

  • Call sites that previously emitted OP_OUT_AMT, OP_OUT_DATA, or OP_OUT_COMM with an immediate index must now OP_PUSH_BYTE <index> before the opcode. Example:

    • Old: [OP_OUT_AMT, 0]
    • New: [OP_PUSH_BYTE, 0, OP_OUT_AMT]
  • Code/tests that relied on OP_VERIFY as a single opcode should be updated to expect the new behaviour; OP_VERIFY is implemented as a macro expansion using OP_ERR for clearer failure semantics.

Files with major changes

  • helm-core/src/vm/macros.rs (new)
  • helm-core/src/vm/mod.rs
  • helm-core/src/vm/op.rs
  • helm-core/src/vm/scanner.rs
  • helm-core/src/transaction.rs (small import/test adjustments)

Why this helps

  • Macros reduce repetition for common instruction patterns (e.g. signature verification), reducing bytecode size and improving maintainability.
  • Moving index handling for output opcodes to runtime makes the opcodes more flexible (no immediate operand required) and simplifies the scanner.
  • Centralized pop/error handling reduces duplication and makes executor paths easier to reason about.

Request for reviewers

  • Focus areas: correctness of macro expansion (scanner), stack safety across refactored opcodes, and that the new runtime semantics for Out* opcodes are compatible with all callers.

Closes: #30

snakedye added 10 commits March 12, 2026 11:46
- Introduce `Expr` macro enum and `OpMacro` trait for macro expansion
- Add `OP_CLONE`, `OP_VERIFYSIG`, and `OP_ERR` opcodes
- Implement macro expansion for `OP_CLONE` and `OP_VERIFYSIG` in scanner
- Remove `Op::True` and `Op::False` variants; use `Op::PushByte`
- Update VM execution and tests for macro support and new opcodes
Replace OP_OUT_VERSION with OP_OUT_COUNT, which pushes the number of
outputs in the transaction. Remove all code and tests related to
OP_SELF_VERSION and OP_OUT_VERSION. Rename OP_PRAGMA_START/END to
OP_PRAGMA and OP_ENDPRAGMA for clarity.
@snakedye snakedye changed the title Resolve issue #30: Add macros (30-macros) Introduce VM macros and opcode/scanner refactor — fixes #30 Mar 15, 2026
@snakedye snakedye self-assigned this Mar 15, 2026
Repository owner deleted a comment from snakedye-pr-agent bot Mar 16, 2026
@snakedye-pr-agent
Copy link

✨ Copilot Agent Review

Summary

Details

  • PR Health: Not assessable without the diff — clarity, testing, and potential risks cannot be evaluated.
  • Linked Issues: Unable to confirm whether referenced issues are addressed; please list issue numbers and the intended resolutions.

What’s Covered

  • None verified (no PR content available to inspect).

Recommendations

  • Provide the PR patch/diff or a link with access, include CI results, unit/integration test outputs, and a summary of files changed; once available, request a full review focusing on correctness, tests, docs, and backwards compatibility.

Confidence

  • Low — unable to verify or run tests without the PR data.

The OpMacro trait has been updated to include a `dyn_clone` method. This
allows for dynamic cloning of OpMacro implementations, which is
necessary for certain macro expansions. The `Expr` enum has also been
updated to use `Box<dyn OpMacro>` for its `Iter` variant.

This change improves the flexibility and extensibility of the macro
system by allowing for more complex macro expansions.
The filter_map call was redundant as `Scanner::new(body).flatten()`
already
handles the `Op::try_from` conversion internally.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Implement VM Macro Opcodes

1 participant