Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
776 changes: 526 additions & 250 deletions bin/evd/src/main.rs

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions bin/testapp/src/eth_eoa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ pub mod eth_eoa_account {
use evolve_collections::item::Item;
use evolve_core::{AccountId, Environment, Message, SdkResult};
use evolve_macros::{exec, init, query};
use evolve_tx_eth::address_to_account_id;
use evolve_tx_eth::TxContext;

/// An Ethereum-compatible externally owned account.
Expand Down Expand Up @@ -93,18 +92,20 @@ pub mod eth_eoa_account {
/// - Just increments nonce (test mode, no signature verification)
#[exec]
fn authenticate(&self, tx: Message, env: &mut dyn Environment) -> SdkResult<()> {
let expected_address = self.eth_address.may_get(env)?.unwrap_or([0u8; 20]);

if let Ok(sender_address) = tx.get::<[u8; 20]>() {
if sender_address != expected_address {
return Err(evolve_core::ErrorCode::new(0x51)); // Sender mismatch
}
// Fast path: validator passes sender AccountId directly.
if let Ok(sender_id) = tx.get::<AccountId>() {
let expected_address = self.eth_address.may_get(env)?.unwrap_or([0u8; 20]);
let expected_id =
address_to_account_id(alloy_primitives::Address::from(expected_address));
if sender_id != expected_id {
} else if let Ok(sender_id) = tx.get::<AccountId>() {
if sender_id != env.whoami() {
return Err(evolve_core::ErrorCode::new(0x51)); // Sender mismatch
}
// Backward-compatible fallback for older validator payloads.
} else if let Ok(mempool_tx) = tx.get::<TxContext>() {
let sender_bytes: [u8; 20] = mempool_tx.sender_address().into();
let expected_address = self.eth_address.may_get(env)?.unwrap_or([0u8; 20]);
if sender_bytes != expected_address {
return Err(evolve_core::ErrorCode::new(0x51)); // Sender mismatch
}
Expand Down
7 changes: 7 additions & 0 deletions bin/testapp/src/genesis_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use alloy_primitives::Address;
use borsh::{BorshDeserialize, BorshSerialize};
use evolve_core::AccountId;
use evolve_fungible_asset::FungibleAssetMetadata;
use evolve_node::HasTokenAccountId;
use serde::Deserialize;
use std::collections::BTreeSet;

Expand Down Expand Up @@ -37,6 +38,12 @@ pub struct EvdGenesisResult {
pub scheduler: AccountId,
}

impl HasTokenAccountId for EvdGenesisResult {
fn token_account_id(&self) -> AccountId {
self.token
}
}

impl EvdGenesisConfig {
/// Load genesis config from a JSON file.
pub fn load(path: &str) -> Result<Self, String> {
Expand Down
64 changes: 12 additions & 52 deletions bin/testapp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ use crate::eth_eoa::eth_eoa_account::{EthEoaAccount, EthEoaAccountRef};
use evolve_authentication::AuthenticationTxValidator;
use evolve_core::{AccountId, BlockContext, Environment, InvokeResponse, ReadonlyKV, SdkResult};
use evolve_fungible_asset::FungibleAssetMetadata;
use evolve_node::HasTokenAccountId;
use evolve_scheduler::scheduler_account::{Scheduler, SchedulerRef};
use evolve_scheduler::server::{SchedulerBeginBlocker, SchedulerEndBlocker};
use evolve_server::Block;
use evolve_stf::execution_state::ExecutionState;
use evolve_stf::{Stf, StorageGasConfig};
use evolve_stf_traits::{AccountsCodeStorage, PostTxExecution, WritableAccountsCodeStorage};
use evolve_token::account::{Token, TokenRef};
use evolve_tx_eth::address_to_account_id;
use evolve_tx_eth::TxContext;
use evolve_tx_eth::{register_runtime_contract_account, resolve_or_create_eoa_account};

pub const MINTER: AccountId = AccountId::new(100_002);

Expand Down Expand Up @@ -78,55 +79,11 @@ pub struct GenesisAccounts {
pub scheduler: AccountId,
}

/// Shared custom-genesis resources used by evd and testapp binaries.
#[derive(Clone, Copy, Debug)]
pub struct CustomGenesisResources {
pub alice: Option<AccountId>,
pub bob: Option<AccountId>,
pub token: AccountId,
pub scheduler: AccountId,
}

/// Initialize funded EOAs, token, and scheduler for custom genesis.
pub fn initialize_custom_genesis_resources(
funded_accounts: &[([u8; 20], u128)],
metadata: FungibleAssetMetadata,
minter: AccountId,
env: &mut dyn Environment,
) -> SdkResult<CustomGenesisResources> {
for (eth_addr, _) in funded_accounts {
EthEoaAccountRef::initialize(*eth_addr, env)?;
impl HasTokenAccountId for GenesisAccounts {
fn token_account_id(&self) -> AccountId {
self.atom
}

let balances: Vec<(AccountId, u128)> = funded_accounts
.iter()
.map(|(eth_addr, balance)| {
let addr = alloy_primitives::Address::from(*eth_addr);
(address_to_account_id(addr), *balance)
})
.collect();

let token = TokenRef::initialize(metadata, balances, Some(minter), env)?.0;

let scheduler_acc = SchedulerRef::initialize(vec![], vec![], env)?.0;
scheduler_acc.update_begin_blockers(vec![], env)?;

let alice = funded_accounts
.first()
.map(|(eth_addr, _)| address_to_account_id(alloy_primitives::Address::from(*eth_addr)));
let bob = funded_accounts
.get(1)
.map(|(eth_addr, _)| address_to_account_id(alloy_primitives::Address::from(*eth_addr)))
.or(alice);

Ok(CustomGenesisResources {
alice,
bob,
token: token.0,
scheduler: scheduler_acc.0,
})
}

fn parse_genesis_address_env(var: &str) -> Option<[u8; 20]> {
use alloy_primitives::Address;
use std::str::FromStr;
Expand Down Expand Up @@ -166,9 +123,11 @@ pub fn do_genesis_with_addresses(
env,
)?
.0;
let _atom_eth_addr = register_runtime_contract_account(atom.0, env)?;

// Create scheduler (no begin blockers needed for block info anymore)
let scheduler_acc = SchedulerRef::initialize(vec![], vec![], env)?.0;
let _scheduler_eth_addr = register_runtime_contract_account(scheduler_acc.0, env)?;

// Update scheduler's account's list.
scheduler_acc.update_begin_blockers(vec![], env)?;
Expand Down Expand Up @@ -226,10 +185,9 @@ pub fn do_eth_genesis_inner(
use alloy_primitives::Address;
use std::str::FromStr;

// Convert Ethereum addresses to AccountIds
// (accounts should already be registered in storage)
let alice_id = address_to_account_id(Address::from(alice_eth_address));
let bob_id = address_to_account_id(Address::from(bob_eth_address));
// Resolve/create canonical EOA accounts from full 20-byte ETH addresses.
let alice_id = resolve_or_create_eoa_account(Address::from(alice_eth_address), env)?;
let bob_id = resolve_or_create_eoa_account(Address::from(bob_eth_address), env)?;
let alice_balance = std::env::var("GENESIS_ALICE_TOKEN_BALANCE")
.ok()
.and_then(|v| u128::from_str(v.trim()).ok())
Expand All @@ -253,9 +211,11 @@ pub fn do_eth_genesis_inner(
env,
)?
.0;
let _evolve_eth_addr = register_runtime_contract_account(evolve.0, env)?;

// Create scheduler
let scheduler_acc = SchedulerRef::initialize(vec![], vec![], env)?.0;
let _scheduler_eth_addr = register_runtime_contract_account(scheduler_acc.0, env)?;
scheduler_acc.update_begin_blockers(vec![], env)?;

Ok(EthGenesisAccounts {
Expand Down
Loading
Loading