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.
This commit is contained in:
Marvin Jones
2026-08-14 17:07:39 -04:00
parent 8c0dffd075
commit 200b60b09e
+15 -7
View File
@@ -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();