Files
logos-execution-zone/integration_tests/tests/program_deployment.rs
T
Marvin JonesandClaude Sonnet 5 ed61107f1c refactor(lee): unify program dispatch/bijection addresses, fix downstream bugs
Programs dispatch at the address seeded via with_programs/a live Deploy
(loader_core::immutable_deploy_account_id), not the bijection
AccountId::from(program_id) used by the legacy ProgramDeploymentTransaction
storage shape. This sweep threads the correct address through
lee/lez/integration_tests/wallet-ffi call sites and fixes 7 dispatch-address
bugs the mismatch was masking: bijection-vs-real-PDA mismatches in
lez/wallet's native_token_transfer facade, integration_tests'
auth_transfer/private and private_pda suites, wallet-ffi's
generic_transaction FFI boundary, a stale assertion in program_deployment.rs,
and a stale expected-error string in cross_zone_state_machine.rs.

Also includes a full clippy/fmt pass: doc-comment reflow, #[expect(...)]
attribute additions, redundant type-annotation/unused-import removal, and
two assert!s added purely for bounds-check elision on already-guarded
slices — no logic changes. Both CI clippy invocations and cargo fmt --check
are clean.

Verified: RISC0_DEV_MODE=1 cargo test -p lee --lib (214 passed) and the
broader sanity set across lee/wallet/bridge_lock_core/ping_core/
cross_zone_outbox_core/sequencer_core (mock features) both green.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 21:14:21 -04:00

112 lines
3.8 KiB
Rust

#![expect(
clippy::tests_outside_test_module,
reason = "We don't care about these in tests"
)]
use std::{io::Write as _, time::Duration};
use anyhow::Result;
use common::transaction::LeeTransaction;
use integration_tests::{TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, get_account, new_account};
use sequencer_service_rpc::RpcClient as _;
use test_fixtures::{
MultiZoneTestContextBuilder, ZoneTestContextBuilder, config::MultiNodeTestContextConfig,
};
use tokio::test;
use wallet::{cli::Command, config::WalletConfigOverrides};
#[test]
async fn deploy_and_execute_program() -> Result<()> {
let mut ctx = TestContext::new().await?;
let claimer = test_programs::claimer();
let mut tempfile = tempfile::NamedTempFile::new()?;
tempfile.write_all(claimer.elf())?;
let binary_filepath = tempfile.path().to_owned();
let command = Command::DeployProgram {
binary_filepath: binary_filepath.clone(),
};
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
let account_id = new_account(&mut ctx, false, None).await?;
let nonces = ctx.wallet_mut().get_accounts_nonces(&[account_id]).await?;
let private_key = ctx
.wallet()
.get_account_public_signing_key(account_id)
.unwrap();
let message = lee::public_transaction::Message::try_new(
program_loader_core::immutable_deploy_account_id(claimer.id()),
vec![account_id],
nonces,
(),
)?;
let witness_set = lee::public_transaction::WitnessSet::for_message(&message, &[private_key]);
let transaction = lee::PublicTransaction::new(message, witness_set);
let _response = ctx
.sequencer_client()
.send_transaction(LeeTransaction::Public(transaction))
.await?;
log::info!("Waiting for next block creation");
// Waiting for long time as it may take some time for such a big transaction to be included in a
// block
tokio::time::sleep(Duration::from_secs(2 * TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
let post_state_account = get_account(&ctx, account_id).await?;
let expected_data: &[u8] = &[];
assert_eq!(
post_state_account.program_owner,
program_loader_core::immutable_deploy_account_id(claimer.id())
);
assert_eq!(post_state_account.balance, 0);
assert_eq!(post_state_account.data.as_ref(), expected_data);
assert_eq!(post_state_account.nonce.0, 1);
log::info!("Successfully deployed and executed program");
Ok(())
}
#[test]
async fn deploy_invalid_program_fails() -> Result<()> {
// An invalid program bytecode is rejected by the sequencer during block production, so the
// deployment transaction is never included in a block. Shrink the wallet's polling window so
// the command gives up quickly instead of waiting for the full default timeout.
let mut ctx = MultiZoneTestContextBuilder::default()
.with_zone(
ZoneTestContextBuilder::new(MultiNodeTestContextConfig::default())
.with_wallet_config_overrides(WalletConfigOverrides {
seq_poll_timeout: Some(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)),
seq_tx_poll_max_blocks: Some(5),
seq_poll_max_retries: Some(2),
..WalletConfigOverrides::default()
}),
)
.build()
.await?;
let mut tempfile = tempfile::NamedTempFile::new()?;
tempfile.write_all(b"this is not a valid program binary")?;
let command = Command::DeployProgram {
binary_filepath: tempfile.path().to_owned(),
};
let result = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await;
assert!(
result.is_err(),
"Deploying an invalid program should fail, but got: {result:?}"
);
log::info!("Deploying an invalid program failed as expected");
Ok(())
}