mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-08-26 20:01:16 +00:00
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>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
960bdfbb33
commit
efbd0a3563
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,14 +4,8 @@ use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use bytesize::ByteSize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Raised from the original 100 KiB to accommodate program elfs stored directly in
|
||||
/// `Account.data` under the Program-as-Account migration.
|
||||
///
|
||||
/// Observed elfs currently run 375 KB-520 KB, plus 631 KB for the fixed
|
||||
/// privacy-preserving circuit itself. This value is a rough placeholder, not a considered
|
||||
/// protocol constant yet — it still needs to be refined against real transaction/block-size
|
||||
/// budgets (e.g. `SequencerConfig::max_block_size`, currently 1 MiB) before this is something
|
||||
/// production traffic should rely on.
|
||||
/// TODO: Temporarily raised cap to 700 KiB from 100 KiB. This is a placeholder
|
||||
/// until multiple accounts are used to store the entire elf.
|
||||
pub const DATA_MAX_LENGTH: ByteSize = ByteSize::kib(700);
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, BorshSerialize)]
|
||||
|
||||
@@ -15,12 +15,8 @@ pub const MAX_NUMBER_CHAINED_CALLS: usize = 10;
|
||||
|
||||
pub type ProgramId = [u32; 8];
|
||||
|
||||
/// Derives the `AccountId` under which a program's data is stored, directly from its
|
||||
/// `ProgramId`, by reinterpreting the 8 little-endian `u32` words as 32 raw bytes.
|
||||
///
|
||||
/// A 1:1, information-preserving mapping (both types are exactly 32 bytes) rather than a
|
||||
/// hash — `ProgramId` is already content-derived (RISC0's `image_id`), so no extra domain
|
||||
/// separation is needed just to use it as a `HashMap<AccountId, Account>` key.
|
||||
/// TODO: This is a temporary conversion; will be removed once `Program` to `Account`
|
||||
/// migration is complete.
|
||||
impl From<ProgramId> for AccountId {
|
||||
fn from(program_id: ProgramId) -> Self {
|
||||
let bytes: Vec<u8> = program_id
|
||||
|
||||
@@ -113,11 +113,6 @@ impl BorshDeserialize for NullifierSet {
|
||||
pub struct V03State {
|
||||
public_state: HashMap<AccountId, Account>,
|
||||
private_state: (CommitmentSet, NullifierSet),
|
||||
/// Deployed programs, stored as `Account`s keyed by `AccountId::from(program_id)` (see that
|
||||
/// impl's doc comment) rather than by `ProgramId` directly, with the elf held in
|
||||
/// `Account.data`. Kept as its own map rather than folded into `public_state`: nothing in
|
||||
/// dispatch/execution reads or writes it, so it isn't part of the account-mutation surface
|
||||
/// `program_owner`-based authorization governs — this is host-side bookkeeping only.
|
||||
programs: HashMap<AccountId, Account>,
|
||||
}
|
||||
|
||||
@@ -324,8 +319,6 @@ impl V03State {
|
||||
let mut accounts: Vec<(&AccountId, &Account)> = public_state.iter().collect();
|
||||
accounts.sort_by(|a, b| a.0.as_ref().cmp(b.0.as_ref()));
|
||||
|
||||
// `programs` is `Account`-shaped now, same as `public_state` — reuse the identical
|
||||
// sort-then-hash-id-plus-encoded-account pattern rather than a bespoke `ProgramId` loop.
|
||||
let mut program_accounts: Vec<(&AccountId, &Account)> = programs.iter().collect();
|
||||
program_accounts.sort_by(|a, b| a.0.as_ref().cmp(b.0.as_ref()));
|
||||
|
||||
|
||||
@@ -112,11 +112,6 @@ impl ValidatedStateDiff {
|
||||
LeeError::MaxChainedCallsDepthExceeded
|
||||
);
|
||||
|
||||
// Check that the `program_id` corresponds to a deployed program. `programs` is
|
||||
// keyed by `AccountId::from(program_id)`, not `program_id` itself (see that impl's
|
||||
// doc comment), and holds the elf as a plain `Account`; reconstruct a `Program` from
|
||||
// it via `new_unchecked` to execute, skipping a redundant image-id recomputation
|
||||
// since the id/elf pairing was already validated once, at deployment time.
|
||||
let Some(program_account) = state
|
||||
.programs()
|
||||
.get(&AccountId::from(chained_call.program_id))
|
||||
|
||||
@@ -133,13 +133,13 @@ impl SeenShard {
|
||||
/// Deliveries one shard can hold before it exceeds `DATA_MAX_LENGTH`.
|
||||
///
|
||||
/// Borsh is 32 bytes of hash, a 4-byte count, then 4 bytes per index, so
|
||||
/// this is exactly the 100 KiB an account may carry.
|
||||
/// this is exactly the 700 KiB an account may carry.
|
||||
///
|
||||
/// Out of reach only because of the L1 inscription cap: a block inscribes as
|
||||
/// one op near 1.75 MiB and a minimal emitting transaction is about 257
|
||||
/// bytes, capping a peer block near 7,100 deliveries. Raising that L1 cap
|
||||
/// past roughly 6.3 MiB puts this back in reach.
|
||||
pub const MAX_DELIVERIES: usize = 25_591;
|
||||
pub const MAX_DELIVERIES: usize = 179_191;
|
||||
|
||||
/// Decodes a shard from account data; empty data is an unclaimed shard.
|
||||
pub fn from_bytes(bytes: &[u8]) -> borsh::io::Result<Self> {
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user