nu-node/crates/nu-vm/src/engine.rs

100 lines
3.9 KiB
Rust

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<TxReceipt>,
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",
}
}