From 200b60b09e29dc26a6c6a1fb91c4a367e0e14e4b Mon Sep 17 00:00:00 2001 From: Marvin Jones Date: Fri, 14 Aug 2026 17:07:39 -0400 Subject: [PATCH] docs(lee): correct the chain-called Deploy limitation's root cause The AccountId migration (marvin/program-as-account-3-1) fixed dispatch locating a Deploy-created PDA-addressed program, but that was never what blocked this test: the forwarder exhausts its 32M public-execution cycle budget just carrying the target bytecode through its own instruction_data before dispatch's addressing even matters. Chain-called Deploy needs a mechanism where bytecode reaches Deploy without being copied through an intermediary guest's interpreted execution, deferred to a future PR. Deploy as the top-level entry point, natively emitting its own follow-up chained calls after deploying, is the supported pattern today. --- lez/sequencer/core/src/tests.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lez/sequencer/core/src/tests.rs b/lez/sequencer/core/src/tests.rs index 4591ff144..62f38455f 100644 --- a/lez/sequencer/core/src/tests.rs +++ b/lez/sequencer/core/src/tests.rs @@ -2972,13 +2972,21 @@ fn loader_rejects_wrong_number_of_accounts() { } #[test] -#[ignore = "known limitation: the forwarding program has to carry the deployed bytecode through \ - its own instruction_data to build the chained call, which blows the interpreted \ - 32M-cycle public-execution cap for any realistically-sized program (the native \ - Deploy fast-path only covers the loader's own execution, not the caller's). Root \ - cause is ChainedCall/Message still referencing programs by ProgramId rather than \ - AccountId, which also means dispatch can't locate a Deploy-created (PDA-addressed) \ - program at all; tracked for marvin/program-as-account-3-1."] +#[ignore = "known limitation, not an addressing problem: a program that wants to chain-call \ + Deploy must carry the target bytecode through its own instruction_data to build the \ + ChainedCall, which costs ~1,400-1,500 cycles/byte of real guest interpretation and \ + blows the 32M-cycle public-execution cap for any realistically-sized program. \ + AccountId-based dispatch (marvin/program-as-account-3-1) fixed locating a \ + Deploy-created (PDA-addressed) program, but that was never the blocker here: the \ + forwarder never gets far enough to need it, since it exhausts its cycle budget just \ + carrying the bytecode through its own execution. Making an arbitrary program able to \ + decide mid-flow to deploy something new, as one step among others it orchestrates, \ + needs a mechanism where the bytecode reaches Deploy without being copied through any \ + intermediary guest's interpreted execution (e.g. a commitment carried in \ + instruction_data with the real payload resolved out-of-band by the dispatcher) — \ + deferred to a future PR. The supported pattern today is Deploy as the top-level \ + entry point, natively emitting its own follow-up chained calls after deploying \ + (see loader_deploys_program)."] fn loader_deploys_program_via_chained_call() { let loader_id: ProgramId = RESERVED_DEPLOYMENT_PROGRAM_ACCOUNT_ID.into(); let forwarder = test_programs::chained_call_forwarder();