Documentation Index
Fetch the complete documentation index at: https://mintlify.com/lanelayer/core-lane/llms.txt
Use this file to discover all available pages before exploring further.
The execute_transaction() function processes Core Lane transactions, validating signatures, nonces, and balances before applying state changes.
Basic Execution
use core_lane::{
execute_transaction, TxEnvelope, Address,
BundleStateManager, CoreLaneStateForLib, StateManager
};
use anyhow::Result;
fn process_transaction(
tx: &TxEnvelope,
sender: Address,
state: &mut CoreLaneStateForLib,
) -> Result<()> {
let mut bundle = BundleStateManager::new();
let block_timestamp = 1704067200; // Unix timestamp
let result = execute_transaction(
tx,
sender,
&mut bundle,
state,
block_timestamp
)?;
if result.success {
println!("Transaction succeeded!");
println!("Gas used: {}", result.gas_used);
// Apply changes to state
let mut state_manager = state.state_manager().clone();
state_manager.apply_changes(bundle);
state.replace_state_manager(state_manager);
} else {
println!("Transaction failed: {:?}", result.error);
}
Ok(())
}
ExecutionResult
The execute_transaction() function returns an ExecutionResult:
pub struct ExecutionResult {
pub success: bool,
pub gas_used: U256,
pub gas_refund: U256,
pub output: Bytes,
pub logs: Vec<String>,
pub error: Option<String>,
}
Checking Results
let result = execute_transaction(tx, sender, &mut bundle, state, block_timestamp)?;
if result.success {
println!("✅ Success");
println!("Gas used: {}", result.gas_used);
for log in &result.logs {
println!("Log: {}", log);
}
if !result.output.is_empty() {
println!("Output: {}", hex::encode(&result.output));
}
} else {
eprintln!("❌ Failed: {}", result.error.unwrap_or_default());
for log in &result.logs {
eprintln!(" {}", log);
}
}
ProcessingContext
The execute_transaction() function requires a type implementing ProcessingContext:
pub trait ProcessingContext {
fn state_manager(&self) -> &StateManager;
fn state_manager_mut(&mut self) -> &mut StateManager;
fn bitcoin_client_read(&self) -> Option<Arc<dyn BitcoinRpcReadClient>>;
fn bitcoin_network(&self) -> bitcoin::Network;
fn handle_cmio_query(
&mut self,
message: CmioMessage,
current_intent_id: Option<B256>,
) -> Option<CmioMessage>;
}
Using CoreLaneStateForLib
The library provides CoreLaneStateForLib which implements ProcessingContext:
use core_lane::{
CoreLaneStateForLib, StateManager,
create_bitcoin_rpc_client
};
use bitcoin::Network;
use std::sync::Arc;
// Create Bitcoin RPC client
let rpc_client = create_bitcoin_rpc_client(
"http://127.0.0.1:18443",
"user",
"password"
)?;
// Create processing context
let state = StateManager::new();
let mut context = CoreLaneStateForLib::new(
state,
rpc_client.clone(),
rpc_client,
Network::Regtest
);
// Now you can execute transactions
let mut bundle = BundleStateManager::new();
let result = execute_transaction(
&tx_envelope,
sender_address,
&mut bundle,
&mut context,
block_timestamp
)?;
Complete Example
Here’s a complete example from examples/simple_sequencer.rs:
use alloy_consensus::{SignableTransaction, TxEip1559};
use alloy_primitives::{Bytes, TxKind};
use alloy_signer::SignerSync;
use alloy_signer_local::PrivateKeySigner;
use core_lane::{
create_bitcoin_rpc_client, execute_transaction,
Address, BundleStateManager, CoreLaneStateForLib,
StateManager, TxEnvelope, U256,
};
use bitcoin::Network;
use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
// Setup Bitcoin RPC client
let bitcoin_client = create_bitcoin_rpc_client(
"http://127.0.0.1:18443",
"user",
"password"
)?;
// Initialize state and context
let mut state = StateManager::new();
let mut state_context = CoreLaneStateForLib::new(
state.clone(),
bitcoin_client.clone(),
bitcoin_client,
Network::Regtest
);
// Create a signer
let signer: PrivateKeySigner =
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
.parse()?;
let sender = signer.address();
let recipient = Address::from([0x99; 20]);
// Give sender initial balance
let mut setup_bundle = BundleStateManager::new();
let initial_balance = U256::from(10_000_000_000_000_000_000u128);
setup_bundle.add_balance(&state, sender, initial_balance)?;
state.apply_changes(setup_bundle);
state_context.replace_state_manager(state.clone());
// Build transaction
let tx = TxEip1559 {
chain_id: 1,
nonce: 0,
max_priority_fee_per_gas: 1_000_000_000,
max_fee_per_gas: 20_000_000_000,
gas_limit: 21000,
to: TxKind::Call(recipient),
value: U256::from(1_000_000_000_000_000_000u128), // 1 ETH
input: Bytes::new(),
access_list: Default::default(),
};
// Sign transaction
let signature = signer.sign_hash_sync(&tx.signature_hash())?;
let signed = tx.into_signed(signature);
let envelope = TxEnvelope::Eip1559(signed);
// Execute transaction
let mut tx_bundle = BundleStateManager::new();
let block_timestamp = 1704067200;
let result = execute_transaction(
&envelope,
sender,
&mut tx_bundle,
&mut state_context,
block_timestamp
)?;
if result.success {
println!("✅ Transaction executed successfully!");
println!("Gas used: {}", result.gas_used);
// Apply changes
state.apply_changes(tx_bundle);
println!("Sender balance: {}", state.get_balance(sender));
println!("Recipient balance: {}", state.get_balance(recipient));
} else {
println!("❌ Transaction failed: {:?}", result.error);
}
Ok(())
}
Transaction Helpers
The library provides helper functions for extracting transaction data:
use core_lane::{get_transaction_input_bytes, get_transaction_nonce};
// Get transaction calldata
let input_bytes = get_transaction_input_bytes(&tx_envelope);
println!("Input: {}", hex::encode(&input_bytes));
// Get transaction nonce
let nonce = get_transaction_nonce(&tx_envelope);
println!("Nonce: {}", nonce);
Special Addresses
Core Lane defines special addresses for system operations:
use core_lane::CoreLaneAddresses;
// Exit marketplace (intent operations)
let exit_marketplace = CoreLaneAddresses::exit_marketplace();
// 0x0000000000000000000000000000000000000045
// Cartesi HTTP runner
let cartesi_runner = CoreLaneAddresses::cartesi_http_runner();
// 0x0000000000000000000000000000000000000042
// Burn address
let burn = CoreLaneAddresses::burn();
// 0x0000000000000000000000000000000000000666
Transactions sent to these addresses trigger special behavior:
- Exit Marketplace: Intent creation, locking, solving, and cancellation
- Cartesi HTTP Runner: RISC-V program execution (requires
cartesi-runner feature)
- Burn Address: Reserved for future use
Nonce Validation
Transactions are validated for correct nonce sequencing:
// Transaction with wrong nonce will fail
let result = execute_transaction(tx, sender, &mut bundle, state, block_timestamp)?;
if !result.success {
// Check for nonce error
if let Some(error) = &result.error {
if error.contains("Invalid nonce") {
println!("Nonce mismatch detected");
}
}
}
The nonce must match the account’s current nonce exactly. After successful execution, the nonce is incremented automatically.
See Also