use nu_block::types::{Block, RawTransaction, TxPayload, TxReceipt}; use nu_state::StateAccessor; use crate::executor::{ execute_node_approve, execute_node_reject, execute_node_submit, execute_stake_op, execute_token_transfer, execute_validator_register, execute_vote_cast, execute_vote_register, execute_voting_open, ExecutionContext, }; pub struct BlockResult { pub receipts: Vec, pub applied: u32, pub failed: u32, } pub fn execute_block(block: &Block, state: &dyn StateAccessor, now_ms: i64) -> BlockResult { let dev_wallet = std::env::var("DEV_WALLET") .unwrap_or_else(|_| "0xDEV0000000000000000000000000000000000000".to_string()); let mut receipts = Vec::with_capacity(block.transactions.len()); let mut applied = 0u32; let mut failed = 0u32; for tx in &block.transactions { let receipt = execute_tx(tx, state, block.header.height, now_ms, &dev_wallet); if receipt.success { applied += 1; } else { failed += 1; } receipts.push(receipt); } BlockResult { receipts, applied, failed } } fn execute_tx( tx: &RawTransaction, state: &dyn StateAccessor, block_height: u64, now_ms: i64, dev_wallet: &str, ) -> TxReceipt { let ctx = ExecutionContext { state, block_height, now_ms }; let result = match &tx.payload { TxPayload::TokenTransfer { to, amount } => { execute_token_transfer(&ctx, &tx.sender, to, *amount, tx.fee, tx.nonce) } TxPayload::NodeSubmit { story_id, parent_node_id, content_hash, temp_id, entry_fee: _ } => { execute_node_submit(&ctx, &tx.sender, tx.nonce, tx.fee, story_id, parent_node_id, content_hash, temp_id) } TxPayload::VoteRegister { node_id, stake_lock: _ } => { execute_vote_register(&ctx, &tx.sender, tx.nonce, tx.fee, node_id) } TxPayload::VoteCast { node_id, approve } => { execute_vote_cast(&ctx, &tx.sender, tx.nonce, tx.fee, node_id, *approve) } TxPayload::StakeOp { stake, amount } => { execute_stake_op(&ctx, &tx.sender, tx.nonce, tx.fee, *stake, *amount) } TxPayload::ValidatorRegister { stake } => { execute_validator_register(&ctx, &tx.sender, tx.nonce, tx.fee, *stake) } TxPayload::VotingOpen { node_id } => { execute_voting_open(&ctx, node_id) } TxPayload::NodeApprove { temp_id, canonical_id } => { execute_node_approve(&ctx, temp_id, canonical_id, dev_wallet) } TxPayload::NodeReject { node_id } => { execute_node_reject(&ctx, node_id) } // Faz 2 later TxPayload::NftMint { .. } | TxPayload::NftTransfer { .. } | TxPayload::CollectionClaim { .. } => { Err(crate::errors::VmError::Unknown(format!("{} not yet implemented", payload_name(&tx.payload)))) } }; match result { Ok(()) => TxReceipt { tx_id: tx.tx_id.clone(), success: true, error: String::new() }, Err(e) => TxReceipt { tx_id: tx.tx_id.clone(), success: false, error: e.to_string() }, } } fn payload_name(payload: &TxPayload) -> &'static str { match payload { TxPayload::TokenTransfer { .. } => "TokenTransfer", TxPayload::NodeSubmit { .. } => "NodeSubmit", TxPayload::VoteRegister { .. } => "VoteRegister", TxPayload::VoteCast { .. } => "VoteCast", TxPayload::NftTransfer { .. } => "NftTransfer", TxPayload::CollectionClaim { .. } => "CollectionClaim", TxPayload::StakeOp { .. } => "StakeOp", TxPayload::ValidatorRegister { .. } => "ValidatorRegister", TxPayload::NodeApprove { .. } => "NodeApprove", TxPayload::NftMint { .. } => "NftMint", TxPayload::NodeReject { .. } => "NodeReject", TxPayload::VotingOpen { .. } => "VotingOpen", } }