diff --git a/crates/rooch-relayer/src/actor/bitcoin_relayer.rs b/crates/rooch-relayer/src/actor/bitcoin_relayer.rs index 411fe7a196..ca6f8c6893 100644 --- a/crates/rooch-relayer/src/actor/bitcoin_relayer.rs +++ b/crates/rooch-relayer/src/actor/bitcoin_relayer.rs @@ -1,22 +1,23 @@ // Copyright (c) RoochNetwork // SPDX-License-Identifier: Apache-2.0 +use super::messages::{GetReadyL1BlockMessage, GetReadyL1TxsMessage, SyncTick}; use crate::actor::bitcoin_client_proxy::BitcoinClientProxy; -use crate::Relayer; use anyhow::Result; use async_trait::async_trait; use bitcoin::hashes::Hash; use bitcoin::Block; use bitcoincore_rpc::bitcoincore_rpc_json::GetBlockHeaderResult; +use coerce::actor::{context::ActorContext, message::Handler, Actor}; use moveos_types::module_binding::MoveFunctionCaller; use rooch_config::BitcoinRelayerConfig; use rooch_executor::proxy::ExecutorProxy; use rooch_types::{ - bitcoin::BitcoinModule, + bitcoin::{pending_block::PendingBlockModule, BitcoinModule}, multichain_id::RoochMultiChainID, - transaction::{L1Block, L1BlockWithBody}, + transaction::{L1Block, L1BlockWithBody, L1Transaction}, }; -use tracing::{debug, info}; +use tracing::{debug, error, info}; pub struct BitcoinRelayer { genesis_block_height: u64, @@ -70,8 +71,8 @@ impl BitcoinRelayer { } self.latest_sync_timestamp = chrono::Utc::now().timestamp() as u64; - let bitcoin_module = self.move_caller.as_module_binding::(); - let latest_block_height_in_rooch = bitcoin_module.get_latest_block_height()?; + let pending_block_module = self.move_caller.as_module_binding::(); + let latest_block_height_in_rooch = pending_block_module.get_latest_block_height()?; let latest_block_hash_in_bitcoin = self.rpc_client.get_best_block_hash().await?; let latest_block_header_info = self .rpc_client @@ -167,12 +168,68 @@ impl BitcoinRelayer { })) } } + + fn get_ready_l1_txs(&mut self) -> Result> { + let pending_block_module = self.move_caller.as_module_binding::(); + let pending_txs = pending_block_module.get_ready_pending_txs()?; + match pending_txs { + Some(pending_txs) => { + let block_hash = pending_txs.block_hash; + let mut txs = pending_txs.txs; + if txs.len() > 1 { + // move coinbase tx to the end + let coinbase_tx = txs.remove(0); + txs.push(coinbase_tx); + } + let l1_txs = txs + .into_iter() + .map(|txid| { + L1Transaction::new( + RoochMultiChainID::Bitcoin.multichain_id(), + block_hash.to_vec(), + txid.to_vec(), + ) + }) + .collect(); + Ok(l1_txs) + } + None => Ok(vec![]), + } + } +} + +#[async_trait] +impl Actor for BitcoinRelayer { + async fn started(&mut self, _ctx: &mut ActorContext) {} +} + +#[async_trait] +impl Handler for BitcoinRelayer { + async fn handle(&mut self, _message: SyncTick, _ctx: &mut ActorContext) { + if let Err(e) = self.sync_block().await { + error!("BitcoinRelayer sync block error: {:?}", e); + } + } } #[async_trait] -impl Relayer for BitcoinRelayer { - async fn relay(&mut self) -> Result> { - self.sync_block().await?; +impl Handler for BitcoinRelayer { + async fn handle( + &mut self, + _message: GetReadyL1BlockMessage, + _ctx: &mut ActorContext, + ) -> Result> { self.pop_buffer() } } + +#[async_trait] +impl Handler for BitcoinRelayer { + async fn handle( + &mut self, + _message: GetReadyL1TxsMessage, + _ctx: &mut ActorContext, + ) -> Result> { + self.get_ready_l1_txs() + } +} diff --git a/crates/rooch-relayer/src/actor/ethereum_relayer.rs b/crates/rooch-relayer/src/actor/ethereum_relayer.rs index 1a4156e613..85f54f3ac0 100644 --- a/crates/rooch-relayer/src/actor/ethereum_relayer.rs +++ b/crates/rooch-relayer/src/actor/ethereum_relayer.rs @@ -1,19 +1,21 @@ // Copyright (c) RoochNetwork // SPDX-License-Identifier: Apache-2.0 -use crate::Relayer; use anyhow::Result; use async_trait::async_trait; +use coerce::actor::{context::ActorContext, message::Handler, Actor}; use ethers::prelude::*; use rooch_config::EthereumRelayerConfig; use rooch_types::{ framework::ethereum::BlockHeader, multichain_id::RoochMultiChainID, - transaction::{L1Block, L1BlockWithBody}, + transaction::{L1Block, L1BlockWithBody, L1Transaction}, }; use std::collections::HashSet; use tracing::info; +use super::messages::{GetReadyL1BlockMessage, GetReadyL1TxsMessage, SyncTick}; + pub struct EthereumRelayer { rpc_client: Provider, processed_blocks: HashSet, @@ -69,8 +71,36 @@ impl EthereumRelayer { } #[async_trait] -impl Relayer for EthereumRelayer { - async fn relay(&mut self) -> Result> { +impl Actor for EthereumRelayer { + async fn started(&mut self, _ctx: &mut ActorContext) {} +} + +#[async_trait] +impl Handler for EthereumRelayer { + async fn handle(&mut self, _message: SyncTick, _ctx: &mut ActorContext) { + //TODO support buffer block + } +} + +#[async_trait] +impl Handler for EthereumRelayer { + async fn handle( + &mut self, + _message: GetReadyL1BlockMessage, + _ctx: &mut ActorContext, + ) -> Result> { self.relay_ethereum().await } } + +#[async_trait] +impl Handler for EthereumRelayer { + async fn handle( + &mut self, + _message: GetReadyL1TxsMessage, + _ctx: &mut ActorContext, + ) -> Result> { + //TODO + Ok(vec![]) + } +} diff --git a/crates/rooch-relayer/src/actor/messages.rs b/crates/rooch-relayer/src/actor/messages.rs index 7e0dccaa7a..40612ab2dc 100644 --- a/crates/rooch-relayer/src/actor/messages.rs +++ b/crates/rooch-relayer/src/actor/messages.rs @@ -4,6 +4,7 @@ use anyhow::Result; use bitcoincore_rpc::json; use coerce::actor::{message::Message, scheduler::timer::TimerTick}; +use rooch_types::transaction::{L1BlockWithBody, L1Transaction}; use serde::{Deserialize, Serialize}; #[derive(Clone)] @@ -48,3 +49,22 @@ pub struct GetBlockHeaderInfoMessage { impl Message for GetBlockHeaderInfoMessage { type Result = Result; } + +pub struct GetReadyL1BlockMessage {} + +impl Message for GetReadyL1BlockMessage { + type Result = Result>; +} + +pub struct GetReadyL1TxsMessage {} + +impl Message for GetReadyL1TxsMessage { + type Result = Result>; +} + +#[derive(Clone)] +pub struct SyncTick {} + +impl Message for SyncTick { + type Result = (); +} diff --git a/crates/rooch-relayer/src/actor/mod.rs b/crates/rooch-relayer/src/actor/mod.rs index c68e5891ac..d00aca309c 100644 --- a/crates/rooch-relayer/src/actor/mod.rs +++ b/crates/rooch-relayer/src/actor/mod.rs @@ -7,3 +7,4 @@ pub mod bitcoin_relayer; pub mod ethereum_relayer; pub mod messages; pub mod relayer; +pub mod relayer_proxy; diff --git a/crates/rooch-relayer/src/actor/relayer.rs b/crates/rooch-relayer/src/actor/relayer.rs index f32ef2adff..f6932a3feb 100644 --- a/crates/rooch-relayer/src/actor/relayer.rs +++ b/crates/rooch-relayer/src/actor/relayer.rs @@ -1,18 +1,15 @@ // Copyright (c) RoochNetwork // SPDX-License-Identifier: Apache-2.0 -use std::collections::VecDeque; - use super::bitcoin_relayer::BitcoinRelayer; use super::ethereum_relayer::EthereumRelayer; use super::messages::RelayTick; use crate::actor::bitcoin_client::BitcoinClientActor; use crate::actor::bitcoin_client_proxy::BitcoinClientProxy; -use crate::Relayer; +use crate::actor::relayer_proxy::RelayerProxy; use anyhow::Result; use async_trait::async_trait; -use coerce::actor::system::ActorSystem; -use coerce::actor::{context::ActorContext, message::Handler, Actor, IntoActor}; +use coerce::actor::{context::ActorContext, message::Handler, Actor}; use move_core_types::account_address::AccountAddress; use move_core_types::vm_status::KeptVMStatus; use moveos_types::moveos_std::gas_schedule::GasScheduleConfig; @@ -22,16 +19,18 @@ use rooch_executor::proxy::ExecutorProxy; use rooch_pipeline_processor::proxy::PipelineProcessorProxy; use rooch_types::address::BitcoinAddress; use rooch_types::crypto::RoochKeyPair; -use rooch_types::transaction::L1Transaction; +use rooch_types::transaction::{L1BlockWithBody, L1Transaction}; use tracing::{error, info, warn}; pub struct RelayerActor { sequencer_address: AccountAddress, sequencer_bitcoin_address: BitcoinAddress, max_gas_amount: u64, - relayers: Vec>, + relayers: Vec, executor: ExecutorProxy, processor: PipelineProcessorProxy, + ethereum_config: Option, + bitcoin_config: Option, } impl RelayerActor { @@ -43,143 +42,150 @@ impl RelayerActor { bitcoin_config: Option, ) -> Result { let sequencer_address = sequencer_key.public().rooch_address()?.into(); - let mut relayers: Vec> = vec![]; - if let Some(ethereum_config) = ethereum_config { - let eth_relayer = EthereumRelayer::new(ethereum_config)?; - relayers.push(Box::new(eth_relayer)); - } - - if let Some(bitcoin_config) = bitcoin_config { - let actor_system = ActorSystem::global_system(); - let bitcoin_client_actor = BitcoinClientActor::new(bitcoin_config.clone())? - .into_actor(Some("BitcoinClient"), &actor_system) - .await?; - let bitcoin_client_proxy = BitcoinClientProxy::new(bitcoin_client_actor.into()); - let bitcoin_relayer = - BitcoinRelayer::new(bitcoin_config, bitcoin_client_proxy, executor.clone())?; - relayers.push(Box::new(bitcoin_relayer)); - } Ok(Self { sequencer_address, sequencer_bitcoin_address: sequencer_key.public().bitcoin_address()?, max_gas_amount: GasScheduleConfig::INITIAL_MAX_GAS_AMOUNT * 1000, - relayers, + relayers: vec![], executor, processor, + ethereum_config, + bitcoin_config, }) } - async fn sync(&mut self) -> Result<()> { - for relayer in &mut self.relayers { - let relayer_name = relayer.name(); - loop { - match relayer.relay().await { - Ok(Some(l1_block)) => { - let sequence_number = self - .executor - .get_sequence_number(self.sequencer_address) - .await?; - let tx_hash = l1_block.block.tx_hash(); - let ctx = TxContext::new( - self.sequencer_address, - sequence_number, - self.max_gas_amount, - tx_hash, - l1_block.block.tx_size(), - ); - let block_hash = hex::encode(&l1_block.block.block_hash); - let block_height = l1_block.block.block_height; - let result = self - .processor - .execute_l1_block( - ctx, - l1_block.clone(), - self.sequencer_bitcoin_address.clone(), - ) - .await?; + async fn init_relayer(&mut self, ctx: &mut ActorContext) -> Result<()> { + if let Some(ethereum_config) = &self.ethereum_config { + let eth_relayer = EthereumRelayer::new(ethereum_config.clone())?; + let eth_relayer_actor_ref = ctx.spawn("eth_relayer".into(), eth_relayer).await?; + self.relayers + .push(RelayerProxy::ethereum(eth_relayer_actor_ref.into())); + info!("EthereumRelayer started") + } - match result.execution_info.status { - KeptVMStatus::Executed => { - info!( - "Relayer execute relay block(hash: {}, height: {}) success", - block_hash, block_height - ); - //TODO lazy execute txs to handle reorg, currently we directly execute txs - if l1_block.block.chain_id.is_bitcoin() { - let block = - bcs::from_bytes::( - &l1_block.block_body, - )?; - let block_hash = l1_block.block.block_hash.clone(); - let mut l1_txs = block - .txdata - .iter() - .map(|tx| { - L1Transaction::new( - l1_block.block.chain_id, - block_hash.clone(), - tx.id.to_vec(), - ) - }) - .collect::>(); + if let Some(bitcoin_config) = &self.bitcoin_config { + let bitcoin_client = BitcoinClientActor::new(bitcoin_config.clone())?; + let bitcoin_client_actor_ref = + ctx.spawn("bitcoin_client".into(), bitcoin_client).await?; + let bitcoin_client_proxy = BitcoinClientProxy::new(bitcoin_client_actor_ref.into()); + let bitcoin_relayer = BitcoinRelayer::new( + bitcoin_config.clone(), + bitcoin_client_proxy, + self.executor.clone(), + )?; + let bitcoin_relayer_actor_ref = + ctx.spawn("bitcoin_relayer".into(), bitcoin_relayer).await?; + self.relayers + .push(RelayerProxy::bitcoin(bitcoin_relayer_actor_ref.into())); + info!("BitcoinRelayer started") + } + Ok(()) + } - //move coinbase tx to the last - let coinbase_tx = - l1_txs.pop_front().expect("coinbase tx should exist"); - l1_txs.push_back(coinbase_tx); + async fn handle_l1_block(&mut self, l1_block: L1BlockWithBody) -> Result<()> { + let sequence_number = self + .executor + .get_sequence_number(self.sequencer_address) + .await?; + let tx_hash = l1_block.block.tx_hash(); + let ctx = TxContext::new( + self.sequencer_address, + sequence_number, + self.max_gas_amount, + tx_hash, + l1_block.block.tx_size(), + ); + let block_hash = hex::encode(&l1_block.block.block_hash); + let block_height = l1_block.block.block_height; + let result = self + .processor + .execute_l1_block( + ctx, + l1_block.clone(), + self.sequencer_bitcoin_address.clone(), + ) + .await?; - for l1_tx in l1_txs { - let sequence_number = self - .executor - .get_sequence_number(self.sequencer_address) - .await?; - let tx_hash = l1_tx.tx_hash(); - let txid = hex::encode(&l1_tx.txid); - let ctx = TxContext::new( - self.sequencer_address, - sequence_number, - self.max_gas_amount, - tx_hash, - l1_tx.tx_size(), - ); - let result = self - .processor - .execute_l1_tx( - ctx, - l1_tx, - self.sequencer_bitcoin_address.clone(), - ) - .await?; + match result.execution_info.status { + KeptVMStatus::Executed => { + info!( + "Relayer execute relay block(hash: {}, height: {}) success", + block_hash, block_height + ); + } + _ => { + //TODO should we stop the service if the relayer failed + error!( + "Relayer execute relay block(hash: {}, height: {}) failed, status: {:?}", + block_hash, block_height, result.execution_info.status + ); + } + } + Ok(()) + } - match result.execution_info.status { - KeptVMStatus::Executed => { - info!( - "Relayer execute relay tx(txid: {}) success", - txid - ); - } - _ => { - error!( - "Relayer execute relay tx(txid: {}) failed, status: {:?}", - txid, result.execution_info.status - ); - break; - } - } - } - } - } - _ => { - //TODO should we stop the service if the relayer failed - error!( - "Relayer execute relay block(hash: {}, height: {}) failed, status: {:?}", - block_hash, block_height, result.execution_info.status - ); - break; + async fn handle_l1_tx(&mut self, l1_tx: L1Transaction) -> Result<()> { + let sequence_number = self + .executor + .get_sequence_number(self.sequencer_address) + .await?; + let tx_hash = l1_tx.tx_hash(); + let txid = hex::encode(&l1_tx.txid); + let ctx = TxContext::new( + self.sequencer_address, + sequence_number, + self.max_gas_amount, + tx_hash, + l1_tx.tx_size(), + ); + let result = self + .processor + .execute_l1_tx(ctx, l1_tx, self.sequencer_bitcoin_address.clone()) + .await?; + + match result.execution_info.status { + KeptVMStatus::Executed => { + info!("Relayer execute relay tx(txid: {}) success", txid); + } + _ => { + error!( + "Relayer execute relay tx(txid: {}) failed, status: {:?}", + txid, result.execution_info.status + ); + } + } + Ok(()) + } + + async fn sync(&mut self) { + let relayers = self.relayers.clone(); + for relayer in relayers { + let relayer_name = relayer.name(); + if let Err(e) = relayer.sync().await { + warn!("Relayer {} sync error: {:?}", relayer_name, e); + } + + loop { + match relayer.get_ready_l1_txs().await { + Ok(txs) => { + for tx in txs { + if let Err(err) = self.handle_l1_tx(tx).await { + warn!("Relayer {} error: {:?}", relayer_name, err); } } } + Err(err) => { + warn!("Relayer {} error: {:?}", relayer_name, err); + break; + } + } + match relayer.get_ready_l1_block().await { + Ok(Some(l1_block)) => { + if let Err(err) = self.handle_l1_block(l1_block).await { + warn!("Relayer {} error: {:?}", relayer_name, err); + } + } Ok(None) => { //skip break; @@ -191,21 +197,21 @@ impl RelayerActor { } } } - - Ok(()) } } #[async_trait] impl Actor for RelayerActor { - async fn started(&mut self, _ctx: &mut ActorContext) {} + async fn started(&mut self, ctx: &mut ActorContext) { + if let Err(err) = self.init_relayer(ctx).await { + error!("Relayer init error: {:?}", err); + } + } } #[async_trait] impl Handler for RelayerActor { async fn handle(&mut self, _message: RelayTick, _ctx: &mut ActorContext) { - if let Err(err) = self.sync().await { - warn!("Relayer tick task error: {:?}", err); - } + self.sync().await } } diff --git a/crates/rooch-relayer/src/actor/relayer_proxy.rs b/crates/rooch-relayer/src/actor/relayer_proxy.rs new file mode 100644 index 0000000000..4adfba2640 --- /dev/null +++ b/crates/rooch-relayer/src/actor/relayer_proxy.rs @@ -0,0 +1,53 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + +use super::{ + bitcoin_relayer::BitcoinRelayer, + ethereum_relayer::EthereumRelayer, + messages::{GetReadyL1BlockMessage, GetReadyL1TxsMessage, SyncTick}, +}; +use anyhow::Result; +use coerce::actor::{ActorRef, ActorRefErr}; +use rooch_types::transaction::{L1BlockWithBody, L1Transaction}; + +#[derive(Clone)] +pub enum RelayerProxy { + Bitcoin(ActorRef), + Ethereum(ActorRef), +} + +impl RelayerProxy { + pub fn bitcoin(actor: ActorRef) -> Self { + Self::Bitcoin(actor) + } + pub fn ethereum(actor: ActorRef) -> Self { + Self::Ethereum(actor) + } + + pub fn name(&self) -> String { + match self { + Self::Bitcoin(actor) => actor.actor_id().to_string(), + Self::Ethereum(actor) => actor.actor_id().to_string(), + } + } + pub async fn sync(&self) -> Result<(), ActorRefErr> { + match self { + Self::Bitcoin(actor) => actor.notify(SyncTick {}).await, + Self::Ethereum(actor) => actor.notify(SyncTick {}).await, + } + } + + pub async fn get_ready_l1_block(&self) -> Result> { + match self { + Self::Bitcoin(actor) => actor.send(GetReadyL1BlockMessage {}).await?, + Self::Ethereum(actor) => actor.send(GetReadyL1BlockMessage {}).await?, + } + } + + pub async fn get_ready_l1_txs(&self) -> Result> { + match self { + Self::Bitcoin(actor) => actor.send(GetReadyL1TxsMessage {}).await?, + Self::Ethereum(actor) => actor.send(GetReadyL1TxsMessage {}).await?, + } + } +} diff --git a/crates/rooch-relayer/src/lib.rs b/crates/rooch-relayer/src/lib.rs index b89a5b1254..786fe119b9 100644 --- a/crates/rooch-relayer/src/lib.rs +++ b/crates/rooch-relayer/src/lib.rs @@ -1,17 +1,4 @@ // Copyright (c) RoochNetwork // SPDX-License-Identifier: Apache-2.0 -use anyhow::Result; -use async_trait::async_trait; -use rooch_types::transaction::L1BlockWithBody; - pub mod actor; - -#[async_trait] -pub trait Relayer: Send + Sync { - fn name(&self) -> &'static str { - std::any::type_name::() - } - - async fn relay(&mut self) -> Result>; -} diff --git a/crates/rooch-types/src/bitcoin/pending_block.rs b/crates/rooch-types/src/bitcoin/pending_block.rs index a4a8b14608..85d748b816 100644 --- a/crates/rooch-types/src/bitcoin/pending_block.rs +++ b/crates/rooch-types/src/bitcoin/pending_block.rs @@ -48,20 +48,23 @@ impl<'a> PendingBlockModule<'a> { ident_str!("get_ready_pending_txs"); pub const GET_LATEST_BLOCK_HEIGHT_FUNCTION_NAME: &'static IdentStr = ident_str!("get_latest_block_height"); + pub const GET_REORG_PENDING_BLOCK_COUNT_FUNCTION_NAME: &'static IdentStr = + ident_str!("get_reorg_pending_block_count"); pub fn get_ready_pending_txs(&self) -> Result> { let call = Self::create_function_call(Self::GET_READY_PENDING_TXS_FUNCTION_NAME, vec![], vec![]); let ctx = TxContext::new_readonly_ctx(AccountAddress::ZERO); - let pending_txs_opt = - self.caller - .call_function(&ctx, call)? - .into_result() - .map(|mut values| { - let value = values.pop().expect("should have one return value"); - bcs::from_bytes::>(&value.value) - .expect("should be a valid MoveOption") - })?; + let pending_txs_opt = self + .caller + .call_function(&ctx, call)? + .into_result() + .map(|mut values| { + let value = values.pop().expect("should have one return value"); + bcs::from_bytes::>(&value.value) + .expect("should be a valid MoveOption") + }) + .map_err(|e| anyhow::anyhow!("Failed to get ready pending txs: {:?}", e))?; Ok(pending_txs_opt.into()) } @@ -80,6 +83,24 @@ impl<'a> PendingBlockModule<'a> { })?; Ok(height.into()) } + + pub fn get_reorg_pending_block_count(&self) -> Result { + let call = Self::create_function_call( + Self::GET_REORG_PENDING_BLOCK_COUNT_FUNCTION_NAME, + vec![], + vec![], + ); + let ctx = TxContext::new_readonly_ctx(AccountAddress::ZERO); + let height = self + .caller + .call_function(&ctx, call)? + .into_result() + .map(|mut values| { + let value = values.pop().expect("should have one return value"); + bcs::from_bytes::(&value.value).expect("should be a valid u64") + })?; + Ok(height) + } } impl<'a> ModuleBinding<'a> for PendingBlockModule<'a> { diff --git a/frameworks/bitcoin-move/doc/pending_block.md b/frameworks/bitcoin-move/doc/pending_block.md index d842c5b02c..b76d9a6c2a 100644 --- a/frameworks/bitcoin-move/doc/pending_block.md +++ b/frameworks/bitcoin-move/doc/pending_block.md @@ -26,6 +26,7 @@ PendingStore is used to store the pending blocks and txs, and handle the reorg - [Function `inprocess_block_height`](#0x4_pending_block_inprocess_block_height) - [Function `get_ready_pending_txs`](#0x4_pending_block_get_ready_pending_txs) - [Function `get_latest_block_height`](#0x4_pending_block_get_latest_block_height) +- [Function `get_reorg_pending_block_count`](#0x4_pending_block_get_reorg_pending_block_count)
use 0x1::option;
@@ -190,7 +191,7 @@ This is a hot potato struct, can not be store and drop
 
 
 
-
public(friend) fun genesis_init(reorg_pending_blocks: u64)
+
public(friend) fun genesis_init(reorg_pending_block_count: u64)
 
@@ -325,3 +326,14 @@ Get the pending txs which are ready to be processed
public fun get_latest_block_height(): option::Option<u64>
 
+ + + + + +## Function `get_reorg_pending_block_count` + + + +
public fun get_reorg_pending_block_count(): u64
+
diff --git a/frameworks/bitcoin-move/sources/genesis.move b/frameworks/bitcoin-move/sources/genesis.move index 9e89e0fdaa..8b9747ad59 100644 --- a/frameworks/bitcoin-move/sources/genesis.move +++ b/frameworks/bitcoin-move/sources/genesis.move @@ -28,9 +28,9 @@ module bitcoin_move::genesis{ utxo::genesis_init(); ord::genesis_init(&genesis_account); bitcoin::genesis_init(&genesis_account, genesis_context.genesis_block_height); - //TODO put the reorg_pending_blocks in the genesis context when reset the genesis - let reorg_pending_blocks = 0; - pending_block::genesis_init(reorg_pending_blocks); + //TODO put the reorg_pending_block_count in the genesis context when reset the genesis + let reorg_pending_block_count = 0; + pending_block::genesis_init(reorg_pending_block_count); } #[test_only] diff --git a/frameworks/bitcoin-move/sources/pending_block.move b/frameworks/bitcoin-move/sources/pending_block.move index a5bac70a00..ae5e31d6a8 100644 --- a/frameworks/bitcoin-move/sources/pending_block.move +++ b/frameworks/bitcoin-move/sources/pending_block.move @@ -41,7 +41,7 @@ module bitcoin_move::pending_block{ /// The latest pending block height latest_block_height: Option, /// How many blocks we should pending for reorg - reorg_pending_blocks: u64, + reorg_pending_block_count: u64, } /// InprocessBlock is used to store the block and txs that are being processed @@ -58,11 +58,11 @@ module bitcoin_move::pending_block{ success: bool, } - public(friend) fun genesis_init(reorg_pending_blocks: u64){ + public(friend) fun genesis_init(reorg_pending_block_count: u64){ let store_obj = object::new_named_object(PendingStore{ pending_blocks: simple_map::new(), latest_block_height: option::none(), - reorg_pending_blocks, + reorg_pending_block_count, }); object::transfer_extend(store_obj, @bitcoin_move); } @@ -197,7 +197,7 @@ module bitcoin_move::pending_block{ let store = borrow_mut_store(); let block_obj = take_pending_block(block_hash); let latest_block_height = *option::borrow(&store.latest_block_height); - assert!(object::borrow(&block_obj).block_height + store.reorg_pending_blocks >= latest_block_height, ErrorNeedToWaitMoreBlocks); + assert!(object::borrow(&block_obj).block_height + store.reorg_pending_block_count >= latest_block_height, ErrorNeedToWaitMoreBlocks); assert!(object::contains_field(&block_obj, txid), ErrorPendingTxNotFound); let tx = object::remove_field(&mut block_obj, txid); let inprocess_block = InprocessBlock{ @@ -222,7 +222,11 @@ module bitcoin_move::pending_block{ assert!(types::is_coinbase_tx(&tx), ErrorPendingBlockNotFinished); let pending_block = object::borrow_mut(&mut block_obj); pending_block.processed_tx = pending_block.processed_tx + 1; - remove_pending_block(block_obj, true) + let block_height = pending_block.block_height; + let header = remove_pending_block(block_obj, true); + let store = borrow_mut_store(); + simple_map::remove(&mut store.pending_blocks, &block_height); + header } public(friend) fun inprocess_block_flotsams_mut(inprocess_block: &mut InprocessBlock): &mut vector{ @@ -262,7 +266,7 @@ module bitcoin_move::pending_block{ return option::none() }; let latest_block_height = *option::borrow(&store.latest_block_height); - let ready_block_height = latest_block_height - store.reorg_pending_blocks; + let ready_block_height = latest_block_height - store.reorg_pending_block_count; if(!simple_map::contains_key(&store.pending_blocks, &ready_block_height)){ return option::none() }; @@ -282,5 +286,10 @@ module bitcoin_move::pending_block{ public fun get_latest_block_height(): Option{ let store = borrow_store(); store.latest_block_height + } + + public fun get_reorg_pending_block_count(): u64{ + let store = borrow_store(); + store.reorg_pending_block_count } } \ No newline at end of file