Skip to content

Commit

Permalink
[bitcoin] Define l1_tx type and split l1_tx execution from l1_block (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jolestar authored Jun 19, 2024
1 parent 74e6772 commit 7b593d7
Show file tree
Hide file tree
Showing 20 changed files with 580 additions and 43 deletions.
1 change: 1 addition & 0 deletions crates/rooch-benchmarks/src/tx_exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ pub fn tx_exec_benchmark(c: &mut Criterion) {
.execute_l1_block(l1_block_with_body.clone())
.unwrap()
}
LedgerTxData::L1Tx(tx) => binding_test.execute_l1_tx(tx).unwrap(),
LedgerTxData::L2Tx(tx) => binding_test.execute(tx).unwrap(),
}
});
Expand Down
43 changes: 40 additions & 3 deletions crates/rooch-executor/src/actor/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use super::messages::{
ExecuteTransactionMessage, ExecuteTransactionResult, GetRootMessage, ValidateL1BlockMessage,
ValidateL2TxMessage,
ValidateL1TxMessage, ValidateL2TxMessage,
};
use anyhow::Result;
use async_trait::async_trait;
Expand All @@ -28,7 +28,9 @@ use rooch_types::framework::ethereum::EthereumModule;
use rooch_types::framework::transaction_validator::TransactionValidator;
use rooch_types::framework::{system_post_execute_functions, system_pre_execute_functions};
use rooch_types::multichain_id::RoochMultiChainID;
use rooch_types::transaction::{AuthenticatorInfo, L1Block, L1BlockWithBody, RoochTransaction};
use rooch_types::transaction::{
AuthenticatorInfo, L1Block, L1BlockWithBody, L1Transaction, RoochTransaction,
};
use tracing::{debug, warn};

pub struct ExecutorActor {
Expand Down Expand Up @@ -98,7 +100,7 @@ impl ExecutorActor {
l1_block: L1BlockWithBody,
sequencer_address: BitcoinAddress,
) -> Result<VerifiedMoveOSTransaction> {
ctx.add(TxValidateResult::new_l1_block(sequencer_address))?;
ctx.add(TxValidateResult::new_l1_block_or_tx(sequencer_address))?;
//In the future, we should verify the block PoW difficulty or PoS validator signature before the sequencer decentralized
let L1BlockWithBody {
block:
Expand Down Expand Up @@ -140,6 +142,30 @@ impl ExecutorActor {
}
}

pub fn validate_l1_tx(
&self,
mut ctx: TxContext,
l1_tx: L1Transaction,
sequencer_address: BitcoinAddress,
) -> Result<VerifiedMoveOSTransaction> {
ctx.add(TxValidateResult::new_l1_block_or_tx(sequencer_address))?;

match RoochMultiChainID::try_from(l1_tx.chain_id.id())? {
RoochMultiChainID::Bitcoin => {
let action = VerifiedMoveAction::Function {
call: BitcoinModule::create_execute_l1_tx_call(l1_tx.block_hash, l1_tx.txid)?,
bypass_visibility: true,
};
Ok(VerifiedMoveOSTransaction::new(
self.root.clone(),
ctx,
action,
))
}
id => Err(anyhow::anyhow!("Chain {} not supported yet", id)),
}
}

pub fn validate_l2_tx(&self, mut tx: RoochTransaction) -> Result<VerifiedMoveOSTransaction> {
let sender = tx.sender();
let tx_hash = tx.tx_hash();
Expand Down Expand Up @@ -273,6 +299,17 @@ impl Handler<ValidateL1BlockMessage> for ExecutorActor {
}
}

#[async_trait]
impl Handler<ValidateL1TxMessage> for ExecutorActor {
async fn handle(
&mut self,
msg: ValidateL1TxMessage,
_ctx: &mut ActorContext,
) -> Result<VerifiedMoveOSTransaction> {
self.validate_l1_tx(msg.ctx, msg.l1_tx, msg.sequencer_address)
}
}

#[async_trait]
impl Handler<ExecuteTransactionMessage> for ExecutorActor {
async fn handle(
Expand Down
13 changes: 12 additions & 1 deletion crates/rooch-executor/src/actor/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use moveos_types::transaction::TransactionExecutionInfo;
use moveos_types::transaction::TransactionOutput;
use moveos_types::transaction::VerifiedMoveOSTransaction;
use rooch_types::address::{BitcoinAddress, MultiChainAddress};
use rooch_types::transaction::{L1BlockWithBody, RoochTransaction};
use rooch_types::transaction::{L1BlockWithBody, L1Transaction, RoochTransaction};
use serde::{Deserialize, Serialize};

#[derive(Debug)]
Expand All @@ -41,6 +41,17 @@ impl Message for ValidateL1BlockMessage {
type Result = Result<VerifiedMoveOSTransaction>;
}

#[derive(Debug)]
pub struct ValidateL1TxMessage {
pub ctx: TxContext,
pub l1_tx: L1Transaction,
pub sequencer_address: BitcoinAddress,
}

impl Message for ValidateL1TxMessage {
type Result = Result<VerifiedMoveOSTransaction>;
}

#[derive(Debug)]
pub struct ExecuteTransactionMessage {
pub tx: VerifiedMoveOSTransaction,
Expand Down
19 changes: 17 additions & 2 deletions crates/rooch-executor/src/proxy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::actor::messages::{
GetAnnotatedStatesByStateMessage, GetEventsByEventHandleMessage, GetEventsByEventIDsMessage,
GetTxExecutionInfosByHashMessage, ListAnnotatedStatesMessage, ListStatesMessage,
RefreshStateMessage, ValidateL1BlockMessage,
RefreshStateMessage, ValidateL1BlockMessage, ValidateL1TxMessage,
};
use crate::actor::reader_executor::ReaderExecutorActor;
use crate::actor::{
Expand Down Expand Up @@ -38,7 +38,7 @@ use moveos_types::{
use rooch_types::address::BitcoinAddress;
use rooch_types::bitcoin::network::BitcoinNetwork;
use rooch_types::framework::chain_id::ChainID;
use rooch_types::transaction::{L1BlockWithBody, RoochTransaction};
use rooch_types::transaction::{L1BlockWithBody, L1Transaction, RoochTransaction};
use tokio::runtime::Handle;

#[derive(Clone)]
Expand Down Expand Up @@ -77,6 +77,21 @@ impl ExecutorProxy {
.await?
}

pub async fn validate_l1_tx(
&self,
ctx: TxContext,
l1_tx: L1Transaction,
sequencer_address: BitcoinAddress,
) -> Result<VerifiedMoveOSTransaction> {
self.actor
.send(ValidateL1TxMessage {
ctx,
l1_tx,
sequencer_address,
})
.await?
}

//TODO ensure the execute result
pub async fn execute_transaction(
&self,
Expand Down
82 changes: 70 additions & 12 deletions crates/rooch-framework-tests/src/binding_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ use rooch_db::RoochDB;
use rooch_executor::actor::reader_executor::ReaderExecutorActor;
use rooch_executor::actor::{executor::ExecutorActor, messages::ExecuteTransactionResult};
use rooch_genesis::RoochGenesis;
use rooch_types::address::BitcoinAddress;
use rooch_types::crypto::RoochKeyPair;
use rooch_types::rooch_network::{BuiltinChainID, RoochNetwork};
use rooch_types::transaction::{L1BlockWithBody, RoochTransaction};
use rooch_types::transaction::{L1BlockWithBody, L1Transaction, RoochTransaction};
use std::collections::VecDeque;
use std::env;
use std::path::Path;
use std::sync::Arc;
Expand All @@ -41,6 +43,7 @@ pub struct RustBindingTest {
//we keep the opt to ensure the temp dir is not be deleted before the test end
opt: RoochOpt,
sequencer: AccountAddress,
sequencer_bitcoin_address: BitcoinAddress,
kp: RoochKeyPair,
pub executor: ExecutorActor,
pub reader_executor: ReaderExecutorActor,
Expand Down Expand Up @@ -79,6 +82,7 @@ impl RustBindingTest {
opt,
root,
sequencer: sequencer.to_rooch_address().into(),
sequencer_bitcoin_address: sequencer,
kp,
executor,
reader_executor,
Expand Down Expand Up @@ -119,30 +123,84 @@ impl RustBindingTest {
}

pub fn execute_l1_block(&mut self, l1_block: L1BlockWithBody) -> Result<()> {
let sequence_number = self.get_account_sequence_number(self.sequencer)?;
let ctx = self.create_bt_blk_tx_ctx(sequence_number, l1_block.clone());
let verified_tx: VerifiedMoveOSTransaction =
let ctx = self.create_l1_block_ctx(&l1_block)?;
let verified_tx: VerifiedMoveOSTransaction = self.executor.validate_l1_block(
ctx,
l1_block.clone(),
self.sequencer_bitcoin_address.clone(),
)?;
self.execute_verified_tx(verified_tx)?;

if l1_block.block.chain_id.is_bitcoin() {
let block =
bcs::from_bytes::<rooch_types::bitcoin::types::Block>(&l1_block.block_body)?;
let mut l1_txs = block
.txdata
.iter()
.map(|tx| {
L1Transaction::new(
l1_block.block.chain_id,
l1_block.block.block_hash.clone(),
tx.id.to_vec(),
)
})
.collect::<VecDeque<_>>();
let coinbase_tx = l1_txs.pop_front().expect("coinbase tx should exist");
l1_txs.push_back(coinbase_tx);
for tx in &block.txdata[1..] {
let l1_tx = L1Transaction::new(
l1_block.block.chain_id,
l1_block.block.block_hash.clone(),
tx.id.to_vec(),
);
self.execute_l1_tx(l1_tx)?;
}
let coinbase_tx = L1Transaction::new(
l1_block.block.chain_id,
l1_block.block.block_hash.clone(),
block.txdata[0].id.to_vec(),
);
self.execute_l1_tx(coinbase_tx)?;
}
Ok(())
}

pub fn execute_l1_tx(&mut self, l1_tx: L1Transaction) -> Result<()> {
let ctx = self.create_l1_tx_ctx(l1_tx.clone())?;
let verified_tx =
self.executor
.validate_l1_block(ctx, l1_block, self.kp.public().bitcoin_address()?)?;
.validate_l1_tx(ctx, l1_tx, self.sequencer_bitcoin_address.clone())?;
self.execute_verified_tx(verified_tx)
}

pub fn create_bt_blk_tx_ctx(
&mut self,
sequence_number: u64,
l1_block: L1BlockWithBody,
) -> TxContext {
pub fn create_l1_block_ctx(&self, l1_block: &L1BlockWithBody) -> Result<TxContext> {
let sequence_number = self.get_account_sequence_number(self.sequencer)?;
let max_gas_amount = GasScheduleConfig::INITIAL_MAX_GAS_AMOUNT * 1000;
let tx_hash = l1_block.block.tx_hash();
let tx_size = l1_block.block.tx_size();

TxContext::new(
Ok(TxContext::new(
self.sequencer,
sequence_number,
max_gas_amount,
tx_hash,
tx_size,
))
}

pub fn create_l1_tx_ctx(&self, l1_tx: L1Transaction) -> Result<TxContext> {
let sequence_number = self.get_account_sequence_number(self.sequencer)?;
let max_gas_amount = GasScheduleConfig::INITIAL_MAX_GAS_AMOUNT * 1000;
let tx_hash = l1_tx.tx_hash();
let tx_size = l1_tx.tx_size();

Ok(TxContext::new(
self.sequencer,
sequence_number,
max_gas_amount,
tx_hash,
tx_size,
)
))
}

pub fn execute_as_result(&mut self, tx: RoochTransaction) -> Result<ExecuteTransactionResult> {
Expand Down
28 changes: 28 additions & 0 deletions crates/rooch-open-rpc-spec/schemas/openrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -1659,6 +1659,34 @@
}
}
},
{
"type": "object",
"required": [
"block_hash",
"chain_id",
"txid",
"type"
],
"properties": {
"block_hash": {
"$ref": "#/components/schemas/alloc::vec::Vec<u8>"
},
"chain_id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
},
"txid": {
"$ref": "#/components/schemas/alloc::vec::Vec<u8>"
},
"type": {
"type": "string",
"enum": [
"l1_tx"
]
}
}
},
{
"type": "object",
"required": [
Expand Down
13 changes: 12 additions & 1 deletion crates/rooch-pipeline-processor/src/actor/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use coerce::actor::message::Message;
use moveos_types::moveos_std::tx_context::TxContext;
use rooch_types::{
address::BitcoinAddress,
transaction::{ExecuteTransactionResponse, L1BlockWithBody, RoochTransaction},
transaction::{ExecuteTransactionResponse, L1BlockWithBody, L1Transaction, RoochTransaction},
};

#[derive(Clone)]
Expand All @@ -28,3 +28,14 @@ pub struct ExecuteL1BlockMessage {
impl Message for ExecuteL1BlockMessage {
type Result = Result<ExecuteTransactionResponse>;
}

#[derive(Clone)]
pub struct ExecuteL1TxMessage {
pub ctx: TxContext,
pub tx: L1Transaction,
pub sequencer_address: BitcoinAddress,
}

impl Message for ExecuteL1TxMessage {
type Result = Result<ExecuteTransactionResponse>;
}
35 changes: 32 additions & 3 deletions crates/rooch-pipeline-processor/src/actor/processor.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use super::messages::{ExecuteL1BlockMessage, ExecuteL2TxMessage};
use super::messages::{ExecuteL1BlockMessage, ExecuteL1TxMessage, ExecuteL2TxMessage};
use anyhow::Result;
use async_trait::async_trait;
use coerce::actor::{context::ActorContext, message::Handler, Actor};
Expand All @@ -16,8 +16,8 @@ use rooch_sequencer::proxy::SequencerProxy;
use rooch_types::{
address::BitcoinAddress,
transaction::{
ExecuteTransactionResponse, L1BlockWithBody, LedgerTransaction, LedgerTxData,
RoochTransaction,
ExecuteTransactionResponse, L1BlockWithBody, L1Transaction, LedgerTransaction,
LedgerTxData, RoochTransaction,
},
};
use tracing::debug;
Expand Down Expand Up @@ -65,6 +65,23 @@ impl PipelineProcessorActor {
self.execute_tx(ledger_tx, moveos_tx).await
}

pub async fn execute_l1_tx(
&mut self,
ctx: TxContext,
l1_tx: L1Transaction,
sequencer_address: BitcoinAddress,
) -> Result<ExecuteTransactionResponse> {
let moveos_tx = self
.executor
.validate_l1_tx(ctx, l1_tx.clone(), sequencer_address)
.await?;
let ledger_tx = self
.sequencer
.sequence_transaction(LedgerTxData::L1Tx(l1_tx))
.await?;
self.execute_tx(ledger_tx, moveos_tx).await
}

pub async fn execute_l2_tx(
&mut self,
mut tx: RoochTransaction,
Expand Down Expand Up @@ -153,3 +170,15 @@ impl Handler<ExecuteL1BlockMessage> for PipelineProcessorActor {
.await
}
}

#[async_trait]
impl Handler<ExecuteL1TxMessage> for PipelineProcessorActor {
async fn handle(
&mut self,
msg: ExecuteL1TxMessage,
_ctx: &mut ActorContext,
) -> Result<ExecuteTransactionResponse> {
self.execute_l1_tx(msg.ctx, msg.tx, msg.sequencer_address)
.await
}
}
Loading

0 comments on commit 7b593d7

Please sign in to comment.