mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-08-27 12:21:17 +00:00
* feat(lee): store deployed programs as Account-shaped state, keyed by AccountId Program-as-Account migration, first slice: V03State.programs becomes HashMap<AccountId, Account> instead of HashMap<ProgramId, Program>, with the elf held directly in Account.data. The map key is derived from ProgramId via a new 1:1 From<ProgramId> for AccountId conversion (both types are exactly 32 bytes) rather than a hash, since ProgramId is already content-derived from the elf. Account.program_owner stays ProgramId-typed everywhere - this only changes how deployed programs are stored and looked up host-side, not the dispatch/authorization model any guest program logic depends on. Dispatch resolves a ChainedCall's program_id by converting to AccountId, fetching the Account, and reconstructing a Program via new_unchecked for execution. DATA_MAX_LENGTH is raised from 100 KiB to 700 KiB to fit real program elfs (observed 375 KB-631 KB) directly in Account.data; noted in its docstring as a rough placeholder pending real transaction/block-size budget analysis. * fix(lee): store deployed programs as Account-shaped state, correct SeenShard cap Corrects lee/state_machine internals for the Program-as-Account migration and fixes SeenShard::MAX_DELIVERIES, which was still calibrated for the old 100 KiB DATA_MAX_LENGTH instead of the current 700 KiB cap. Rebuilds program artifacts and the sequencer test fixture to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * address PR #720 review nits - Use FIXME instead of TODO for the temporary ProgramId->AccountId conversion, per review convention for patches guaranteed to be fixed later. - Derive cross_zone_inbox's MAX_DELIVERIES from DATA_MAX_LENGTH instead of a hand-recomputed literal, so it stays in sync automatically the next time the cap changes. * feat(lee): migrate Account.program_owner from ProgramId to AccountId Account.program_owner is now AccountId-typed instead of ProgramId, via a new bijective From<ProgramId> for AccountId / From<AccountId> for ProgramId conversion pair (pure byte reinterpretation, not a hash - both types are exactly 32 bytes). Adds DEFAULT_PROGRAM_OWNER as the AccountId-typed counterpart to DEFAULT_PROGRAM_ID, used at every program_owner comparison/claim site instead of an inline AccountId::default(). Touches every call site across lee_core, lee (including the guest-side privacy-preserving circuit), all 16 deployed guest programs, wallet/wallet-ffi, indexer_ffi/indexer_service/ indexer_service_protocol, sequencer_core, testnet_initial_state, system_accounts, cross_zone, storage, cycle_bench, and integration_tests - mostly mechanical .into() conversions, plus two simplifications: wallet's manual base58 encode/decode of program_owner was dead code once it's AccountId (which already has Display/FromStr), and the FFI crates' program_owner field now reuses the existing generic FfiBytes32 wrapper instead of the now-unused FfiProgramId one. Rebuilds every guest ELF artifact and the prebuilt sequencer test fixture via just build-artifacts, since execute_and_prove runs against the checked-in precompiled privacy_preserving_circuit.bin, which isn't rebuilt automatically by cargo test/check. * chore(lee): rebuild artifacts after rebase, drop unused base58 dep Rebases marvin/program-as-account-2 onto the updated marvin/program-as-account (SeenShard cap fix), regenerating program and circuit artifacts plus the sequencer test fixture to match. Also removes lez/wallet's now-unused base58 dependency, dead since AccountId gained its own Display/FromStr base58 encoding. * docs(lee): trim DEFAULT_PROGRAM_OWNER and From<AccountId> for ProgramId docs * test(lee): add known-answer tests for ProgramId/AccountId conversion, rebuild artifacts * fix(lee): apply program_owner AccountId migration to code added after rebase dev grew new program_owner call sites (sequencer_stake genesis/config handling, committee_discovery, a new selective_pda_delegator test program, and related tests) after this branch's ProgramId->AccountId migration commit was originally written, so they predated the .into() sweep and didn't conflict during the rebase - they just still assumed the old ProgramId-typed field. Converts all of them, fixes a stray unseparated hex literal clippy caught along the way, and rebuilds artifacts against the fixed source. * chore(lee): regenerate test fixture after rebasing onto dev --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
100 lines
3.1 KiB
Rust
100 lines
3.1 KiB
Rust
use authenticated_transfer_core::Instruction;
|
|
use lee_core::{
|
|
account::{Account, AccountWithMetadata},
|
|
program::{
|
|
AccountPostState, Claim, DEFAULT_PROGRAM_OWNER, ProgramInput, ProgramOutput,
|
|
read_lee_inputs,
|
|
},
|
|
};
|
|
|
|
/// Initializes a default account under the ownership of this program.
|
|
fn initialize_account(pre_state: AccountWithMetadata) -> AccountPostState {
|
|
let account_to_claim = AccountPostState::new_claimed(pre_state.account, Claim::Authorized);
|
|
|
|
// Continue only if the account to claim has default values
|
|
assert!(
|
|
account_to_claim.account() == &Account::default(),
|
|
"Account must be uninitialized"
|
|
);
|
|
|
|
account_to_claim
|
|
}
|
|
|
|
/// Transfers `balance_to_move` native balance from `sender` to `recipient`.
|
|
fn transfer(
|
|
sender: AccountWithMetadata,
|
|
recipient: AccountWithMetadata,
|
|
balance_to_move: u128,
|
|
) -> Vec<AccountPostState> {
|
|
// Continue only if the sender has authorized this operation.
|
|
assert!(sender.is_authorized, "Sender must be authorized");
|
|
|
|
// Create accounts post states, with updated balances
|
|
let sender_post = {
|
|
// Modify sender's balance
|
|
let mut sender_post_account = sender.account;
|
|
sender_post_account.balance = sender_post_account
|
|
.balance
|
|
.checked_sub(balance_to_move)
|
|
.expect("Sender has insufficient balance");
|
|
AccountPostState::new(sender_post_account)
|
|
};
|
|
|
|
let recipient_post = {
|
|
// Modify recipient's balance
|
|
let mut recipient_post_account = recipient.account;
|
|
recipient_post_account.balance = recipient_post_account
|
|
.balance
|
|
.checked_add(balance_to_move)
|
|
.expect("Recipient balance overflow");
|
|
|
|
// Claim recipient account if it has default program owner
|
|
if recipient_post_account.program_owner == DEFAULT_PROGRAM_OWNER {
|
|
AccountPostState::new_claimed(recipient_post_account, Claim::Authorized)
|
|
} else {
|
|
AccountPostState::new(recipient_post_account)
|
|
}
|
|
};
|
|
|
|
vec![sender_post, recipient_post]
|
|
}
|
|
|
|
/// A transfer of balance program.
|
|
/// To be used both in public and private contexts.
|
|
fn main() {
|
|
// Read input accounts.
|
|
let (
|
|
ProgramInput {
|
|
self_program_id,
|
|
caller_program_id,
|
|
pre_states,
|
|
instruction,
|
|
},
|
|
instruction_words,
|
|
) = read_lee_inputs::<Instruction>();
|
|
|
|
let post_states = match instruction {
|
|
Instruction::Initialize => {
|
|
let [account_to_claim] = <[_; 1]>::try_from(pre_states.clone())
|
|
.expect("Initialize requires exactly 1 account");
|
|
vec![initialize_account(account_to_claim)]
|
|
}
|
|
Instruction::Transfer {
|
|
amount: balance_to_move,
|
|
} => {
|
|
let [sender, recipient] = <[_; 2]>::try_from(pre_states.clone())
|
|
.expect("Transfer requires exactly 2 accounts");
|
|
transfer(sender, recipient, balance_to_move)
|
|
}
|
|
};
|
|
|
|
ProgramOutput::new(
|
|
self_program_id,
|
|
caller_program_id,
|
|
instruction_words,
|
|
pre_states,
|
|
post_states,
|
|
)
|
|
.write();
|
|
}
|