Skip to content

Commit

Permalink
Fix bug in init account on subchain.
Browse files Browse the repository at this point in the history
  • Loading branch information
vldm committed Feb 11, 2025
1 parent 4a8ef7c commit 4d83bb4
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 35 deletions.
20 changes: 15 additions & 5 deletions evm-utils/programs/evm_loader/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use {
pub const BURN_ADDR: evm_state::H160 = evm_state::H160::zero();

pub const SUBCHAIN_CREATION_DEPOSIT_VLX: u64 = 1_000_000;
const SUBCHAIN_MINT_ADDRESS: H160 = H160::repeat_byte(0x11);
const SUBCHAIN_MINT_ADDRESS: H160 = BURN_ADDR;

/// Return the next AccountInfo or a NotEnoughAccountKeys error
pub fn next_account_info<'a, 'b, I: Iterator<Item = &'a KeyedAccount<'b>>>(
Expand Down Expand Up @@ -1199,7 +1199,9 @@ impl EvmProcessor {
let executor = get_executor!(rc, refmut => invoke_context, subchain_id);

// Load pre-seed
executor.evm_backend.set_initial(alloc.clone());
executor
.evm_backend
.init_accounts_without_commit(alloc.clone());

for (evm_address, account) in alloc {
executor.register_swap_tx_in_evm(SUBCHAIN_MINT_ADDRESS, evm_address, account.balance);
Expand Down Expand Up @@ -1417,9 +1419,10 @@ mod test {
crate::instructions::AllocAccount,
evm::lamports_to_wei,
evm_state::{
empty_trie_hash,
transactions::{TransactionAction, TransactionSignature},
AccountProvider, AccountState, ExitReason, ExitSucceed, FromKey, BURN_GAS_PRICE,
BURN_GAS_PRICE_IN_SUBCHAIN,
AccountProvider, AccountState, ExitReason, ExitSucceed, FromKey, UnsignedTransaction,
BURN_GAS_PRICE, BURN_GAS_PRICE_IN_SUBCHAIN,
},
hex_literal::hex,
num_traits::Zero,
Expand Down Expand Up @@ -4053,6 +4056,8 @@ mod test {
tx_hash
}

// test that will deplo mint_burn mock contract and check if minting and burning work, and cannot be broken.

// 1. test that sequence of transactions will set hash after successfull processing tx
#[test]
fn subchain_finalize() {
Expand All @@ -4074,9 +4079,14 @@ mod test {

let chain_id = 0x561;
setup_chain(&mut evm_context, user_id, chain_id, config, 840000 * 3);

let root_before_init = evm_context.subchains.get(&chain_id).unwrap().last_root();
assert_eq!(root_before_init, empty_trie_hash());
// multiple finalize should not create multiple blocks
evm_context.commit_state();

let root_after_init = evm_context.subchains.get(&chain_id).unwrap().last_root();

assert_ne!(root_after_init, empty_trie_hash());
evm_context.commit_state();

let subchain_evm = evm_context.subchains.get(&chain_id).unwrap();
Expand Down
68 changes: 38 additions & 30 deletions runtime/src/bank/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use {
solana_measure::measure::Measure,
solana_program_runtime::evm_executor_context::{
BlockHashEvm, Chain, EvmBank, EvmExecutorContext, EvmExecutorContextType, PatchStrategy,
MAX_EVM_BLOCKHASHES,
StateExt, MAX_EVM_BLOCKHASHES,
},
solana_sdk::{
feature_set,
Expand All @@ -31,7 +31,23 @@ impl Bank {
evm_state::H256,
evm_state::ChangedState,
)> {
todo!()
let mut results = Vec::new();
if let Some((root, changes)) = self.evm.main_chain().changed_list().clone() {
let block = self
.evm
.main_chain()
.state()
.get_block()
.expect("Change with block");
results.push((None, block, root, changes));
}
for v in self.evm().side_chains().iter() {
if let Some((root, changes)) = v.evm_changed_list.clone() {
let block = v.state().get_block().expect("Change with block");
results.push((Some(*v.key()), block, root, changes));
}
}
results
}

pub fn evm_blocks(&self) -> Vec<(Chain, evm_state::Block)> {
Expand Down Expand Up @@ -308,10 +324,7 @@ mod evmtests {
instructions::AllocAccount, precompiles::ETH_TO_VLX_ADDR,
processor::SUBCHAIN_CREATION_DEPOSIT_VLX, scope::evm::lamports_to_wei,
},
solana_program_runtime::{
evm_executor_context::{EvmExecutorContext, StateExt},
timings::ExecuteTimings,
},
solana_program_runtime::{evm_executor_context::StateExt, timings::ExecuteTimings},
solana_sdk::{
account::ReadableAccount,
clock::MAX_PROCESSING_AGE,
Expand All @@ -321,7 +334,6 @@ mod evmtests {
pubkey::Pubkey,
transaction::{Transaction, TransactionError},
},
solana_zk_token_sdk::encryption::pedersen::H,
std::{collections::BTreeMap, sync::Arc},
};
#[allow(deprecated)]
Expand Down Expand Up @@ -851,7 +863,7 @@ mod evmtests {
let mut evm_state = bank0.evm.main_chain().state_write();
match &mut *evm_state {
evm_state::EvmState::Incomming(i) => {
i.set_initial(vec![(
i.init_accounts_without_commit(vec![(
sender_addr,
evm_state::MemoryAccount {
balance: init_balance,
Expand All @@ -861,29 +873,27 @@ mod evmtests {
}
_ => panic!("Not exepcetd state"),
}

evm_state
.try_commit(bank0.slot(), bank0.last_blockhash().to_bytes())
.unwrap();
}
let bank0 = Arc::new(bank0);
let bank1 = Bank::new_from_parent(&bank0, &solana_sdk::pubkey::new_rand(), 1);
let pubkey: evm_state::H160 = H256::random().into();
{
let evm_state = bank0.evm.main_chain().state();
let evm_state = bank1.evm.main_chain().state();
assert_eq!(
evm_state.get_account_state(sender_addr).unwrap().balance,
init_balance
);
}
info!("transfer 1 {} mint: {}", pubkey, mint_keypair.pubkey());
bank0
bank1
.transfer_evm(1_000, &mint_keypair, &sender, &pubkey)
.unwrap();

let bank0_state = bank0.hash_internal_state();
let bank0 = Arc::new(bank0);
let bank1_state = bank1.hash_internal_state();
let bank1 = Arc::new(bank1);

// Checkpointing should result in a new state while freezing the parent
let bank2 = Bank::new_from_parent(&bank0, &solana_sdk::pubkey::new_rand(), 1);
let bank2 = Bank::new_from_parent(&bank1, &solana_sdk::pubkey::new_rand(), 2);

{
let evm_state = bank2.evm.main_chain().state();
Expand All @@ -892,15 +902,15 @@ mod evmtests {
init_balance - 21000 - 1000
);
}
assert_ne!(bank0_state, bank2.hash_internal_state());
assert_ne!(bank1_state, bank2.hash_internal_state());
// Checkpointing should modify the checkpoint's state when freezed
assert_ne!(bank0_state, bank0.hash_internal_state());
assert_ne!(bank1_state, bank0.hash_internal_state());

// Checkpointing should never modify the checkpoint's state once frozen
let bank0_state = bank0.hash_internal_state();
bank2.update_accounts_hash();
assert!(bank2.verify_bank_hash(true, false));
let bank3 = Bank::new_from_parent(&bank0, &solana_sdk::pubkey::new_rand(), 2);
let bank3 = Bank::new_from_parent(&bank1, &solana_sdk::pubkey::new_rand(), 3);
assert_eq!(bank0_state, bank0.hash_internal_state());
assert!(bank2.verify_bank_hash(true, false));
bank3.update_accounts_hash();
Expand Down Expand Up @@ -939,7 +949,7 @@ mod evmtests {
let mut evm_state = bank0.evm.main_chain().state_write();
match &mut *evm_state {
evm_state::EvmState::Incomming(i) => {
i.set_initial(vec![(
i.init_accounts_without_commit(vec![(
sender_addr,
evm_state::MemoryAccount {
balance: init_balance,
Expand All @@ -949,29 +959,27 @@ mod evmtests {
}
_ => panic!("Not exepcetd state"),
}

evm_state
.try_commit(bank0.slot(), bank0.last_blockhash().to_bytes())
.unwrap();
}
let bank0 = Arc::new(bank0);
let bank1 = Bank::new_from_parent(&bank0, &solana_sdk::pubkey::new_rand(), 1);
let pubkey: evm_state::H160 = H256::random().into();
{
let evm_state = bank0.evm.main_chain().state();
let evm_state = bank1.evm.main_chain().state();
assert_eq!(
evm_state.get_account_state(sender_addr).unwrap().balance,
init_balance
);
}
info!("transfer 1 {} mint: {}", pubkey, mint_keypair.pubkey());
bank0
bank1
.transfer_evm(1_000, &mint_keypair, &sender, &pubkey)
.unwrap();
let bank0 = Arc::new(bank0);
let bank1 = Arc::new(bank1);

// Checkpointing should result in a new state while freezing the parent
let bank2 = Bank::new_from_parent(&bank0, &solana_sdk::pubkey::new_rand(), 1);
let bank2 = Bank::new_from_parent(&bank1, &solana_sdk::pubkey::new_rand(), 2);

drop(bank0);
drop(bank1);
{
let evm_state = bank2.evm.main_chain().state();
assert_eq!(
Expand Down

0 comments on commit 4d83bb4

Please sign in to comment.