Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions programs/magic-root-interface/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
authors.workspace = true
edition.workspace = true
homepage.workspace = true
license.workspace = true
name = "magic-root-interface"
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[dependencies]
wincode = { workspace = true }

solana-account = { workspace = true, features = ["wincode"] }
solana-instruction = { workspace = true }
solana-pubkey = { workspace = true }


[lints]
workspace = true
12 changes: 12 additions & 0 deletions programs/magic-root-interface/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# `magic-root-interface`

A caller that wants to build a MagicRoot instruction shouldn't have to depend on
the program that *executes* it. This crate is the seam that makes that possible:
it holds the instruction schema (`MagicRootInstruction`) shared between
`magic-root-program` and `engine`, so the builder side and the execution side
agree on the wire format without the builder pulling in execution logic.

`compose` assembles an instruction: it prepends the target-account meta and
serializes the instruction data. Only `PostFinalize` adds anything beyond that —
it contributes extra metas for each follow-up (the follow-up's program id and its
accounts, with their signer bits cleared).
55 changes: 55 additions & 0 deletions programs/magic-root-interface/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#![doc = include_str!("../README.md")]

use solana_account::AccountFieldPatch;
use solana_instruction::{AccountMeta, Instruction};
use solana_pubkey::{Pubkey, declare_id};
use wincode::{SchemaRead, SchemaWrite};

declare_id!("MagicRootDRJ5atQjSJUxFjXzjeZXMADHUDznbk22gy");

/// Instructions accepted by the MagicRoot built-in program.
#[derive(SchemaRead, SchemaWrite)]
pub enum MagicRootInstruction {
/// Apply a single-field patch to the target account.
Patch(AccountFieldPatch),
/// Finalize the target account: drain its lamports back to the payer and,
/// if it is executable, load it into the transaction's program cache.
Finalize,
/// Close the target account.
Delete,
/// Run follow-up instructions once the account is finalized (e.g.
/// initializing a freshly created account); each is invoked via CPI against
/// the accounts it declares.
PostFinalize(Vec<Instruction>),
}

impl MagicRootInstruction {
/// Composes this variant into an [`Instruction`] targeting the MagicRoot
/// program: prepends the target `account` meta, appends any metas the
/// variant requires, and serializes the instruction data.
pub fn compose(&self, account: Pubkey) -> wincode::Result<Instruction> {
let mut accounts = vec![AccountMeta::new(account, false)];
self.extend_metas(&mut accounts);
let data = wincode::serialize(self)?;
Ok(Instruction { program_id: ID, accounts, data })
}

/// Appends the extra account metas a variant requires. Only [`PostFinalize`]
/// contributes any: the program id and de-signed accounts of each follow-up
/// instruction.
///
/// [`PostFinalize`]: MagicRootInstruction::PostFinalize
fn extend_metas(&self, accounts: &mut Vec<AccountMeta>) {
let Self::PostFinalize(ixs) = self else {
return;
};
for ix in ixs {
accounts.push(AccountMeta::new_readonly(ix.program_id, false));
let metas = ix.accounts.clone().into_iter().map(|mut meta| {
meta.is_signer = false;
meta
});
accounts.extend(metas)
}
}
}
26 changes: 26 additions & 0 deletions programs/magic-root-program/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "magic-root-program"

authors.workspace = true
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[dependencies]
magic-root-interface = { workspace = true }

nucleus = { workspace = true, features = ["tls"] }
wincode = { workspace = true }

solana-account = { workspace = true }
solana-instruction = { workspace = true }
solana-instruction-error = { workspace = true }
solana-program-runtime = { workspace = true }
solana-svm-log-collector = { workspace = true }
solana-transaction-context = { workspace = true }

[lints]
workspace = true
25 changes: 25 additions & 0 deletions programs/magic-root-program/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# `magic-root-program`

Some account changes are ones no ordinary on-chain program is ever allowed to
make: patching arbitrary account fields, finalizing, closing an account outright.
The engine still needs to make them, so it has a built-in program that *can* —
this one. It's the privileged escape hatch, wired in as `MagicRootEntrypoint`,
with its instruction schema defined in `nucleus::runtime` and its execution logic
here.

Because it's unrestricted, it has to be locked down by authority instead of by
capability. Every instruction must be **top-level** (no CPI can reach it) and
**signed by `AUTHORITY`**, and both checks run *before any account is touched* —
so an unauthorized call can't have side effects on its way to being rejected.

## Instructions

- `Patch` — writes a single account field. Patching lamports settles the delta
against the authority (the payer) so total supply stays conserved and
re-patching the same balance is a no-op — an in-place `update` therefore does
not drain the authority again.
- `Finalize` — loads executable targets into the transaction's program cache.
Balances are already settled at patch time, so it no longer touches lamports.
- `Delete` — sets the target to `AccountMode::Closed`.
- `PostFinalize` — CPIs into follow-up instructions, after rejecting any account
that is immutable but marked writable.
161 changes: 161 additions & 0 deletions programs/magic-root-program/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#![doc = include_str!("../README.md")]

use magic_root_interface::MagicRootInstruction;
use nucleus::tls::AUTHORITY;
use solana_account::{AccountFieldPatch, AccountMode, ReadableAccount, WritableAccount};
use solana_instruction::{Instruction, TRANSACTION_LEVEL_STACK_HEIGHT};
use solana_instruction_error::InstructionError;
use solana_program_runtime::{invoke_context::InvokeContext, loaded_programs::ProgramCacheEntry};
use solana_svm_log_collector::ic_msg;
use solana_transaction_context::IndexOfAccount;

/// Instruction-account index of the account a MagicRoot instruction operates on.
pub const TARGET_ACCOUNT_IDX: u16 = 0;

/// Executes a MagicRoot instruction: authorizes the caller, decodes the
/// instruction, then applies it to the target account.
pub fn process(ctx: &mut InvokeContext<'_, '_>) -> Result<(), InstructionError> {
authorize(ctx)?;
let ix = decode(ctx)?;
apply(ctx, ix)
}

/// Rejects CPI invocations and callers other than the configured [`AUTHORITY`].
///
/// MagicRoot is engine-internal: it must run as a top-level instruction signed
/// by the authority, both checked before any account is touched.
fn authorize(ctx: &InvokeContext<'_, '_>) -> Result<(), InstructionError> {
let height = ctx.get_stack_height();
if height != TRANSACTION_LEVEL_STACK_HEIGHT {
ic_msg!(ctx, "MagicRoot: CPI denied (height {})", height);
return Err(InstructionError::CallDepth);
}
let signer = *ctx.transaction_context.get_key_of_account_at_index(0)?;
if signer != AUTHORITY.get() {
ic_msg!(ctx, "MagicRoot: unauthorized signer {}", signer);
return Err(InstructionError::MissingRequiredSignature);
}
Ok(())
}

/// Decodes the current instruction's data into a [`MagicRootInstruction`].
fn decode(ctx: &InvokeContext<'_, '_>) -> Result<MagicRootInstruction, InstructionError> {
let ixctx = ctx.transaction_context.get_current_instruction_context()?;
let data = ixctx.get_instruction_data();
wincode::deserialize(data).map_err(|_| {
ic_msg!(ctx, "MagicRoot: malformed instruction data");
InstructionError::InvalidInstructionData
})
}

/// Resolves the target account index and dispatches to the matching handler.
fn apply(
ctx: &mut InvokeContext<'_, '_>,
ix: MagicRootInstruction,
) -> Result<(), InstructionError> {
let ixctx = ctx.transaction_context.get_current_instruction_context()?;
let idx = ixctx.get_index_of_instruction_account_in_transaction(TARGET_ACCOUNT_IDX)?;
match ix {
MagicRootInstruction::Patch(patch) => patch_account(ctx, idx, patch),
MagicRootInstruction::Finalize => finalize_account(ctx, idx),
MagicRootInstruction::Delete => delete_account(ctx, idx),
MagicRootInstruction::PostFinalize(actions) => post_finalize(ctx, actions),
}
}

/// Applies a single-field patch to the target account.
fn patch_account(
ctx: &InvokeContext<'_, '_>,
idx: IndexOfAccount,
patch: AccountFieldPatch,
) -> Result<(), InstructionError> {
let mut account = ctx.transaction_context.accounts().try_borrow_mut(idx)?;
ic_msg!(ctx, "MagicRoot: patch {:?}", patch);
let old = account.lamports();
patch.apply(&mut account);
let new = account.lamports();
let mut authority = ctx.transaction_context.accounts().try_borrow_mut(0)?;
if new > old {
authority.checked_sub_lamports(new - old)?;
} else if new < old {
authority.checked_add_lamports(old - new)?;
}
Ok(())
}

/// Loads an executable target into the transaction's program cache.
fn finalize_account(
ctx: &mut InvokeContext<'_, '_>,
idx: IndexOfAccount,
) -> Result<(), InstructionError> {
let account = ctx.transaction_context.accounts().try_borrow(idx)?;
if !account.executable() {
return Ok(());
}
let pubkey = *ctx.transaction_context.get_key_of_account_at_index(idx)?;
let entry = ProgramCacheEntry::new(
ctx.environment_config
.program_runtime_environments_for_execution
.get_env_for_execution()
.clone(),
account.data(),
)
.map_err(|_| {
ic_msg!(ctx, "MagicRoot: program load failed {}", pubkey);
InstructionError::ProgramEnvironmentSetupFailure
})?
.into();
ctx.program_cache_for_tx_batch.store_modified_entry(pubkey, entry);
ic_msg!(ctx, "MagicRoot: finalized program load");
Ok(())
}

/// Marks the target account closed for removal from storage.
fn delete_account(
ctx: &InvokeContext<'_, '_>,
idx: IndexOfAccount,
) -> Result<(), InstructionError> {
ctx.transaction_context
.accounts()
.try_borrow_mut(idx)?
.set_mode(AccountMode::Closed);
ic_msg!(ctx, "MagicRoot: removed");
Ok(())
}

/// Runs the post-finalize follow-up instructions: rejects any writable
/// instruction account that is not mutable, then invokes each action via CPI,
/// forwarding the signers declared across the actions.
fn post_finalize(
ctx: &mut InvokeContext<'_, '_>,
actions: Vec<Instruction>,
) -> Result<(), InstructionError> {
ic_msg!(ctx, "MagicRoot: post-finalize {} action(s)", actions.len());
let ixctx = ctx.transaction_context.get_current_instruction_context()?;
let count = ixctx.get_number_of_instruction_accounts();
for i in 0..count {
let idx = ixctx.get_index_of_instruction_account_in_transaction(i)?;
let acc = ctx.transaction_context.accounts().try_borrow(idx)?;
if ixctx.is_instruction_account_writable(i)? && !acc.mutable() {
ic_msg!(
ctx,
"MagicRoot: post-finalize rejected immutable writable account"
);
return Err(InstructionError::Immutable);
}
}
let signers: Vec<_> = actions
.iter()
.flat_map(|ix| ix.accounts.iter().filter_map(|m| m.is_signer.then_some(m.pubkey)))
.collect();
for action in actions {
ctx.native_invoke(action, &signers)?;
}
Ok(())
}

#[allow(missing_docs)]
pub mod entrypoint {
use solana_program_runtime::declare_process_instruction;
declare_process_instruction!(MagicRootEntrypoint, 150, |ctx| { super::process(ctx) });
}
22 changes: 22 additions & 0 deletions programs/v42-calculator-interface/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "v42-calculator-interface"

authors.workspace = true
# Compiled to BPF as the program's opcode dependency, so it stays within the
# SBF toolchain's rustc: edition 2021 and no elevated workspace MSRV.
edition = "2021"
homepage.workspace = true
license.workspace = true
repository.workspace = true
version.workspace = true

[dependencies]
solana-instruction = { workspace = true, optional = true }
solana-pubkey = { workspace = true }

[features]
builder = ["dep:solana-instruction"]
default = ["builder"]

[lints]
workspace = true
26 changes: 26 additions & 0 deletions programs/v42-calculator-interface/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# `v42-calculator-interface`

Client side of the `v42-calculator` test program: the program id, the RPN wire
format (`opcodes`), and [`Expr`](crate::builder::Expr) — a small builder for
turning ordinary arithmetic into calculator instructions. A test that wants to
*generate* a transaction depends only on this crate; it never pulls in the
on-chain program.

The calculator evaluates a postfix (RPN) byte stream against a `u64` stack.
`Expr` hides that: leaves are literals (`lit`), account operands (`acc`), and
the `Clock` sysvar (`clock`); the `+ - * /` operators combine subexpressions, and
`.cpi()` marks a subexpression to be evaluated by a recursive self-CPI instead
of inline — useful for exercising CPI depth and the return-data path. Because
the builder keeps each subexpression already in postfix order, composition is
pure concatenation with no intermediate tree.

`compose` assembles the instruction: account 0 is the writable output that
receives the final result (LE `u64`); the read-only operands follow and are
addressed by `Expr::acc` (starting at index 1). The calculator program id is
appended as a final read-only account so recursive CPI has its callee account in
scope without shifting operand indices.

The opcode table lives in `opcodes` and is the single source of truth for the
wire format — the on-chain program depends on this crate with the `builder`
feature off, taking only those constants. Composing transactions needs the
`builder` feature (on by default).
Loading