Repository navigation
Expand file tree
/
Copy pathlib.rs
More file actions
101 lines (93 loc) · 4.43 KB
/
Copy pathlib.rs
File metadata and controls
101 lines (93 loc) · 4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#![doc = include_str!("../README.md")]
use solana_account::{AccountFieldPatch, OwnedAccount, StateFlags};
use solana_instruction::{AccountMeta, Instruction, error::InstructionError};
use solana_pubkey::{Pubkey, declare_id};
use wincode::{SchemaRead, SchemaWrite};
declare_id!("MagicRootDRJ5atQjSJUxFjXzjeZXMADHUDznbk22gy");
/// MagicRoot rejected a conditional replacement because the account changed.
pub const ACCOUNT_CHANGED: InstructionError = InstructionError::Custom(0);
/// Trusted provenance and follow-up instructions for a finalized account.
///
/// `source_program` becomes the effective caller of each direct action. Code
/// constructing this payload must therefore verify it against authoritative
/// provenance, such as the owner in a slot-matched delegation record, before
/// submitting [`MagicRootInstruction::PostFinalize`]. It must not be copied
/// from untrusted action data. The source program need not equal the finalized
/// account's current owner because projected accounts may deliberately retain
/// a different state owner.
#[derive(Clone, SchemaRead, SchemaWrite)]
pub struct PostFinalize {
/// Verified program to expose as the effective caller of each direct action.
pub source_program: Pubkey,
/// Instructions to invoke after account finalization.
pub actions: Vec<Instruction>,
}
/// Instructions accepted by the MagicRoot built-in program.
#[derive(SchemaRead, SchemaWrite)]
pub enum MagicRootInstruction {
/// Apply one bounded account-image patch to the target account.
Patch(AccountFieldPatch),
/// Replace the target's complete flag value and, when executable, load it
/// into the transaction's program cache. Does not change lamports.
Finalize(StateFlags),
/// Close the target account and hide any cached executable immediately.
Delete,
/// Run follow-up instructions immediately after finalizing the same target
/// (e.g. initializing a freshly created account); each is invoked via CPI
/// against the accounts it declares.
PostFinalize(PostFinalize),
/// Distinguishes repeated private operations without changing account state.
Nonce(u64),
/// Applies a patch only if the complete account image still matches.
CompareAndPatch {
/// Complete image expected before mutation.
expected: OwnedAccount,
/// First replacement patch, applied after a successful comparison.
patch: AccountFieldPatch,
},
}
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) -> Result<Instruction, InstructionError> {
let mut accounts = vec![AccountMeta::new(account, false)];
self.extend_metas(&mut accounts);
let data = wincode::serialize(self).map_err(|_| InstructionError::BorshIoError)?;
Ok(Instruction { program_id: ID, accounts, data })
}
/// Composes `account` into the ordered instruction sequence that patches
/// every non-flag field on `target`, then finalizes it with `account`'s
/// complete flag value.
pub fn compose_account(
target: Pubkey,
account: OwnedAccount,
) -> Result<Vec<Instruction>, InstructionError> {
let flags = account.flags();
let patches = AccountFieldPatch::sequence(account);
let mut instructions = Vec::with_capacity(patches.len() + 1);
for patch in patches {
instructions.push(Self::Patch(patch).compose(target)?);
}
instructions.push(Self::Finalize(flags).compose(target)?);
Ok(instructions)
}
/// Appends the extra account metas a variant requires. Only [`PostFinalize`]
/// contributes any: each action's program id and accounts with signer bits
/// cleared. MagicRoot supplies the declared signers during the action's CPI.
///
/// [`PostFinalize`]: MagicRootInstruction::PostFinalize
fn extend_metas(&self, accounts: &mut Vec<AccountMeta>) {
let Self::PostFinalize(post_finalize) = self else {
return;
};
for ix in &post_finalize.actions {
accounts.push(AccountMeta::new_readonly(ix.program_id, false));
let metas = ix.accounts.iter().cloned().map(|mut meta| {
meta.is_signer = false;
meta
});
accounts.extend(metas)
}
}
}