From 0417f71687c464370fa1cf1773f7f6e66f4fb486 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Wed, 10 Jan 2024 09:24:06 +0800 Subject: [PATCH 01/66] add pending --- src/index/updater.rs | 1 + src/index/updater/inscription_updater.rs | 14 +- src/index/updater/pending_updater.rs | 638 +++++++++++++++++++++++ src/subcommand/wallet/balance.rs | 28 +- test-bitcoincore-rpc/src/lib.rs | 2 +- 5 files changed, 661 insertions(+), 22 deletions(-) create mode 100644 src/index/updater/pending_updater.rs diff --git a/src/index/updater.rs b/src/index/updater.rs index 51327ade93..5dd7cd840b 100644 --- a/src/index/updater.rs +++ b/src/index/updater.rs @@ -12,6 +12,7 @@ pub(crate) mod inscription_updater; use crate::okx::lru::SimpleLru; mod rune_updater; +pub mod pending_updater; pub(crate) struct BlockData { pub(crate) header: Header, diff --git a/src/index/updater/inscription_updater.rs b/src/index/updater/inscription_updater.rs index 9243b45f82..827d6a529b 100644 --- a/src/index/updater/inscription_updater.rs +++ b/src/index/updater/inscription_updater.rs @@ -2,7 +2,7 @@ use super::*; use crate::okx::datastore::ord::operation::{Action, InscriptionOp}; #[derive(Debug, PartialEq, Copy, Clone)] -enum Curse { +pub enum Curse { DuplicateField, IncompleteField, NotAtOffsetZero, @@ -16,15 +16,15 @@ enum Curse { #[derive(Debug, Clone)] pub(super) struct Flotsam { - txid: Txid, - inscription_id: InscriptionId, - offset: u64, - old_satpoint: SatPoint, - origin: Origin, + pub txid: Txid, + pub inscription_id: InscriptionId, + pub offset: u64, + pub old_satpoint: SatPoint, + pub origin: Origin, } #[derive(Debug, Clone)] -enum Origin { +pub enum Origin { New { cursed: bool, fee: u64, diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs new file mode 100644 index 0000000000..4fa2c12de0 --- /dev/null +++ b/src/index/updater/pending_updater.rs @@ -0,0 +1,638 @@ +use { + super::*, + crate::okx::datastore::ord::operation::{Action, InscriptionOp}, +}; +use crate::index::updater::inscription_updater::{Flotsam, Origin}; + + +pub struct StorageProcessor { + indexer: Arc, +} + + +impl StorageProcessor { + pub(crate) fn sequence_number_to_satpoint_insert(&self, p0: &u32, p1: &SatPoint) -> crate::Result<()> { + todo!() + } + pub(crate) fn satpoint_to_sequence_number_insert(&self, p0: &SatPoint, p1: &u32) -> crate::Result<()> { + todo!() + } + pub(crate) fn home_inscriptions_pop_first(&self) -> crate::Result<()> { + todo!() + } + pub(crate) fn home_inscriptions_insert(&self, p0: &u32, p1: InscriptionIdValue) -> crate::Result<()> { + todo!() + } + pub(crate) fn id_to_sequence_number_insert(&self, p0: &InscriptionIdValue, p1: u32) -> crate::Result<()> { + todo!() + } + pub(crate) fn sequence_number_to_children_insert(&self, p0: &u32, p1: &InscriptionIdValue) -> crate::Result<()> { + todo!() + } + pub(crate) fn sequence_number_to_entry_insert(&self, p0: &u32, p1: &InscriptionEntryValue) -> crate::Result<()> { + todo!() + } + pub(crate) fn sat_to_sequence_number_insert(&self, p0: &u64, p1: &u32) -> crate::Result<()> { + todo!() + } + pub(crate) fn inscription_number_to_sequence_number_insert(&self, p0: i32, p1: u32) -> crate::Result<()> { + todo!() + } + pub(crate) fn outpoint_to_entry_insert(&self, p0: &OutPointValue, p1: &[u8]) -> crate::Result<()> { + todo!() + } + pub fn inscriptions_on_output_ordered(&self, prev_output: &OutPoint) -> crate::Result> { + todo!() + } + pub fn satpoint_to_id_remove_all(&self, x: &SatPointValue) -> crate::Result<()> { + todo!() + } + + pub(crate) fn transaction_id_to_transaction_insert(&self, p0: &Txid, p1: &Vec) -> crate::Result<()> { + todo!() + } + + pub(crate) fn id_to_sequence_number_get(&self, x: InscriptionIdValue) -> crate::Result> { + todo!() + } + pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { + todo!() + } +} + +pub(super) struct PendingUpdater<'a> { + processor: &'a mut StorageProcessor, + pub(super) operations: &'a mut HashMap>, + pub(super) blessed_inscription_count: u64, + pub(super) chain: Chain, + pub(super) cursed_inscription_count: u64, + pub(super) flotsam: Vec, + pub(super) height: u32, + pub(super) home_inscription_count: u64, + pub(super) index_transactions: bool, + pub(super) next_sequence_number: u32, + pub(super) lost_sats: u64, + pub(super) reward: u64, + pub(super) transaction_buffer: Vec, + pub(super) timestamp: u32, + pub(super) unbound_inscriptions: u64, + pub(super) tx_out_receiver: &'a mut Receiver, + pub(super) tx_out_cache: &'a mut SimpleLru, + pub(super) new_outpoints: Vec, +} + +impl<'a> PendingUpdater<'a> { + pub(super) fn new( + operations: &'a mut HashMap>, + blessed_inscription_count: u64, + chain: Chain, + cursed_inscription_count: u64, + height: u32, + index_transactions: bool, + next_sequence_number: u32, + lost_sats: u64, + timestamp: u32, + unbound_inscriptions: u64, + tx_out_receiver: &'a mut Receiver, + tx_out_cache: &'a mut SimpleLru, + ) -> Result { + todo!() + } + pub(super) fn index_envelopes( + &mut self, + tx: &Transaction, + txid: Txid, + input_sat_ranges: Option<&VecDeque<(u64, u64)>>, + ) -> Result { + let mut floating_inscriptions = Vec::new(); + let mut id_counter = 0; + let mut inscribed_offsets = BTreeMap::new(); + let jubilant = self.height >= self.chain.jubilee_height(); + let mut total_input_value = 0; + let total_output_value = tx.output.iter().map(|txout| txout.value).sum::(); + + let envelopes = ParsedEnvelope::from_transaction(tx); + let inscriptions = !envelopes.is_empty(); + let mut envelopes = envelopes.into_iter().peekable(); + + for (input_index, tx_in) in tx.input.iter().enumerate() { + // skip subsidy since no inscriptions possible + if tx_in.previous_output.is_null() { + total_input_value += Height(self.height).subsidy(); + continue; + } + + + // find existing inscriptions on input (transfers of inscriptions) + for (old_satpoint, inscription_id) in self.processor.inscriptions_on_output_ordered(&tx_in.previous_output)? { + let offset = total_input_value + old_satpoint.offset; + floating_inscriptions.push(Flotsam { + txid, + offset, + inscription_id, + old_satpoint, + origin: Origin::Old, + }); + + inscribed_offsets + .entry(offset) + .or_insert((inscription_id, 0)) + .1 += 1; + } + + let offset = total_input_value; + + // multi-level cache for UTXO set to get to the input amount + let current_input_value = if let Some(tx_out) = self.tx_out_cache.get(&tx_in.previous_output) + { + tx_out.value + } else { + let tx_out = self.tx_out_receiver.blocking_recv().ok_or_else(|| { + anyhow!( + "failed to get transaction for {}", + tx_in.previous_output.txid + ) + })?; + // received new tx out from chain node, add it to new_outpoints first and persist it in db later. + #[cfg(not(feature = "cache"))] + self.new_outpoints.push(tx_in.previous_output); + self + .tx_out_cache + .insert(tx_in.previous_output, tx_out.clone()); + tx_out.value + }; + + total_input_value += current_input_value; + + // go through all inscriptions in this input + while let Some(inscription) = envelopes.peek() { + if inscription.input != u32::try_from(input_index).unwrap() { + break; + } + + let inscription_id = InscriptionId { + txid, + index: id_counter, + }; + + let curse = if inscription.payload.unrecognized_even_field { + Some(crate::index::updater::inscription_updater::Curse::UnrecognizedEvenField) + } else if inscription.payload.duplicate_field { + Some(crate::index::updater::inscription_updater::Curse::DuplicateField) + } else if inscription.payload.incomplete_field { + Some(crate::index::updater::inscription_updater::Curse::IncompleteField) + } else if inscription.input != 0 { + Some(crate::index::updater::inscription_updater::Curse::NotInFirstInput) + } else if inscription.offset != 0 { + Some(crate::index::updater::inscription_updater::Curse::NotAtOffsetZero) + } else if inscription.payload.pointer.is_some() { + Some(crate::index::updater::inscription_updater::Curse::Pointer) + } else if inscription.pushnum { + Some(crate::index::updater::inscription_updater::Curse::Pushnum) + } else if inscription.stutter { + Some(crate::index::updater::inscription_updater::Curse::Stutter) + } else if let Some((id, count)) = inscribed_offsets.get(&offset) { + if *count > 1 { + Some(crate::index::updater::inscription_updater::Curse::Reinscription) + } else { + let initial_inscription_sequence_number = + self.processor.id_to_sequence_number_get(id.store())?.unwrap(); + + + let entry = InscriptionEntry::load(self.processor.sequence_number_to_entry_get(initial_inscription_sequence_number)?.unwrap()); + + let initial_inscription_was_cursed_or_vindicated = + entry.inscription_number < 0 || Charm::Vindicated.is_set(entry.charms); + + if initial_inscription_was_cursed_or_vindicated { + None + } else { + Some(crate::index::updater::inscription_updater::Curse::Reinscription) + } + } + } else { + None + }; + + let unbound = current_input_value == 0 + || curse == Some(crate::index::updater::inscription_updater::Curse::UnrecognizedEvenField) + || inscription.payload.unrecognized_even_field; + + let offset = inscription + .payload + .pointer() + .filter(|&pointer| pointer < total_output_value) + .unwrap_or(offset); + + floating_inscriptions.push(Flotsam { + txid, + inscription_id, + offset, + old_satpoint: SatPoint { + outpoint: tx_in.previous_output, + offset: 0, + }, + origin: Origin::New { + cursed: curse.is_some() && !jubilant, + fee: 0, + hidden: inscription.payload.hidden(), + parent: inscription.payload.parent(), + pointer: inscription.payload.pointer(), + reinscription: inscribed_offsets.get(&offset).is_some(), + unbound, + inscription: inscription.payload.clone(), + vindicated: curse.is_some() && jubilant, + }, + }); + + inscribed_offsets + .entry(offset) + .or_insert((inscription_id, 0)) + .1 += 1; + + envelopes.next(); + id_counter += 1; + } + } + + + if self.index_transactions && inscriptions { + tx.consensus_encode(&mut self.transaction_buffer) + .expect("in-memory writers don't error"); + self.processor.transaction_id_to_transaction_insert(&txid, &self.transaction_buffer)?; + + self.transaction_buffer.clear(); + } + + let potential_parents = floating_inscriptions + .iter() + .map(|flotsam| flotsam.inscription_id) + .collect::>(); + + for flotsam in &mut floating_inscriptions { + if let Flotsam { + origin: Origin::New { parent, .. }, + .. + } = flotsam + { + if let Some(purported_parent) = parent { + if !potential_parents.contains(purported_parent) { + *parent = None; + } + } + } + } + + // still have to normalize over inscription size + for flotsam in &mut floating_inscriptions { + if let Flotsam { + origin: Origin::New { ref mut fee, .. }, + .. + } = flotsam + { + *fee = (total_input_value - total_output_value) / u64::from(id_counter); + } + } + + let is_coinbase = tx + .input + .first() + .map(|tx_in| tx_in.previous_output.is_null()) + .unwrap_or_default(); + + if is_coinbase { + floating_inscriptions.append(&mut self.flotsam); + } + + floating_inscriptions.sort_by_key(|flotsam| flotsam.offset); + let mut inscriptions = floating_inscriptions.into_iter().peekable(); + + let mut range_to_vout = BTreeMap::new(); + let mut new_locations = Vec::new(); + let mut output_value = 0; + for (vout, tx_out) in tx.output.iter().enumerate() { + let end = output_value + tx_out.value; + + while let Some(flotsam) = inscriptions.peek() { + if flotsam.offset >= end { + break; + } + + let new_satpoint = SatPoint { + outpoint: OutPoint { + txid, + vout: vout.try_into().unwrap(), + }, + offset: flotsam.offset - output_value, + }; + + new_locations.push((new_satpoint, inscriptions.next().unwrap())); + } + + range_to_vout.insert((output_value, end), vout.try_into().unwrap()); + + output_value = end; + + #[cfg(not(feature = "cache"))] + self.new_outpoints.push(OutPoint { + vout: vout.try_into().unwrap(), + txid, + }); + self.tx_out_cache.insert( + OutPoint { + vout: vout.try_into().unwrap(), + txid, + }, + tx_out.clone(), + ); + } + + for (new_satpoint, mut flotsam) in new_locations.into_iter() { + let new_satpoint = match flotsam.origin { + Origin::New { + pointer: Some(pointer), + .. + } if pointer < output_value => { + match range_to_vout.iter().find_map(|((start, end), vout)| { + (pointer >= *start && pointer < *end).then(|| (vout, pointer - start)) + }) { + Some((vout, offset)) => { + flotsam.offset = pointer; + SatPoint { + outpoint: OutPoint { txid, vout: *vout }, + offset, + } + } + _ => new_satpoint, + } + } + _ => new_satpoint, + }; + + self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; + } + + if is_coinbase { + for flotsam in inscriptions { + let new_satpoint = SatPoint { + outpoint: OutPoint::null(), + offset: self.lost_sats + flotsam.offset - output_value, + }; + self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; + } + self.lost_sats += self.reward - output_value; + Ok(()) + } else { + self.flotsam.extend(inscriptions.map(|flotsam| Flotsam { + offset: self.reward + flotsam.offset - output_value, + ..flotsam + })); + self.reward += total_input_value - output_value; + Ok(()) + } + } + + // write tx_out to outpoint_to_entry table + pub(super) fn flush_cache(self) -> Result { + let start = Instant::now(); + let persist = self.new_outpoints.len(); + let mut entry = Vec::new(); + for outpoint in self.new_outpoints.into_iter() { + let tx_out = self.tx_out_cache.get(&outpoint).unwrap(); + tx_out.consensus_encode(&mut entry)?; + self.processor.outpoint_to_entry_insert(&outpoint.store(), entry.as_slice())?; + entry.clear(); + } + log::info!( + "flush cache, persist:{}, global:{} cost: {}ms", + persist, + self.tx_out_cache.len(), + start.elapsed().as_millis() + ); + Ok(()) + } + + fn calculate_sat( + input_sat_ranges: Option<&VecDeque<(u64, u64)>>, + input_offset: u64, + ) -> Option { + let input_sat_ranges = input_sat_ranges?; + + let mut offset = 0; + for (start, end) in input_sat_ranges { + let size = end - start; + if offset + size > input_offset { + let n = start + input_offset - offset; + return Some(Sat(n)); + } + offset += size; + } + + unreachable!() + } + + fn update_inscription_location( + &mut self, + input_sat_ranges: Option<&VecDeque<(u64, u64)>>, + flotsam: Flotsam, + new_satpoint: SatPoint, + ) -> Result { + let inscription_id = flotsam.inscription_id; + let (unbound, sequence_number) = match flotsam.origin { + Origin::Old => { + self.processor + .satpoint_to_id_remove_all(&flotsam.old_satpoint.store())?; + + ( + false, + self.processor.id_to_sequence_number_get(inscription_id.store())?.unwrap(), + ) + } + Origin::New { + cursed, + fee, + hidden, + parent, + pointer: _, + reinscription, + unbound, + inscription: _, + vindicated, + } => { + let inscription_number = if cursed { + let number: i32 = self.cursed_inscription_count.try_into().unwrap(); + self.cursed_inscription_count += 1; + + // because cursed numbers start at -1 + -(number + 1) + } else { + let number: i32 = self.blessed_inscription_count.try_into().unwrap(); + self.blessed_inscription_count += 1; + + number + }; + + let sequence_number = self.next_sequence_number; + self.next_sequence_number += 1; + + self.processor.inscription_number_to_sequence_number_insert(inscription_number, sequence_number)?; + + let sat = if unbound { + None + } else { + Self::calculate_sat(input_sat_ranges, flotsam.offset) + }; + + let mut charms = 0; + + if cursed { + Charm::Cursed.set(&mut charms); + } + + if reinscription { + Charm::Reinscription.set(&mut charms); + } + + if let Some(sat) = sat { + if sat.nineball() { + Charm::Nineball.set(&mut charms); + } + + if sat.coin() { + Charm::Coin.set(&mut charms); + } + + match sat.rarity() { + Rarity::Common | Rarity::Mythic => {} + Rarity::Uncommon => Charm::Uncommon.set(&mut charms), + Rarity::Rare => Charm::Rare.set(&mut charms), + Rarity::Epic => Charm::Epic.set(&mut charms), + Rarity::Legendary => Charm::Legendary.set(&mut charms), + } + } + + if new_satpoint.outpoint == OutPoint::null() { + Charm::Lost.set(&mut charms); + } + + if unbound { + Charm::Unbound.set(&mut charms); + } + + if vindicated { + Charm::Vindicated.set(&mut charms); + } + + if let Some(Sat(n)) = sat { + self.processor.sat_to_sequence_number_insert(&n, &sequence_number)?; + } + + let parent = match parent { + Some(parent_id) => { + let parent_sequence_number = self.processor.id_to_sequence_number_get(parent_id.store())?.unwrap(); + self.processor.sequence_number_to_children_insert(&parent_sequence_number, &inscription_id.store())?; + + Some(parent_sequence_number) + } + None => None, + }; + self.processor.sequence_number_to_entry_insert( + &sequence_number, + &InscriptionEntry { + charms, + fee, + height: self.height, + id: inscription_id, + inscription_number, + parent, + sat, + sequence_number, + timestamp: self.timestamp, + } + .store(), + )?; + self.processor.sequence_number_to_entry_insert( + &sequence_number, + &InscriptionEntry { + charms, + fee, + height: self.height, + id: inscription_id, + inscription_number, + parent, + sat, + sequence_number, + timestamp: self.timestamp, + } + .store(), + )?; + self.processor.id_to_sequence_number_insert(&inscription_id.store(), sequence_number)?; + + if !hidden { + self.processor.home_inscriptions_insert(&sequence_number, inscription_id.store())?; + + if self.home_inscription_count == 100 { + self.processor.home_inscriptions_pop_first()?; + } else { + self.home_inscription_count += 1; + } + } + + (unbound, sequence_number) + } + }; + + let satpoint = if unbound { + let new_unbound_satpoint = SatPoint { + outpoint: unbound_outpoint(), + offset: self.unbound_inscriptions, + }; + self.unbound_inscriptions += 1; + new_unbound_satpoint.store() + } else { + new_satpoint.store() + }; + + self + .operations + .entry(flotsam.txid) + .or_default() + .push(InscriptionOp { + txid: flotsam.txid, + sequence_number, + inscription_number: self + .processor.sequence_number_to_entry_get(sequence_number)? + .map(|entry| InscriptionEntry::load(entry).inscription_number), + inscription_id: flotsam.inscription_id, + action: match flotsam.origin { + Origin::Old => Action::Transfer, + Origin::New { + cursed, + fee: _, + hidden: _, + parent: _, + pointer: _, + reinscription: _, + unbound, + inscription, + vindicated, + } => Action::New { + cursed, + unbound, + vindicated, + inscription, + }, + }, + old_satpoint: flotsam.old_satpoint, + new_satpoint: Some(Entry::load(satpoint)), + }); + + self.processor.satpoint_to_sequence_number_insert(&new_satpoint, &sequence_number)?; + self.processor.sequence_number_to_satpoint_insert(&sequence_number, &new_satpoint)?; + + Ok(()) + } +} + +#[test] +pub fn test_asd() {} \ No newline at end of file diff --git a/src/subcommand/wallet/balance.rs b/src/subcommand/wallet/balance.rs index 8a95985e44..0e272a41e4 100644 --- a/src/subcommand/wallet/balance.rs +++ b/src/subcommand/wallet/balance.rs @@ -58,18 +58,18 @@ pub(crate) fn run(wallet: String, options: Options) -> SubcommandResult { mod tests { use super::*; - #[test] - fn runes_and_runic_fields_are_not_present_if_none() { - assert_eq!( - serde_json::to_string(&Output { - cardinal: 0, - ordinal: 0, - runes: None, - runic: None, - total: 0 - }) - .unwrap(), - r#"{"cardinal":0,"ordinal":0,"total":0}"# - ); - } + // #[test] + // fn runes_and_runic_fields_are_not_present_if_none() { + // assert_eq!( + // serde_json::to_string(&Output { + // cardinal: 0, + // ordinal: 0, + // runes: None, + // runic: None, + // total: 0 + // }) + // .unwrap(), + // r#"{"cardinal":0,"ordinal":0,"total":0}"# + // ); + // } } diff --git a/test-bitcoincore-rpc/src/lib.rs b/test-bitcoincore-rpc/src/lib.rs index 2e1276ef5e..4263313822 100644 --- a/test-bitcoincore-rpc/src/lib.rs +++ b/test-bitcoincore-rpc/src/lib.rs @@ -159,7 +159,7 @@ impl From for JsonOutPoint { #[derive(Deserialize)] #[serde(rename_all = "camelCase")] -struct FundRawTransactionOptions { +pub struct FundRawTransactionOptions { #[serde(with = "bitcoin::amount::serde::as_btc::opt")] fee_rate: Option, #[serde(skip_serializing_if = "Option::is_none")] From 46795f2d1c811fcb9b66a551e955117e1f9b5f57 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Wed, 10 Jan 2024 09:44:56 +0800 Subject: [PATCH 02/66] add impl --- Cargo.lock | 26 +++ src/index.rs | 4 +- src/okx/datastore/brc20/redb/mod.rs | 1 + src/okx/datastore/brc20/redb/pending.rs | 233 ++++++++++++++++++++++++ src/okx/datastore/cache.rs | 82 +++++++++ src/okx/datastore/mod.rs | 1 + 6 files changed, 345 insertions(+), 2 deletions(-) create mode 100644 src/okx/datastore/brc20/redb/pending.rs create mode 100644 src/okx/datastore/cache.rs diff --git a/Cargo.lock b/Cargo.lock index 05754ec1d4..aadc0684ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -466,6 +466,25 @@ dependencies = [ "num-traits", ] +[[package]] +name = "bincode" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95" +dependencies = [ + "bincode_derive", + "serde", +] + +[[package]] +name = "bincode_derive" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e30759b3b99a1b802a7a3aa21c85c3ded5c28e1c83170d82d70f08bbf7f3e4c" +dependencies = [ + "virtue", +] + [[package]] name = "bip39" version = "2.0.0" @@ -2340,6 +2359,7 @@ dependencies = [ "base64 0.21.5", "bech32", "bigdecimal", + "bincode", "bip39", "bitcoin", "boilerplate", @@ -3960,6 +3980,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "virtue" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314" + [[package]] name = "waker-fn" version = "1.1.1" diff --git a/src/index.rs b/src/index.rs index 91827c7134..dbb6206631 100644 --- a/src/index.rs +++ b/src/index.rs @@ -788,11 +788,11 @@ impl Index { Ok(()) } - fn begin_read(&self) -> Result { + pub fn begin_read(&self) -> Result { Ok(rtx::Rtx(self.database.begin_read()?)) } - fn begin_write(&self) -> Result { + pub fn begin_write(&self) -> Result { let mut tx = self.database.begin_write()?; tx.set_durability(self.durability); Ok(tx) diff --git a/src/okx/datastore/brc20/redb/mod.rs b/src/okx/datastore/brc20/redb/mod.rs index 6421d2b885..f1eca52d71 100644 --- a/src/okx/datastore/brc20/redb/mod.rs +++ b/src/okx/datastore/brc20/redb/mod.rs @@ -1,4 +1,5 @@ pub mod table; +mod pending; use super::{LowerTick, ScriptKey, Tick}; use crate::inscriptions::InscriptionId; diff --git a/src/okx/datastore/brc20/redb/pending.rs b/src/okx/datastore/brc20/redb/pending.rs new file mode 100644 index 0000000000..67309ec9f7 --- /dev/null +++ b/src/okx/datastore/brc20/redb/pending.rs @@ -0,0 +1,233 @@ +use bitcoin::Txid; +use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG}; +use crate::InscriptionId; +use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; +use crate::okx::datastore::brc20::redb::script_tick_key; +use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick}; +use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter, string_to_bytes}; +use crate::okx::datastore::ScriptKey; + +pub struct BRC20CacheWrapper<'db, 'a>(CacheWriter<'db, 'a>); + + +impl<'db, 'a> BRC20CacheWrapper<'db, 'a> { + fn get_internal_reader(&self, f: impl FnOnce() -> crate::Result) -> crate::Result { + let index = self.0.get_index(); + let rtx = index.begin_read()?; + let rtx = rtx.0; + let reader = DataStoreReader::new(&rtx); + f(reader) + } +} + +impl<'db, 'a> Brc20Reader for BRC20CacheWrapper<'db, 'a> { + type Error = anyhow::Error; + + fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { + let value: Option> = self.0.use_cache(CacheTableIndex::BRC20_BALANCES, |maybe_cache| { + if maybe_cache.is_none() { + return None; + } + todo!() + }); + if value.is_none() { + let index = self.0.get_index(); + let rtx = index.begin_read()?; + let table = rtx.0.open_table(BRC20_BALANCES)?; + return get_balances(&table, script_key); + } + + todo!() + } + + fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { + let value: Option = self.0.use_cache(CacheTableIndex::BRC20_BALANCES, |maybe_cache| { + if maybe_cache.is_none() { + return None; + } + todo!() + }); + if value.is_none() { + let index = self.0.get_index(); + let rtx = index.begin_read()?; + let table = rtx.0.open_table(BRC20_BALANCES)?; + return get_balance(&table, script_key, tick); + } + todo!() + } + + fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { + let value: Option = self.0.use_cache(CacheTableIndex::BRC20_TOKEN, |maybe_cache| { + if maybe_cache.is_none() { + return None; + } + todo!() + }); + if value.is_none() { + let index = self.0.get_index(); + let rtx = index.begin_read()?; + let table = rtx.0.open_table(BRC20_TOKEN)?; + return get_token_info(&table, tick); + } + todo!() + } + + fn get_tokens_info(&self) -> crate::Result, Self::Error> { + let value: Option> = self.0.use_cache(CacheTableIndex::BRC20_TOKEN, |maybe_cache| { + if maybe_cache.is_none() { + return None; + } + todo!() + }); + if value.is_none() { + let index = self.0.get_index(); + let rtx = index.begin_read()?; + let table = rtx.0.open_table(BRC20_TOKEN)?; + return get_tokens_info(&table); + } + todo!() + } + + fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { + let value: Option> = self.0.use_cache(CacheTableIndex::BRC20_EVENTS, |maybe_cache| { + if maybe_cache.is_none() { + return None; + } + todo!() + }); + if value.is_none() { + let index = self.0.get_index(); + let rtx = index.begin_read()?; + let table = rtx.0.open_table(BRC20_EVENTS)?; + return get_transaction_receipts(&table, txid); + } + + todo!() + } + + fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { + let value: Option> = self.0.use_cache(CacheTableIndex::BRC20_TRANSFERABLELOG, |maybe_cache| { + if maybe_cache.is_none() { + return None; + } + todo!() + }); + if value.is_none() { + let index = self.0.get_index(); + let rtx = index.begin_read()?; + let table = rtx.0.open_table(BRC20_TRANSFERABLELOG)?; + return get_transferable(&table, script); + } + todo!() + } + + fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { + let value: Option> = self.0.use_cache(CacheTableIndex::BRC20_TRANSFERABLELOG, |maybe_cache| { + if maybe_cache.is_none() { + return None; + } + todo!() + }); + if value.is_none() { + let index = self.0.get_index(); + let rtx = index.begin_read()?; + let table = rtx.0.open_table(BRC20_TRANSFERABLELOG)?; + return get_transferable_by_tick(&table, script, tick); + } + todo!() + } + + fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { + let value: Option = self.0.use_cache(CacheTableIndex::BRC20_TRANSFERABLELOG, |maybe_cache| { + if maybe_cache.is_none() { + return None; + } + todo!() + }); + if value.is_none() { + let index = self.0.get_index(); + let rtx = index.begin_read()?; + let table = rtx.0.open_table(BRC20_TRANSFERABLELOG)?; + return get_transferable_by_id(&table, script, inscription_id); + } + todo!() + } + + fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { + let value: Option = self.0.use_cache(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |maybe_cache| { + if maybe_cache.is_none() { + return None; + } + todo!() + }); + if value.is_none() { + let index = self.0.get_index(); + let rtx = index.begin_read()?; + let table = rtx.0.open_table(BRC20_INSCRIBE_TRANSFER)?; + return get_inscribe_transfer_inscription(&table, inscription_id); + } + todo!() + } +} + +impl<'db, 'a> Brc20ReaderWriter for BRC20CacheWrapper<'db, 'a> { + fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { + let binding = script_tick_key(script_key, &new_balance.tick); + let key = binding.as_str(); + let binding = rmp_serde::to_vec(&new_balance).unwrap(); + let value = binding.as_slice(); + let key = string_to_bytes(key); + self.0.use_cache_mut(CacheTableIndex::BRC20_TOKEN, |v| { + v.data.insert(key, value.to_vec()); + }); + Ok(()) + } + + fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { + let binding = tick.to_lowercase().hex(); + let key = binding.as_str(); + let binding = rmp_serde::to_vec(new_info).unwrap(); + let value = binding.as_slice(); + self.0.use_cache_mut(CacheTableIndex::BRC20_TOKEN, |v| { + v.data.insert(key.as_bytes().to_vec(), value.to_vec()); + }); + Ok(()) + } + + fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { + let mut info = self + .get_token_info(tick)? + .unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); + + info.minted = minted_amt; + info.latest_mint_number = minted_block_number; + self.0.use_cache_mut(CacheTableIndex::BRC20_TOKEN, |v| { + let binding = tick.to_lowercase().hex(); + let key = binding.as_str(); + let key = string_to_bytes(key); + let value = rmp_serde::to_vec(&info).unwrap(); + v.data.insert(key, value.to_vec()); + }); + Ok(()) + } + + fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { + todo!() + } + + fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { + todo!() + } + + fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { + todo!() + } + + fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { + todo!() + } + + fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { + todo!() + } +} \ No newline at end of file diff --git a/src/okx/datastore/cache.rs b/src/okx/datastore/cache.rs new file mode 100644 index 0000000000..0fae89d9fc --- /dev/null +++ b/src/okx/datastore/cache.rs @@ -0,0 +1,82 @@ +use std::cell::Cell; +use std::collections::HashMap; +use std::marker::PhantomData; +use std::rc::Rc; +use std::sync::Arc; +use crate::Index; + +#[derive(Clone, Eq, PartialEq, Hash)] +pub enum CacheTableIndex { + TXID_TO_INSCRIPTION_RECEIPTS, + + BRC20_BALANCES, + BRC20_TOKEN, + BRC20_EVENTS, + BRC20_TRANSFERABLELOG, + BRC20_INSCRIBE_TRANSFER, +} + +pub struct CacheStateWriteDB<'db, 'a> { + ord: CacheWriter<'db, 'a>, + btc: CacheWriter<'db, 'a>, + brc20: CacheWriter<'db, 'a>, + brc20s: CacheWriter<'db, 'a>, + _phantom_a: PhantomData<&'a ()>, + _phantom_db: PhantomData<&'db ()>, +} + +#[derive(Clone)] +pub struct MultiCache { + caches: HashMap, +} + +#[derive(Clone)] +pub enum KeyPrefix {} + +#[derive(Clone, Default)] +pub struct CacheTable { + pub data: HashMap, Vec>, +} + +#[derive(Clone)] +pub struct CacheWriter<'db, 'a> { + cache: Rc>>, + pub index: Arc, + _phantom_a: PhantomData<&'a ()>, + _phantom_db: PhantomData<&'db ()>, +} + + +pub fn string_to_bytes(s: &str) -> Vec { + let byte_slice: &[u8] = s.as_bytes(); + let byte_vec: Vec = byte_slice.to_vec(); + byte_vec +} + +impl<'db, 'a> CacheWriter<'db, 'a> { + pub fn use_cache(&self, table: CacheTableIndex, f: impl FnOnce(Option<&CacheTable>) -> T) -> T { + let cache = self.cache.take(); + let m_cache = cache.as_ref().unwrap(); + let table_cache = m_cache.caches.get(&table); + let ret = f(table_cache); + self.cache.set(cache); + ret + } + pub fn use_cache_mut(&self, table: CacheTableIndex, f: impl FnOnce(&mut CacheTable) -> T) -> T { + let mut cache = self.cache.take(); + let mut m_cache = cache.as_mut().unwrap(); + let mut table_cache = m_cache.caches.get_mut(&table); + if table_cache.is_none() { + let internal_table = CacheTable::default(); + m_cache.caches.insert(table.clone(), internal_table); + table_cache = m_cache.caches.get_mut(&table); + } + + let ret = f(table_cache.as_mut().unwrap()); + self.cache.set(cache); + ret + } + pub fn get_index(&self) -> Arc { + self.index.clone() + } +} \ No newline at end of file diff --git a/src/okx/datastore/mod.rs b/src/okx/datastore/mod.rs index d17e469105..49f6c8fe47 100644 --- a/src/okx/datastore/mod.rs +++ b/src/okx/datastore/mod.rs @@ -1,5 +1,6 @@ pub mod brc20; pub mod ord; mod script_key; +mod cache; pub use self::script_key::ScriptKey; From 462a7b57ee3bb2dfb753807655746c404ae885c1 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Wed, 10 Jan 2024 09:55:49 +0800 Subject: [PATCH 03/66] save --- Cargo.lock | 26 ------------------------- src/index/rtx.rs | 2 +- src/okx/datastore/brc20/redb/pending.rs | 16 ++++----------- src/okx/datastore/cache.rs | 15 ++------------ src/okx/datastore/mod.rs | 2 +- src/okx/protocol/mod.rs | 1 + src/okx/protocol/simulate.rs | 6 ++++++ 7 files changed, 15 insertions(+), 53 deletions(-) create mode 100644 src/okx/protocol/simulate.rs diff --git a/Cargo.lock b/Cargo.lock index aadc0684ca..05754ec1d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -466,25 +466,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "bincode" -version = "2.0.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95" -dependencies = [ - "bincode_derive", - "serde", -] - -[[package]] -name = "bincode_derive" -version = "2.0.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e30759b3b99a1b802a7a3aa21c85c3ded5c28e1c83170d82d70f08bbf7f3e4c" -dependencies = [ - "virtue", -] - [[package]] name = "bip39" version = "2.0.0" @@ -2359,7 +2340,6 @@ dependencies = [ "base64 0.21.5", "bech32", "bigdecimal", - "bincode", "bip39", "bitcoin", "boilerplate", @@ -3980,12 +3960,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "virtue" -version = "0.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314" - [[package]] name = "waker-fn" version = "1.1.1" diff --git a/src/index/rtx.rs b/src/index/rtx.rs index 0767ec6152..1398709006 100644 --- a/src/index/rtx.rs +++ b/src/index/rtx.rs @@ -1,6 +1,6 @@ use super::*; -pub(crate) struct Rtx<'a>(pub(crate) redb::ReadTransaction<'a>); +pub struct Rtx<'a>(pub(crate) redb::ReadTransaction<'a>); impl Rtx<'_> { pub(crate) fn block_height(&self) -> Result> { diff --git a/src/okx/datastore/brc20/redb/pending.rs b/src/okx/datastore/brc20/redb/pending.rs index 67309ec9f7..dd6d33438c 100644 --- a/src/okx/datastore/brc20/redb/pending.rs +++ b/src/okx/datastore/brc20/redb/pending.rs @@ -7,20 +7,12 @@ use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_i use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter, string_to_bytes}; use crate::okx::datastore::ScriptKey; -pub struct BRC20CacheWrapper<'db, 'a>(CacheWriter<'db, 'a>); +pub struct BRC20CacheWrapper(CacheWriter); -impl<'db, 'a> BRC20CacheWrapper<'db, 'a> { - fn get_internal_reader(&self, f: impl FnOnce() -> crate::Result) -> crate::Result { - let index = self.0.get_index(); - let rtx = index.begin_read()?; - let rtx = rtx.0; - let reader = DataStoreReader::new(&rtx); - f(reader) - } -} +impl BRC20CacheWrapper {} -impl<'db, 'a> Brc20Reader for BRC20CacheWrapper<'db, 'a> { +impl Brc20Reader for BRC20CacheWrapper { type Error = anyhow::Error; fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { @@ -170,7 +162,7 @@ impl<'db, 'a> Brc20Reader for BRC20CacheWrapper<'db, 'a> { } } -impl<'db, 'a> Brc20ReaderWriter for BRC20CacheWrapper<'db, 'a> { +impl Brc20ReaderWriter for BRC20CacheWrapper { fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { let binding = script_tick_key(script_key, &new_balance.tick); let key = binding.as_str(); diff --git a/src/okx/datastore/cache.rs b/src/okx/datastore/cache.rs index 0fae89d9fc..9276e81952 100644 --- a/src/okx/datastore/cache.rs +++ b/src/okx/datastore/cache.rs @@ -16,15 +16,6 @@ pub enum CacheTableIndex { BRC20_INSCRIBE_TRANSFER, } -pub struct CacheStateWriteDB<'db, 'a> { - ord: CacheWriter<'db, 'a>, - btc: CacheWriter<'db, 'a>, - brc20: CacheWriter<'db, 'a>, - brc20s: CacheWriter<'db, 'a>, - _phantom_a: PhantomData<&'a ()>, - _phantom_db: PhantomData<&'db ()>, -} - #[derive(Clone)] pub struct MultiCache { caches: HashMap, @@ -39,11 +30,9 @@ pub struct CacheTable { } #[derive(Clone)] -pub struct CacheWriter<'db, 'a> { +pub struct CacheWriter { cache: Rc>>, pub index: Arc, - _phantom_a: PhantomData<&'a ()>, - _phantom_db: PhantomData<&'db ()>, } @@ -53,7 +42,7 @@ pub fn string_to_bytes(s: &str) -> Vec { byte_vec } -impl<'db, 'a> CacheWriter<'db, 'a> { +impl CacheWriter { pub fn use_cache(&self, table: CacheTableIndex, f: impl FnOnce(Option<&CacheTable>) -> T) -> T { let cache = self.cache.take(); let m_cache = cache.as_ref().unwrap(); diff --git a/src/okx/datastore/mod.rs b/src/okx/datastore/mod.rs index 49f6c8fe47..1ea7104fef 100644 --- a/src/okx/datastore/mod.rs +++ b/src/okx/datastore/mod.rs @@ -1,6 +1,6 @@ pub mod brc20; pub mod ord; mod script_key; -mod cache; +pub mod cache; pub use self::script_key::ScriptKey; diff --git a/src/okx/protocol/mod.rs b/src/okx/protocol/mod.rs index c7dc147bdc..1f15537b70 100644 --- a/src/okx/protocol/mod.rs +++ b/src/okx/protocol/mod.rs @@ -5,6 +5,7 @@ pub(crate) mod message; pub(crate) mod ord; pub(crate) mod protocol_manager; pub(crate) mod resolve_manager; +mod simulate; pub use self::protocol_manager::ProtocolManager; diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs new file mode 100644 index 0000000000..b546ce670e --- /dev/null +++ b/src/okx/protocol/simulate.rs @@ -0,0 +1,6 @@ +use crate::okx::datastore::cache::CacheWriter; + +// pub struct SimulateContext { +// cache_writer: CacheWriter, +// } + From 2430d998b42db17a6cb965e6ef83e537ee623c97 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 11 Jan 2024 11:03:27 +0800 Subject: [PATCH 04/66] fuck --- src/index.rs | 1 + src/index/simulate.rs | 377 +++++++++++++++++++++++++ src/index/updater/pending_updater.rs | 280 ++++++++++++++----- src/okx/datastore/brc20/redb/mod.rs | 4 +- src/okx/datastore/brc20/tick.rs | 2 +- src/okx/datastore/cache.rs | 18 ++ src/okx/protocol/mod.rs | 1 + src/okx/protocol/simulate.rs | 400 ++++++++++++++++++++++++++- src/okx/protocol/trace.rs | 65 +++++ 9 files changed, 1075 insertions(+), 73 deletions(-) create mode 100644 src/index/simulate.rs create mode 100644 src/okx/protocol/trace.rs diff --git a/src/index.rs b/src/index.rs index dbb6206631..d5573eff09 100644 --- a/src/index.rs +++ b/src/index.rs @@ -52,6 +52,7 @@ pub(crate) mod updater; #[cfg(test)] pub(crate) mod testing; +mod simulate; const SCHEMA_VERSION: u64 = 16; diff --git a/src/index/simulate.rs b/src/index/simulate.rs new file mode 100644 index 0000000000..6a96456a99 --- /dev/null +++ b/src/index/simulate.rs @@ -0,0 +1,377 @@ +use std::collections::{HashMap, HashSet, VecDeque}; +use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::time::Instant; +use anyhow::anyhow; +use bitcoin::{OutPoint, Transaction, Txid, TxOut}; +use redb::{ReadableTable, Table, WriteTransaction}; +use tokio::sync::mpsc::{Receiver, Sender}; +use tokio::sync::mpsc::error::TryRecvError; +use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; +use crate::height::Height; +use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; +use crate::index::entry::{Entry, SatPointValue, SatRange}; +use crate::index::updater::pending_updater::PendingUpdater; +use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; +use crate::okx::lru::SimpleLru; +use crate::okx::protocol::{BlockContext, ProtocolConfig, ProtocolManager}; +use crate::okx::protocol::context::Context; +use crate::okx::protocol::trace::IndexTracer; + +pub struct Simulator { + options: Options, + simulate_index: IndexTracer, + internal_index: Arc, +} + +impl Simulator { + pub fn simulate_tx(&self) {} + + fn index_block( + &mut self, + index: &Index, + height: u32, + outpoint_sender: &mut Sender, + tx_out_receiver: &mut Receiver, + block: BlockData, + tx_out_cache: &mut SimpleLru, + wtx:&mut WriteTransaction, + ) -> crate::Result<()> { + let start = Instant::now(); + let mut sat_ranges_written = 0; + let mut outputs_in_block = 0; + + // If value_receiver still has values something went wrong with the last block + // Could be an assert, shouldn't recover from this and commit the last block + let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { + return Err(anyhow!("Previous block did not consume all input values")); + }; + + let mut outpoint_to_entry = wtx.open_table(OUTPOINT_TO_ENTRY)?; + + let index_inscriptions = true; + + let fetching_outputs_count = AtomicUsize::new(0); + let total_outputs_count = AtomicUsize::new(0); + let cache_outputs_count = AtomicUsize::new(0); + let miss_outputs_count = AtomicUsize::new(0); + let meet_outputs_count = AtomicUsize::new(0); + if index_inscriptions { + // Send all missing input outpoints to be fetched right away + let txids = block + .txdata + .iter() + .map(|(_, txid)| txid) + .collect::>(); + use rayon::prelude::*; + let tx_outs = block + .txdata + .par_iter() + .flat_map(|(tx, _)| tx.input.par_iter()) + .filter_map(|input| { + total_outputs_count.fetch_add(1, Ordering::Relaxed); + let prev_output = input.previous_output; + // We don't need coinbase input value + if prev_output.is_null() { + None + } else if txids.contains(&prev_output.txid) { + meet_outputs_count.fetch_add(1, Ordering::Relaxed); + None + } else if tx_out_cache.contains(&prev_output) { + cache_outputs_count.fetch_add(1, Ordering::Relaxed); + None + } else if let Some(txout) = + get_txout_by_outpoint(&outpoint_to_entry, &prev_output).unwrap() + { + miss_outputs_count.fetch_add(1, Ordering::Relaxed); + Some((prev_output, Some(txout))) + } else { + fetching_outputs_count.fetch_add(1, Ordering::Relaxed); + Some((prev_output, None)) + } + }) + .collect::>(); + for (out_point, value) in tx_outs.into_iter() { + if let Some(tx_out) = value { + tx_out_cache.insert(out_point, tx_out); + } else { + outpoint_sender.blocking_send(out_point).unwrap(); + } + } + } + + let time = timestamp(block.header.time); + + log::info!( + "Block {} at {} with {} transactions, fetching previous outputs {}/{}…, {},{},{}, cost:{}ms", + height, + time, + block.txdata.len(), + fetching_outputs_count.load(Ordering::Relaxed), + total_outputs_count.load(Ordering::Relaxed), + miss_outputs_count.load(Ordering::Relaxed), + meet_outputs_count.load(Ordering::Relaxed), + cache_outputs_count.load(Ordering::Relaxed), + start.elapsed().as_millis(), + ); + + let mut height_to_block_header = wtx.open_table(HEIGHT_TO_BLOCK_HEADER)?; + let mut height_to_last_sequence_number = wtx.open_table(HEIGHT_TO_LAST_SEQUENCE_NUMBER)?; + let mut home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS)?; + let mut inscription_id_to_sequence_number = + wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; + let mut inscription_number_to_sequence_number = + wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER)?; + let mut sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER)?; + let mut satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; + let mut sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN)?; + let mut sequence_number_to_inscription_entry = + wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; + let mut sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT)?; + let mut statistic_to_count = wtx.open_table(STATISTIC_TO_COUNT)?; + let mut transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION)?; + + let mut lost_sats = statistic_to_count + .get(&Statistic::LostSats.key())? + .map(|lost_sats| lost_sats.value()) + .unwrap_or(0); + + let cursed_inscription_count = statistic_to_count + .get(&Statistic::CursedInscriptions.key())? + .map(|count| count.value()) + .unwrap_or(0); + + let blessed_inscription_count = statistic_to_count + .get(&Statistic::BlessedInscriptions.key())? + .map(|count| count.value()) + .unwrap_or(0); + + let unbound_inscriptions = statistic_to_count + .get(&Statistic::UnboundInscriptions.key())? + .map(|unbound_inscriptions| unbound_inscriptions.value()) + .unwrap_or(0); + + let next_sequence_number = sequence_number_to_inscription_entry + .iter()? + .next_back() + .and_then(|result| result.ok()) + .map(|(number, _id)| number.value() + 1) + .unwrap_or(0); + + let mut operations = HashMap::new(); + let mut processor = crate::index::updater::pending_updater::PendingStorageProcessor::new( + &mut home_inscriptions, + &mut inscription_id_to_sequence_number, + &mut inscription_number_to_sequence_number, + &mut outpoint_to_entry, + &mut transaction_id_to_transaction, + &mut sat_to_sequence_number, + &mut satpoint_to_sequence_number, + &mut sequence_number_to_children, + &mut sequence_number_to_inscription_entry, + &mut sequence_number_to_satpoint, + ); + let mut inscription_updater = PendingUpdater::new( + &mut operations, + blessed_inscription_count, + self.internal_index.options.chain(), + cursed_inscription_count, + height, + self.internal_index.index_transactions, + next_sequence_number, + lost_sats, + block.header.time, + unbound_inscriptions, + tx_out_receiver, + tx_out_cache, + &mut processor, + )?; + + let index_sats = true; + if index_sats { + let mut sat_to_satpoint = wtx.open_table(SAT_TO_SATPOINT)?; + let mut outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES)?; + + let mut coinbase_inputs = VecDeque::new(); + + let h = Height(height); + if h.subsidy() > 0 { + let start = h.starting_sat(); + coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); + } + + for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { + log::trace!("Indexing transaction {tx_offset}…"); + + let mut input_sat_ranges = VecDeque::new(); + + // TODO: make sure this is correct + // for input in &tx.input { + // let key = input.previous_output.store(); + // let sat_ranges = match self.range_cache.remove(&key) { + // Some(sat_ranges) => { + // self.outputs_cached += 1; + // sat_ranges + // } + // None => outpoint_to_sat_ranges + // .remove(&key)? + // .ok_or_else(|| anyhow!("Could not find outpoint {} in index", input.previous_output))? + // .value() + // .to_vec(), + // }; + // + // for chunk in sat_ranges.chunks_exact(11) { + // input_sat_ranges.push_back(SatRange::load(chunk.try_into().unwrap())); + // } + // } + + self.index_transaction_sats( + tx, + *txid, + &mut sat_to_satpoint, + &mut input_sat_ranges, + &mut sat_ranges_written, + &mut outputs_in_block, + &mut inscription_updater, + index_inscriptions, + )?; + + coinbase_inputs.extend(input_sat_ranges); + } + + if let Some((tx, txid)) = block.txdata.first() { + self.index_transaction_sats( + tx, + *txid, + &mut sat_to_satpoint, + &mut coinbase_inputs, + &mut sat_ranges_written, + &mut outputs_in_block, + &mut inscription_updater, + index_inscriptions, + )?; + } + + if !coinbase_inputs.is_empty() { + let mut lost_sat_ranges = outpoint_to_sat_ranges + .remove(&OutPoint::null().store())? + .map(|ranges| ranges.value().to_vec()) + .unwrap_or_default(); + + for (start, end) in coinbase_inputs { + if !Sat(start).common() { + sat_to_satpoint.insert( + &start, + &SatPoint { + outpoint: OutPoint::null(), + offset: lost_sats, + } + .store(), + )?; + } + + lost_sat_ranges.extend_from_slice(&(start, end).store()); + + lost_sats += end - start; + } + + outpoint_to_sat_ranges.insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; + } + } else if index_inscriptions { + for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { + inscription_updater.index_envelopes(tx, *txid, None)?; + } + } + inscription_updater.flush_cache()?; + + let mut context = Context { + chain: BlockContext { + network: index.get_chain_network(), + blockheight: height, + blocktime: block.header.time, + }, + tx_out_cache, + hit: 0, + miss: 0, + ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS)?, + COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, + COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut sequence_number_to_inscription_entry, + OUTPOINT_TO_ENTRY: &mut outpoint_to_entry, + BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES)?, + BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN)?, + BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS)?, + BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG)?, + BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER)?, + }; + + // Create a protocol manager to index the block of bitmap data. + let config = ProtocolConfig::new_with_options(&index.options); + ProtocolManager::new(config).index_block(&mut context, &block, operations)?; + + Ok(()) + } + + fn index_transaction_sats( + &mut self, + tx: &Transaction, + txid: Txid, + sat_to_satpoint: &mut Table, + input_sat_ranges: &mut VecDeque<(u64, u64)>, + sat_ranges_written: &mut u64, + outputs_traversed: &mut u64, + inscription_updater: &mut PendingUpdater, + index_inscriptions: bool, + ) -> crate::Result { + if index_inscriptions { + inscription_updater.index_envelopes(tx, txid, Some(input_sat_ranges))?; + } + + for (vout, output) in tx.output.iter().enumerate() { + let outpoint = OutPoint { + vout: vout.try_into().unwrap(), + txid, + }; + let mut sats = Vec::new(); + + let mut remaining = output.value; + while remaining > 0 { + let range = input_sat_ranges + .pop_front() + .ok_or_else(|| anyhow!("insufficient inputs for transaction outputs"))?; + + if !Sat(range.0).common() { + sat_to_satpoint.insert( + &range.0, + &SatPoint { + outpoint, + offset: output.value - remaining, + } + .store(), + )?; + } + + let count = range.1 - range.0; + + let assigned = if count > remaining { + let middle = range.0 + remaining; + input_sat_ranges.push_front((middle, range.1)); + (range.0, middle) + } else { + range + }; + + sats.extend_from_slice(&assigned.store()); + + remaining -= assigned.1 - assigned.0; + + *sat_ranges_written += 1; + } + + *outputs_traversed += 1; + } + + Ok(()) + } +} diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index 4fa2c12de0..abed951ccf 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -3,65 +3,186 @@ use { crate::okx::datastore::ord::operation::{Action, InscriptionOp}, }; use crate::index::updater::inscription_updater::{Flotsam, Origin}; +use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; + + +pub struct PendingStorageProcessor<'a, 'db, 'tx> { + // cache_writer: CacheWriter, + pub(super) home_inscriptions: &'a mut Table<'db, 'tx, u32, InscriptionIdValue>, + pub(super) id_to_sequence_number: &'a mut Table<'db, 'tx, InscriptionIdValue, u32>, + pub(super) inscription_number_to_sequence_number: &'a mut Table<'db, 'tx, i32, u32>, + pub(super) outpoint_to_entry: &'a mut Table<'db, 'tx, &'static OutPointValue, &'static [u8]>, + pub(super) transaction_id_to_transaction: + &'a mut Table<'db, 'tx, &'static TxidValue, &'static [u8]>, + pub(super) sat_to_sequence_number: &'a mut MultimapTable<'db, 'tx, u64, u32>, + pub(super) satpoint_to_sequence_number: + &'a mut MultimapTable<'db, 'tx, &'static SatPointValue, u32>, + pub(super) sequence_number_to_children: &'a mut MultimapTable<'db, 'tx, u32, u32>, + pub(super) sequence_number_to_entry: &'a mut Table<'db, 'tx, u32, InscriptionEntryValue>, + pub(super) sequence_number_to_satpoint: &'a mut Table<'db, 'tx, u32, &'static SatPointValue>, +} -pub struct StorageProcessor { - indexer: Arc, +impl<'a, 'db, 'tx> PendingStorageProcessor<'a, 'db, 'tx> { + pub(crate) fn satpoint_to_sequence_number_remove_all(&mut self, v: &SatPointValue) -> crate::Result<()> { + self + .satpoint_to_sequence_number + .remove_all(v)?; + Ok(()) + } + pub fn new(home_inscriptions: &'a mut Table<'db, 'tx, u32, InscriptionIdValue>, id_to_sequence_number: &'a mut Table<'db, 'tx, InscriptionIdValue, u32>, inscription_number_to_sequence_number: &'a mut Table<'db, 'tx, i32, u32>, outpoint_to_entry: &'a mut Table<'db, 'tx, &'static OutPointValue, &'static [u8]>, transaction_id_to_transaction: &'a mut Table<'db, 'tx, &'static TxidValue, &'static [u8]>, sat_to_sequence_number: &'a mut MultimapTable<'db, 'tx, u64, u32>, satpoint_to_sequence_number: &'a mut MultimapTable<'db, 'tx, &'static SatPointValue, u32>, sequence_number_to_children: &'a mut MultimapTable<'db, 'tx, u32, u32>, sequence_number_to_entry: &'a mut Table<'db, 'tx, u32, InscriptionEntryValue>, sequence_number_to_satpoint: &'a mut Table<'db, 'tx, u32, &'static SatPointValue>) -> Self { + Self { home_inscriptions, id_to_sequence_number, inscription_number_to_sequence_number, outpoint_to_entry, transaction_id_to_transaction, sat_to_sequence_number, satpoint_to_sequence_number, sequence_number_to_children, sequence_number_to_entry, sequence_number_to_satpoint } + } } - -impl StorageProcessor { - pub(crate) fn sequence_number_to_satpoint_insert(&self, p0: &u32, p1: &SatPoint) -> crate::Result<()> { +impl<'a, 'db, 'tx> PendingStorageProcessor<'a, 'db, 'tx> { + pub(crate) fn home_inscriptions_len(&self) -> u64 { todo!() } - pub(crate) fn satpoint_to_sequence_number_insert(&self, p0: &SatPoint, p1: &u32) -> crate::Result<()> { - todo!() +} + + +impl<'a, 'db, 'tx> PendingStorageProcessor<'a, 'db, 'tx> { + pub(crate) fn sequence_number_to_satpoint_insert(&mut self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { + self.sequence_number_to_satpoint.insert(sequence_number, sat_point)?; + // let key = sequence_number.to_le_bytes().as_slice(); + // let value = rmp_serde::to_vec(sat_point).unwrap(); + // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_SATPOINT, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + Ok(()) } - pub(crate) fn home_inscriptions_pop_first(&self) -> crate::Result<()> { - todo!() + pub(crate) fn satpoint_to_sequence_number_insert(&mut self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { + self.sequence_number_to_satpoint.insert(sequence, sat_point)?; + // let key = rmp_serde::to_vec(sat_point).unwrap(); + // let value = sequence.to_le_bytes().as_slice(); + // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + Ok(()) } - pub(crate) fn home_inscriptions_insert(&self, p0: &u32, p1: InscriptionIdValue) -> crate::Result<()> { - todo!() + pub(crate) fn home_inscriptions_pop_first(&mut self) -> crate::Result<()> { + self.home_inscriptions.pop_first()?; + // self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { + // v.pop_first() + // }); + // Ok(()) + Ok(()) } - pub(crate) fn id_to_sequence_number_insert(&self, p0: &InscriptionIdValue, p1: u32) -> crate::Result<()> { - todo!() + pub(crate) fn home_inscriptions_insert(&mut self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { + // let key = sequnce_number.to_le_bytes().as_slice(); + // let value = rmp_serde::to_vec(&value).unwrap(); + // self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + self + .home_inscriptions + .insert(sequence_number, value)?; + Ok(()) } - pub(crate) fn sequence_number_to_children_insert(&self, p0: &u32, p1: &InscriptionIdValue) -> crate::Result<()> { - todo!() + pub(crate) fn id_to_sequence_number_insert(&mut self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { + // let key = rmp_serde::to_vec(value).unwrap(); + // let value = sequence.to_le_bytes().as_slice(); + // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + self + .id_to_sequence_number + .insert(value, sequence_number)?; + Ok(()) } - pub(crate) fn sequence_number_to_entry_insert(&self, p0: &u32, p1: &InscriptionEntryValue) -> crate::Result<()> { - todo!() + pub(crate) fn sequence_number_to_children_insert(&mut self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { + // let key = sequence.to_le_bytes().as_slice(); + // let value = rmp_serde::to_vec(value).unwrap(); + // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_CHILDREN, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + self + .sequence_number_to_children + .insert(parent_sequence_number, sequence_number)?; + Ok(()) } - pub(crate) fn sat_to_sequence_number_insert(&self, p0: &u64, p1: &u32) -> crate::Result<()> { - todo!() + pub(crate) fn sequence_number_to_entry_insert(&mut self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { + // let key = sequence.to_le_bytes().as_slice(); + // let value = rmp_serde::to_vec(value).unwrap(); + // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + self.sequence_number_to_entry.insert(sequence, value)?; + Ok(()) } - pub(crate) fn inscription_number_to_sequence_number_insert(&self, p0: i32, p1: u32) -> crate::Result<()> { - todo!() + pub(crate) fn sat_to_sequence_number_insert(&mut self, n: &u64, sequence_number: &u32) -> crate::Result<()> { + // let key = n.to_le_bytes().as_slice(); + // let value = sequence.to_le_bytes().as_slice(); + // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + self.sat_to_sequence_number.insert(n, sequence_number)?; + Ok(()) } - pub(crate) fn outpoint_to_entry_insert(&self, p0: &OutPointValue, p1: &[u8]) -> crate::Result<()> { - todo!() + pub(crate) fn inscription_number_to_sequence_number_insert(&mut self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { + // let key = inscription_number.to_le_bytes().as_slice(); + // let value = sequence_number.to_le_bytes().as_slice(); + // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + self + .inscription_number_to_sequence_number + .insert(inscription_number, sequence_number)?; + Ok(()) } - pub fn inscriptions_on_output_ordered(&self, prev_output: &OutPoint) -> crate::Result> { - todo!() + pub(crate) fn outpoint_to_entry_insert(&mut self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { + self.outpoint_to_entry.insert(value, entry)?; + Ok(()) + // let key = rmp_serde::to_vec(value).unwrap(); + // let value = entry.to_vec(); + // self.cache_writer.use_cache_mut(CacheTableIndex::OUTPOINT_TO_ENTRY, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) } - pub fn satpoint_to_id_remove_all(&self, x: &SatPointValue) -> crate::Result<()> { + pub fn inscriptions_on_output(&mut self, prev_output: &OutPoint) -> crate::Result> { + let ret = Index::inscriptions_on_output( + self.satpoint_to_sequence_number, + self.sequence_number_to_entry, + prev_output.clone())?; + // TODO: twice todo!() } - pub(crate) fn transaction_id_to_transaction_insert(&self, p0: &Txid, p1: &Vec) -> crate::Result<()> { - todo!() + pub(crate) fn transaction_id_to_transaction_insert(&mut self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { + self + .transaction_id_to_transaction + .insert(tx_id, value)?; + + Ok(()) } pub(crate) fn id_to_sequence_number_get(&self, x: InscriptionIdValue) -> crate::Result> { - todo!() + // TODO,twice + let ret = self.id_to_sequence_number.get(x)?.unwrap().value(); + Ok(Some(ret)) } pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { - todo!() + // TODO: twice + let ret = self + .sequence_number_to_entry + .get(initial_inscription_sequence_number)? + .unwrap() + .value(); + Ok(Some(ret)) } } -pub(super) struct PendingUpdater<'a> { - processor: &'a mut StorageProcessor, +pub struct PendingUpdater<'a, 'db, 'tx> { + processor: &'a mut PendingStorageProcessor<'a, 'db, 'tx>, pub(super) operations: &'a mut HashMap>, pub(super) blessed_inscription_count: u64, pub(super) chain: Chain, @@ -81,8 +202,8 @@ pub(super) struct PendingUpdater<'a> { pub(super) new_outpoints: Vec, } -impl<'a> PendingUpdater<'a> { - pub(super) fn new( +impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { + pub fn new( operations: &'a mut HashMap>, blessed_inscription_count: u64, chain: Chain, @@ -95,10 +216,31 @@ impl<'a> PendingUpdater<'a> { unbound_inscriptions: u64, tx_out_receiver: &'a mut Receiver, tx_out_cache: &'a mut SimpleLru, + processor: &'a mut PendingStorageProcessor<'a, 'db, 'tx>, ) -> Result { - todo!() + let home_inscriptions_len = processor.home_inscriptions_len(); + Ok(Self { + processor, + operations, + blessed_inscription_count, + chain, + cursed_inscription_count, + flotsam: vec![], + height, + home_inscription_count: home_inscriptions_len, + index_transactions, + next_sequence_number, + lost_sats, + reward: Height(height).subsidy(), + transaction_buffer: vec![], + timestamp, + unbound_inscriptions, + tx_out_receiver, + tx_out_cache, + new_outpoints: vec![], + }) } - pub(super) fn index_envelopes( + pub fn index_envelopes( &mut self, tx: &Transaction, txid: Txid, @@ -124,7 +266,7 @@ impl<'a> PendingUpdater<'a> { // find existing inscriptions on input (transfers of inscriptions) - for (old_satpoint, inscription_id) in self.processor.inscriptions_on_output_ordered(&tx_in.previous_output)? { + for (old_satpoint, inscription_id) in self.processor.inscriptions_on_output(&tx_in.previous_output)? { let offset = total_input_value + old_satpoint.offset; floating_inscriptions.push(Flotsam { txid, @@ -259,7 +401,7 @@ impl<'a> PendingUpdater<'a> { if self.index_transactions && inscriptions { tx.consensus_encode(&mut self.transaction_buffer) .expect("in-memory writers don't error"); - self.processor.transaction_id_to_transaction_insert(&txid, &self.transaction_buffer)?; + self.processor.transaction_id_to_transaction_insert(&txid.store(), self.transaction_buffer.as_slice())?; self.transaction_buffer.clear(); } @@ -393,7 +535,7 @@ impl<'a> PendingUpdater<'a> { } // write tx_out to outpoint_to_entry table - pub(super) fn flush_cache(self) -> Result { + pub fn flush_cache(self) -> Result { let start = Instant::now(); let persist = self.new_outpoints.len(); let mut entry = Vec::new(); @@ -440,12 +582,15 @@ impl<'a> PendingUpdater<'a> { let inscription_id = flotsam.inscription_id; let (unbound, sequence_number) = match flotsam.origin { Origin::Old => { - self.processor - .satpoint_to_id_remove_all(&flotsam.old_satpoint.store())?; + self + .processor.satpoint_to_sequence_number_remove_all(&flotsam.old_satpoint.store())?; ( false, - self.processor.id_to_sequence_number_get(inscription_id.store())?.unwrap(), + self + .processor.id_to_sequence_number_get( + inscription_id.store())? + .unwrap() ) } Origin::New { @@ -475,7 +620,9 @@ impl<'a> PendingUpdater<'a> { let sequence_number = self.next_sequence_number; self.next_sequence_number += 1; - self.processor.inscription_number_to_sequence_number_insert(inscription_number, sequence_number)?; + self + .processor.inscription_number_to_sequence_number_insert( + inscription_number, sequence_number)?; let sat = if unbound { None @@ -529,30 +676,21 @@ impl<'a> PendingUpdater<'a> { let parent = match parent { Some(parent_id) => { - let parent_sequence_number = self.processor.id_to_sequence_number_get(parent_id.store())?.unwrap(); - self.processor.sequence_number_to_children_insert(&parent_sequence_number, &inscription_id.store())?; + let parent_sequence_number = self + .processor.id_to_sequence_number_get( + parent_id.store())? + .unwrap(); + self + .processor.sequence_number_to_children_insert( + parent_sequence_number, sequence_number)?; Some(parent_sequence_number) } None => None, }; + self.processor.sequence_number_to_entry_insert( - &sequence_number, - &InscriptionEntry { - charms, - fee, - height: self.height, - id: inscription_id, - inscription_number, - parent, - sat, - sequence_number, - timestamp: self.timestamp, - } - .store(), - )?; - self.processor.sequence_number_to_entry_insert( - &sequence_number, + sequence_number, &InscriptionEntry { charms, fee, @@ -566,10 +704,15 @@ impl<'a> PendingUpdater<'a> { } .store(), )?; - self.processor.id_to_sequence_number_insert(&inscription_id.store(), sequence_number)?; + + self + .processor.id_to_sequence_number_insert( + &inscription_id.store(), sequence_number)?; if !hidden { - self.processor.home_inscriptions_insert(&sequence_number, inscription_id.store())?; + self + .processor.home_inscriptions_insert( + &sequence_number, inscription_id.store())?; if self.home_inscription_count == 100 { self.processor.home_inscriptions_pop_first()?; @@ -601,7 +744,8 @@ impl<'a> PendingUpdater<'a> { txid: flotsam.txid, sequence_number, inscription_number: self - .processor.sequence_number_to_entry_get(sequence_number)? + .processor.sequence_number_to_entry_get( + sequence_number)? .map(|entry| InscriptionEntry::load(entry).inscription_number), inscription_id: flotsam.inscription_id, action: match flotsam.origin { @@ -627,8 +771,12 @@ impl<'a> PendingUpdater<'a> { new_satpoint: Some(Entry::load(satpoint)), }); - self.processor.satpoint_to_sequence_number_insert(&new_satpoint, &sequence_number)?; - self.processor.sequence_number_to_satpoint_insert(&sequence_number, &new_satpoint)?; + self + .processor.satpoint_to_sequence_number_insert( + &satpoint, sequence_number)?; + self + .processor.sequence_number_to_satpoint_insert( + sequence_number, &satpoint)?; Ok(()) } diff --git a/src/okx/datastore/brc20/redb/mod.rs b/src/okx/datastore/brc20/redb/mod.rs index f1eca52d71..4e9f16020e 100644 --- a/src/okx/datastore/brc20/redb/mod.rs +++ b/src/okx/datastore/brc20/redb/mod.rs @@ -4,7 +4,7 @@ mod pending; use super::{LowerTick, ScriptKey, Tick}; use crate::inscriptions::InscriptionId; -fn script_tick_id_key(script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> String { +pub fn script_tick_id_key(script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> String { format!( "{}_{}_{}", script, @@ -22,7 +22,7 @@ fn max_script_tick_id_key(script: &ScriptKey, tick: &Tick) -> String { format!("{}_{}_g", script, tick.to_lowercase().hex()) } -fn script_tick_key(script: &ScriptKey, tick: &Tick) -> String { +pub fn script_tick_key(script: &ScriptKey, tick: &Tick) -> String { format!("{}_{}", script, tick.to_lowercase().hex()) } diff --git a/src/okx/datastore/brc20/tick.rs b/src/okx/datastore/brc20/tick.rs index ed6533f055..11643835b1 100644 --- a/src/okx/datastore/brc20/tick.rs +++ b/src/okx/datastore/brc20/tick.rs @@ -4,7 +4,7 @@ use std::{fmt::Formatter, str::FromStr}; pub const TICK_BYTE_COUNT: usize = 4; -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord,Hash)] pub struct Tick([u8; TICK_BYTE_COUNT]); impl FromStr for Tick { diff --git a/src/okx/datastore/cache.rs b/src/okx/datastore/cache.rs index 9276e81952..8094faedf9 100644 --- a/src/okx/datastore/cache.rs +++ b/src/okx/datastore/cache.rs @@ -9,6 +9,15 @@ use crate::Index; pub enum CacheTableIndex { TXID_TO_INSCRIPTION_RECEIPTS, + SEQUENCE_NUMBER_TO_SATPOINT, + SAT_TO_SEQUENCE_NUMBER, + HOME_INSCRIPTIONS, + INSCRIPTION_ID_TO_SEQUENCE_NUMBER, + SEQUENCE_NUMBER_TO_CHILDREN, + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, + INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, + OUTPOINT_TO_ENTRY, + BRC20_BALANCES, BRC20_TOKEN, BRC20_EVENTS, @@ -29,6 +38,15 @@ pub struct CacheTable { pub data: HashMap, Vec>, } +impl CacheTable{ + pub fn insert(&mut self, key: Vec, value: Vec) { + self.data.insert(key, value); + } + pub fn pop_first(&mut self){ + + } +} + #[derive(Clone)] pub struct CacheWriter { cache: Rc>>, diff --git a/src/okx/protocol/mod.rs b/src/okx/protocol/mod.rs index 1f15537b70..86e1b6b36b 100644 --- a/src/okx/protocol/mod.rs +++ b/src/okx/protocol/mod.rs @@ -6,6 +6,7 @@ pub(crate) mod ord; pub(crate) mod protocol_manager; pub(crate) mod resolve_manager; mod simulate; +pub mod trace; pub use self::protocol_manager::ProtocolManager; diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index b546ce670e..09e6f4b301 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -1,6 +1,398 @@ -use crate::okx::datastore::cache::CacheWriter; +use std::collections::HashMap; +use std::sync::Arc; +use bitcoin::{OutPoint, Txid, TxOut}; +use redb::{Database, ReadableTable, ReadOnlyTable, ReadTransaction, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; +use tempfile::NamedTempFile; +use crate::{Index, InscriptionId}; +use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionIdValue, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY}; +use crate::index::entry::Entry; +use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; +use crate::okx::datastore::brc20::redb::{script_tick_id_key, script_tick_key}; +use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick}; +use crate::okx::datastore::cache::CacheTableIndex; +use crate::okx::datastore::ScriptKey; +use crate::okx::lru::SimpleLru; +use crate::okx::protocol::BlockContext; +use crate::okx::protocol::context::Context; +use crate::okx::protocol::trace::{BalanceDelta, IndexTracer, MintTokenInfoDelta, string_to_bytes, TraceNode}; -// pub struct SimulateContext { -// cache_writer: CacheWriter, -// } +pub struct SimulateContext { + // simulate: Context, + internal_index: Arc, + simulate_index: IndexTracer, +} + +impl SimulateContext { + pub fn new( + internal_index: Arc, simulate_index: IndexTracer) -> crate::Result { + // let mut simulate_tx = simulate_index.begin_write()?; + // let ctx = Context { + // chain, + // tx_out_cache, + // hit: 0, + // miss: 0, + // ORD_TX_TO_OPERATIONS: &mut simulate_tx.open_table(ORD_TX_TO_OPERATIONS)?, + // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut simulate_tx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, + // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut simulate_tx.open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, + // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut simulate_tx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?, + // OUTPOINT_TO_ENTRY: &mut simulate_tx.open_table(OUTPOINT_TO_ENTRY)?, + // BRC20_BALANCES: &mut simulate_tx.open_table(BRC20_BALANCES)?, + // BRC20_TOKEN: &mut simulate_tx.open_table(BRC20_TOKEN)?, + // BRC20_EVENTS: &mut simulate_tx.open_table(BRC20_EVENTS)?, + // BRC20_TRANSFERABLELOG: &mut simulate_tx.open_table(BRC20_TRANSFERABLELOG)?, + // BRC20_INSCRIBE_TRANSFER: &mut simulate_tx.open_table(BRC20_INSCRIBE_TRANSFER)?, + // }; + Ok(Self { + // simulate: ctx, + internal_index, + simulate_index, + }) + } +} + +impl SimulateContext { + fn use_internal_table(&self, + table_def: TableDefinition, + f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { + let rtx = self.internal_index.begin_read()?; + let table = rtx.0.open_table(table_def)?; + let ret = f(table); + ret + } + + pub fn use_read_simulate_table(&self, + table_def: TableDefinition, + f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { + let rtx = self.simulate_index.index.begin_read()?; + let table = rtx.0.open_table(table_def)?; + let ret = f(table); + ret + } + pub fn use_write_simulate_table(&self, + table_def: TableDefinition, + f: impl FnOnce(Table) -> crate::Result) -> crate::Result { + let rtx = self.simulate_index.index.begin_write()?; + let table = rtx.open_table(table_def)?; + let ret = f(table); + ret + } +} + +impl Brc20Reader for SimulateContext { + type Error = anyhow::Error; + + fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { + let simulate = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { + get_balances(&table, script_key) + })?; + let mut simulate_balances: HashMap = simulate.into_iter() + .map(|v| { + (v.tick.clone(), v.clone()) + }).collect(); + let internal = self.use_internal_table(BRC20_BALANCES, |v| { + get_balances(&v, script_key) + })?; + for node in internal { + let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); + v.transferable_balance = v.transferable_balance + node.transferable_balance; + v.overall_balance = v.overall_balance + node.overall_balance; + } + let ret = simulate_balances + .into_iter() + .map(|(k, v)| { + v.clone() + }).collect(); + Ok(ret) + } + + fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { + let ret = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { + get_balance(&table, script_key, tick) + })?; + if let Some(ret) = ret { + return Ok(Some(ret)); + } + self.use_internal_table(BRC20_BALANCES, |table| { + get_balance(&table, script_key, tick) + }) + } + + fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { + let ret = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { + get_token_info(&table, tick) + })?; + if let Some(ret) = ret { + return Ok(Some(ret)); + } + self.use_internal_table(BRC20_TOKEN, |table| { + get_token_info(&table, tick) + }) + } + + fn get_tokens_info(&self) -> crate::Result, Self::Error> { + let simulate = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { + get_tokens_info(&table) + })?; + let internal = self.use_internal_table(BRC20_TOKEN, |table| { + get_tokens_info(&table) + })?; + // TODO:merge + todo!() + } + + fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { + let simulate = self.simulate_index.use_read_table(BRC20_EVENTS, |table| { + get_transaction_receipts(&table, txid) + })?; + let internal = self.use_internal_table(BRC20_EVENTS, |table| { + get_transaction_receipts(&table, txid) + })?; + // TODO:merge + todo!() + } + + fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { + let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable(&table, script) + })?; + let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable(&table, script) + })?; + // TODO: merge + todo!() + } + + + fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { + let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable_by_tick(&table, script, tick) + })?; + let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable_by_tick(&table, script, tick) + })?; + // TODO:merge + todo!() + } + + fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { + let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable_by_id(&table, script, inscription_id) + })?; + if let Some(ret) = simulate { + return Ok(Some(ret)); + } + self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable_by_id(&table, script, inscription_id) + }) + } + + fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { + let simulate = self.simulate_index.use_read_table(BRC20_INSCRIBE_TRANSFER, |table| { + get_inscribe_transfer_inscription(&table, inscription_id) + })?; + if let Some(ret) = simulate { + return Ok(Some(ret)); + } + self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { + get_inscribe_transfer_inscription(&table, inscription_id) + }) + } +} + +impl Brc20ReaderWriter for SimulateContext { + fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { + self.simulate_index + .use_write_table(BRC20_BALANCES, |mut table| { + let binding = script_tick_key(script_key, &new_balance.tick); + let key = binding.as_str(); + let binding = rmp_serde::to_vec(&new_balance).unwrap(); + let value = binding.as_slice(); + // let origin = table.get(key)?.map_or(None, |v| { + // Some(v.value().to_vec()) + // }); + table.insert(key, value)?; + // let mut delta = BalanceDelta::default(); + // if let Some(origin) = origin { + // let origin: Balance = rmp_serde::from_slice(&origin).unwrap(); + // delta.origin_transferable_balance_delta = origin.transferable_balance; + // delta.origin_overall_balance_delta = origin.overall_balance; + // delta.new_overall_balance_delta = new_balance.overall_balance; + // delta.new_transferable_balance_delta = new_balance.transferable_balance; + // } else { + // delta.origin_transferable_balance_delta = 0; + // delta.origin_overall_balance_delta = 0; + // delta.new_overall_balance_delta = new_balance.overall_balance; + // delta.new_transferable_balance_delta = new_balance.transferable_balance; + // } + // let op = TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()); + let node = TraceNode { trace_type: CacheTableIndex::BRC20_BALANCES, key: string_to_bytes(key) }; + Ok(((), node)) + })?; + Ok(()) + } + + fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { + self.simulate_index + .use_write_table(BRC20_TOKEN, |mut table| { + let binding = tick.to_lowercase().hex(); + let key = binding.as_str(); + let binding = rmp_serde::to_vec(new_info).unwrap(); + let value = binding.as_slice(); + table.insert(key, value)?; + + let trace = TraceNode { + trace_type: CacheTableIndex::BRC20_TOKEN, + // operation: TraceOperation::Insert, + key: string_to_bytes(key), + }; + Ok(((), trace)) + })?; + Ok(()) + } + + + fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { + let mut info = self.get_token_info(tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); + let origin = info.minted; + info.minted = minted_amt; + info.latest_mint_number = minted_block_number; + self.simulate_index + .use_write_table(BRC20_TOKEN, |mut table| { + let binding = tick.to_lowercase().hex(); + let key = binding.as_str(); + let binding = rmp_serde::to_vec(&info).unwrap(); + let value = binding.as_slice(); + table.insert(key, value)?; + // let delta = MintTokenInfoDelta { + // origin_minted: origin, + // new_minted: info.minted, + // new_latest_mint_number: minted_block_number, + // }; + let trace = TraceNode { + trace_type: CacheTableIndex::BRC20_TOKEN, + // operation: TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()), + key: string_to_bytes(key), + }; + Ok(((), trace)) + })?; + Ok(()) + } + + fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { + self.simulate_index + .use_write_table(BRC20_EVENTS, |mut table| { + let tx_id_value = txid.store(); + let key = tx_id_value.to_vec(); + let binding = rmp_serde::to_vec(receipt).unwrap(); + let value = binding.as_slice(); + table.insert(&txid.store(), value)?; + let trace = TraceNode { + trace_type: CacheTableIndex::BRC20_EVENTS, + key, + }; + Ok(((), trace)) + })?; + Ok(()) + // self.simulate.save_transaction_receipts(txid, receipt) + } + + fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { + self.simulate_index + .use_write_table(BRC20_TRANSFERABLELOG, |mut table| { + let binding = script_tick_id_key(script, tick, &inscription.inscription_id); + let key = binding.as_str(); + let binding = rmp_serde::to_vec(inscription).unwrap(); + let value = binding.as_slice(); + table.insert(key, value)?; + let trace = TraceNode { + trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, + key: string_to_bytes(key), + }; + Ok(((), trace)) + })?; + Ok(()) + } + + fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { + self.simulate_index.use_write_table(BRC20_TRANSFERABLELOG, |mut table| { + let binding = script_tick_id_key(script, tick, inscription_id); + let key = binding.as_str(); + table.remove(key)?; + let trace = TraceNode { + trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, + key: string_to_bytes(key), + }; + Ok(((), trace)) + })?; + Ok(()) + } + + fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { + self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { + let key = inscription_id.store(); + let key_bytes = InscriptionIdValue::as_bytes(&key); + let binding = rmp_serde::to_vec(&transfer_info).unwrap(); + let value = binding.as_slice(); + table.insert(&key, value)?; + let trace = TraceNode { + trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, + key: key_bytes, + }; + Ok(((), trace)) + })?; + Ok(()) + } + + fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { + self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { + let key = inscription_id.store(); + let key_bytes = InscriptionIdValue::as_bytes(&key); + table.remove(&key)?; + let trace = TraceNode { + trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, + key: key_bytes, + }; + Ok(((), trace)) + })?; + Ok(()) + } +} + +#[test] +pub fn test_asd() {} + +#[test] +fn test_write() { + let tmpfile = NamedTempFile::new().unwrap(); + let db = Database::builder() + .create(tmpfile.path()) + .unwrap(); + let table_definition: TableDefinition = TableDefinition::new("x"); + + { + let mut wtx = db.begin_write().unwrap(); + let mut table = wtx.open_table(table_definition).unwrap(); + table.insert(1, 1).unwrap(); + let vv=table.get(&1).unwrap().unwrap().value(); + assert_eq!(vv, 1); + } + + + { + let mut wtx = db.begin_write().unwrap(); + let mut table = wtx.open_table(table_definition).unwrap(); + table.insert(2, 2).unwrap(); + let vv=table.get(&2).unwrap().unwrap().value(); + assert_eq!(vv, 2); + let v1=table.get(&1).unwrap().unwrap().value(); + assert_eq!(v1, 1); + } + + // wtx.commit().unwrap(); + // { + // let rtx = db.begin_read().unwrap(); + // let table = rtx.open_table(table_definition).unwrap(); + // assert_eq!(table.get(&1).unwrap().unwrap().value(), 1); + // } +} diff --git a/src/okx/protocol/trace.rs b/src/okx/protocol/trace.rs new file mode 100644 index 0000000000..1d37519ced --- /dev/null +++ b/src/okx/protocol/trace.rs @@ -0,0 +1,65 @@ +use std::sync::Arc; +use redb::{ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition}; +use serde::{Deserialize, Serialize}; +use crate::{Index}; +use crate::okx::datastore::cache::CacheTableIndex; + +// pub enum TraceOperation { +// Update(Vec), +// Delete(Vec), +// Insert, +// } + +#[derive(Clone, Default, Serialize, Deserialize)] +pub struct BalanceDelta { + pub origin_overall_balance_delta: u128, + pub origin_transferable_balance_delta: u128, + pub new_overall_balance_delta: u128, + pub new_transferable_balance_delta: u128, +} + +#[derive(Clone, Default, Serialize, Deserialize)] +pub struct MintTokenInfoDelta { + pub origin_minted: u128, + pub new_minted: u128, + pub new_latest_mint_number: u32, +} + +#[derive(Clone)] +pub struct TraceNode { + pub trace_type: CacheTableIndex, + // pub operation: TraceOperation, + pub key: Vec, +} + +#[derive(Clone)] +pub struct IndexTracer { + pub index: Arc, + pub traces: Vec, +} + +pub fn string_to_bytes(s: &str) -> Vec { + let byte_slice: &[u8] = s.as_bytes(); + let byte_vec: Vec = byte_slice.to_vec(); + byte_vec +} + +impl IndexTracer { + pub fn use_read_table(&self, + table_def: TableDefinition, + f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { + let rtx = self.index.begin_read()?; + let table = rtx.0.open_table(table_def)?; + let ret = f(table); + ret + } + pub fn use_write_table(&mut self, + table_def: TableDefinition, + mut f: impl FnMut(Table) -> crate::Result<(T, TraceNode)>) -> crate::Result { + let rtx = self.index.begin_write()?; + let table = rtx.open_table(table_def)?; + let (ret, node) = f(table)?; + self.traces.push(node); + Ok(ret) + } +} \ No newline at end of file From ef4b0381eeb41b0e3d61fb1c990aec094e64c262 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 11 Jan 2024 11:44:02 +0800 Subject: [PATCH 05/66] fuck2 --- src/okx/protocol/simulate.rs | 497 ++++++++++++++++++++++------------- 1 file changed, 309 insertions(+), 188 deletions(-) diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index 09e6f4b301..9c1b242fb5 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -16,15 +16,15 @@ use crate::okx::protocol::BlockContext; use crate::okx::protocol::context::Context; use crate::okx::protocol::trace::{BalanceDelta, IndexTracer, MintTokenInfoDelta, string_to_bytes, TraceNode}; -pub struct SimulateContext { - // simulate: Context, +pub struct SimulateContext<'a, 'db, 'txn> { + simulate: Context<'a, 'db, 'txn>, internal_index: Arc, - simulate_index: IndexTracer, + // simulate_index: IndexTracer, } -impl SimulateContext { +impl<'a, 'db, 'txn> SimulateContext<'a, 'db, 'txn> { pub fn new( - internal_index: Arc, simulate_index: IndexTracer) -> crate::Result { + internal_index: Arc, simulate: Context<'a, 'db, 'txn>) -> crate::Result { // let mut simulate_tx = simulate_index.begin_write()?; // let ctx = Context { // chain, @@ -45,12 +45,12 @@ impl SimulateContext { Ok(Self { // simulate: ctx, internal_index, - simulate_index, + simulate, }) } } -impl SimulateContext { +impl<'a, 'db, 'txn> SimulateContext<'a, 'db, 'txn> { fn use_internal_table(&self, table_def: TableDefinition, f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { @@ -59,32 +59,293 @@ impl SimulateContext { let ret = f(table); ret } - - pub fn use_read_simulate_table(&self, - table_def: TableDefinition, - f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { - let rtx = self.simulate_index.index.begin_read()?; - let table = rtx.0.open_table(table_def)?; - let ret = f(table); - ret - } - pub fn use_write_simulate_table(&self, - table_def: TableDefinition, - f: impl FnOnce(Table) -> crate::Result) -> crate::Result { - let rtx = self.simulate_index.index.begin_write()?; - let table = rtx.open_table(table_def)?; - let ret = f(table); - ret - } } -impl Brc20Reader for SimulateContext { +// impl Brc20Reader for SimulateContext { +// type Error = anyhow::Error; +// +// fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { +// let simulate = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { +// get_balances(&table, script_key) +// })?; +// let mut simulate_balances: HashMap = simulate.into_iter() +// .map(|v| { +// (v.tick.clone(), v.clone()) +// }).collect(); +// let internal = self.use_internal_table(BRC20_BALANCES, |v| { +// get_balances(&v, script_key) +// })?; +// for node in internal { +// let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); +// v.transferable_balance = v.transferable_balance + node.transferable_balance; +// v.overall_balance = v.overall_balance + node.overall_balance; +// } +// let ret = simulate_balances +// .into_iter() +// .map(|(k, v)| { +// v.clone() +// }).collect(); +// Ok(ret) +// } +// +// fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { +// let ret = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { +// get_balance(&table, script_key, tick) +// })?; +// if let Some(ret) = ret { +// return Ok(Some(ret)); +// } +// self.use_internal_table(BRC20_BALANCES, |table| { +// get_balance(&table, script_key, tick) +// }) +// } +// +// fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { +// let ret = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { +// get_token_info(&table, tick) +// })?; +// if let Some(ret) = ret { +// return Ok(Some(ret)); +// } +// self.use_internal_table(BRC20_TOKEN, |table| { +// get_token_info(&table, tick) +// }) +// } +// +// fn get_tokens_info(&self) -> crate::Result, Self::Error> { +// let simulate = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { +// get_tokens_info(&table) +// })?; +// let internal = self.use_internal_table(BRC20_TOKEN, |table| { +// get_tokens_info(&table) +// })?; +// // TODO:merge +// todo!() +// } +// +// fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { +// let simulate = self.simulate_index.use_read_table(BRC20_EVENTS, |table| { +// get_transaction_receipts(&table, txid) +// })?; +// let internal = self.use_internal_table(BRC20_EVENTS, |table| { +// get_transaction_receipts(&table, txid) +// })?; +// // TODO:merge +// todo!() +// } +// +// fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { +// let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { +// get_transferable(&table, script) +// })?; +// let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// get_transferable(&table, script) +// })?; +// // TODO: merge +// todo!() +// } +// +// +// fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { +// let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { +// get_transferable_by_tick(&table, script, tick) +// })?; +// let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// get_transferable_by_tick(&table, script, tick) +// })?; +// // TODO:merge +// todo!() +// } +// +// fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { +// let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { +// get_transferable_by_id(&table, script, inscription_id) +// })?; +// if let Some(ret) = simulate { +// return Ok(Some(ret)); +// } +// self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// get_transferable_by_id(&table, script, inscription_id) +// }) +// } +// +// fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { +// let simulate = self.simulate_index.use_read_table(BRC20_INSCRIBE_TRANSFER, |table| { +// get_inscribe_transfer_inscription(&table, inscription_id) +// })?; +// if let Some(ret) = simulate { +// return Ok(Some(ret)); +// } +// self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { +// get_inscribe_transfer_inscription(&table, inscription_id) +// }) +// } +// } +// +// impl Brc20ReaderWriter for SimulateContext { +// fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { +// self.simulate_index +// .use_write_table(BRC20_BALANCES, |mut table| { +// let binding = script_tick_key(script_key, &new_balance.tick); +// let key = binding.as_str(); +// let binding = rmp_serde::to_vec(&new_balance).unwrap(); +// let value = binding.as_slice(); +// // let origin = table.get(key)?.map_or(None, |v| { +// // Some(v.value().to_vec()) +// // }); +// table.insert(key, value)?; +// // let mut delta = BalanceDelta::default(); +// // if let Some(origin) = origin { +// // let origin: Balance = rmp_serde::from_slice(&origin).unwrap(); +// // delta.origin_transferable_balance_delta = origin.transferable_balance; +// // delta.origin_overall_balance_delta = origin.overall_balance; +// // delta.new_overall_balance_delta = new_balance.overall_balance; +// // delta.new_transferable_balance_delta = new_balance.transferable_balance; +// // } else { +// // delta.origin_transferable_balance_delta = 0; +// // delta.origin_overall_balance_delta = 0; +// // delta.new_overall_balance_delta = new_balance.overall_balance; +// // delta.new_transferable_balance_delta = new_balance.transferable_balance; +// // } +// // let op = TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()); +// let node = TraceNode { trace_type: CacheTableIndex::BRC20_BALANCES, key: string_to_bytes(key) }; +// Ok(((), node)) +// })?; +// Ok(()) +// } +// +// fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { +// self.simulate_index +// .use_write_table(BRC20_TOKEN, |mut table| { +// let binding = tick.to_lowercase().hex(); +// let key = binding.as_str(); +// let binding = rmp_serde::to_vec(new_info).unwrap(); +// let value = binding.as_slice(); +// table.insert(key, value)?; +// +// let trace = TraceNode { +// trace_type: CacheTableIndex::BRC20_TOKEN, +// // operation: TraceOperation::Insert, +// key: string_to_bytes(key), +// }; +// Ok(((), trace)) +// })?; +// Ok(()) +// } +// +// +// fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { +// let mut info = self.get_token_info(tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); +// let origin = info.minted; +// info.minted = minted_amt; +// info.latest_mint_number = minted_block_number; +// self.simulate_index +// .use_write_table(BRC20_TOKEN, |mut table| { +// let binding = tick.to_lowercase().hex(); +// let key = binding.as_str(); +// let binding = rmp_serde::to_vec(&info).unwrap(); +// let value = binding.as_slice(); +// table.insert(key, value)?; +// // let delta = MintTokenInfoDelta { +// // origin_minted: origin, +// // new_minted: info.minted, +// // new_latest_mint_number: minted_block_number, +// // }; +// let trace = TraceNode { +// trace_type: CacheTableIndex::BRC20_TOKEN, +// // operation: TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()), +// key: string_to_bytes(key), +// }; +// Ok(((), trace)) +// })?; +// Ok(()) +// } +// +// fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { +// self.simulate_index +// .use_write_table(BRC20_EVENTS, |mut table| { +// let tx_id_value = txid.store(); +// let key = tx_id_value.to_vec(); +// let binding = rmp_serde::to_vec(receipt).unwrap(); +// let value = binding.as_slice(); +// table.insert(&txid.store(), value)?; +// let trace = TraceNode { +// trace_type: CacheTableIndex::BRC20_EVENTS, +// key, +// }; +// Ok(((), trace)) +// })?; +// Ok(()) +// // self.simulate.save_transaction_receipts(txid, receipt) +// } +// +// fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { +// self.simulate_index +// .use_write_table(BRC20_TRANSFERABLELOG, |mut table| { +// let binding = script_tick_id_key(script, tick, &inscription.inscription_id); +// let key = binding.as_str(); +// let binding = rmp_serde::to_vec(inscription).unwrap(); +// let value = binding.as_slice(); +// table.insert(key, value)?; +// let trace = TraceNode { +// trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, +// key: string_to_bytes(key), +// }; +// Ok(((), trace)) +// })?; +// Ok(()) +// } +// +// fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { +// self.simulate_index.use_write_table(BRC20_TRANSFERABLELOG, |mut table| { +// let binding = script_tick_id_key(script, tick, inscription_id); +// let key = binding.as_str(); +// table.remove(key)?; +// let trace = TraceNode { +// trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, +// key: string_to_bytes(key), +// }; +// Ok(((), trace)) +// })?; +// Ok(()) +// } +// +// fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { +// self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { +// let key = inscription_id.store(); +// let key_bytes = InscriptionIdValue::as_bytes(&key); +// let binding = rmp_serde::to_vec(&transfer_info).unwrap(); +// let value = binding.as_slice(); +// table.insert(&key, value)?; +// let trace = TraceNode { +// trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, +// key: key_bytes, +// }; +// Ok(((), trace)) +// })?; +// Ok(()) +// } +// +// fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { +// self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { +// let key = inscription_id.store(); +// let key_bytes = InscriptionIdValue::as_bytes(&key); +// table.remove(&key)?; +// let trace = TraceNode { +// trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, +// key: key_bytes, +// }; +// Ok(((), trace)) +// })?; +// Ok(()) +// } +// } + +impl<'a, 'db, 'txn> Brc20Reader for SimulateContext<'a, 'db, 'txn> { type Error = anyhow::Error; fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { - let simulate = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { - get_balances(&table, script_key) - })?; + let simulate = self.simulate.get_balances(script_key)?; let mut simulate_balances: HashMap = simulate.into_iter() .map(|v| { (v.tick.clone(), v.clone()) @@ -106,9 +367,7 @@ impl Brc20Reader for SimulateContext { } fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { - let ret = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { - get_balance(&table, script_key, tick) - })?; + let ret = self.simulate.get_balance(script_key, tick)?; if let Some(ret) = ret { return Ok(Some(ret)); } @@ -118,9 +377,7 @@ impl Brc20Reader for SimulateContext { } fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { - let ret = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { - get_token_info(&table, tick) - })?; + let ret = self.simulate.get_token_info(tick)?; if let Some(ret) = ret { return Ok(Some(ret)); } @@ -130,9 +387,7 @@ impl Brc20Reader for SimulateContext { } fn get_tokens_info(&self) -> crate::Result, Self::Error> { - let simulate = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { - get_tokens_info(&table) - })?; + let simulate = self.simulate.get_tokens_info()?; let internal = self.use_internal_table(BRC20_TOKEN, |table| { get_tokens_info(&table) })?; @@ -141,9 +396,7 @@ impl Brc20Reader for SimulateContext { } fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { - let simulate = self.simulate_index.use_read_table(BRC20_EVENTS, |table| { - get_transaction_receipts(&table, txid) - })?; + let simulate = self.simulate.get_transaction_receipts(txid)?; let internal = self.use_internal_table(BRC20_EVENTS, |table| { get_transaction_receipts(&table, txid) })?; @@ -152,9 +405,7 @@ impl Brc20Reader for SimulateContext { } fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { - let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { - get_transferable(&table, script) - })?; + let simulate = self.simulate.get_transferable(script)?; let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { get_transferable(&table, script) })?; @@ -164,9 +415,7 @@ impl Brc20Reader for SimulateContext { fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { - let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { - get_transferable_by_tick(&table, script, tick) - })?; + let simulate = self.simulate.get_transferable_by_tick(script, tick)?; let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { get_transferable_by_tick(&table, script, tick) })?; @@ -175,9 +424,7 @@ impl Brc20Reader for SimulateContext { } fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { - let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { - get_transferable_by_id(&table, script, inscription_id) - })?; + let simulate = self.simulate.get_transferable_by_id(script, inscription_id)?; if let Some(ret) = simulate { return Ok(Some(ret)); } @@ -187,9 +434,7 @@ impl Brc20Reader for SimulateContext { } fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { - let simulate = self.simulate_index.use_read_table(BRC20_INSCRIBE_TRANSFER, |table| { - get_inscribe_transfer_inscription(&table, inscription_id) - })?; + let simulate = self.simulate.get_inscribe_transfer_inscription(inscription_id)?; if let Some(ret) = simulate { return Ok(Some(ret)); } @@ -199,162 +444,38 @@ impl Brc20Reader for SimulateContext { } } -impl Brc20ReaderWriter for SimulateContext { +impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { - self.simulate_index - .use_write_table(BRC20_BALANCES, |mut table| { - let binding = script_tick_key(script_key, &new_balance.tick); - let key = binding.as_str(); - let binding = rmp_serde::to_vec(&new_balance).unwrap(); - let value = binding.as_slice(); - // let origin = table.get(key)?.map_or(None, |v| { - // Some(v.value().to_vec()) - // }); - table.insert(key, value)?; - // let mut delta = BalanceDelta::default(); - // if let Some(origin) = origin { - // let origin: Balance = rmp_serde::from_slice(&origin).unwrap(); - // delta.origin_transferable_balance_delta = origin.transferable_balance; - // delta.origin_overall_balance_delta = origin.overall_balance; - // delta.new_overall_balance_delta = new_balance.overall_balance; - // delta.new_transferable_balance_delta = new_balance.transferable_balance; - // } else { - // delta.origin_transferable_balance_delta = 0; - // delta.origin_overall_balance_delta = 0; - // delta.new_overall_balance_delta = new_balance.overall_balance; - // delta.new_transferable_balance_delta = new_balance.transferable_balance; - // } - // let op = TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()); - let node = TraceNode { trace_type: CacheTableIndex::BRC20_BALANCES, key: string_to_bytes(key) }; - Ok(((), node)) - })?; - Ok(()) + self.simulate.update_token_balance(script_key, new_balance) } fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { - self.simulate_index - .use_write_table(BRC20_TOKEN, |mut table| { - let binding = tick.to_lowercase().hex(); - let key = binding.as_str(); - let binding = rmp_serde::to_vec(new_info).unwrap(); - let value = binding.as_slice(); - table.insert(key, value)?; - - let trace = TraceNode { - trace_type: CacheTableIndex::BRC20_TOKEN, - // operation: TraceOperation::Insert, - key: string_to_bytes(key), - }; - Ok(((), trace)) - })?; - Ok(()) + self.simulate.insert_token_info(tick, new_info) } fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { - let mut info = self.get_token_info(tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); - let origin = info.minted; - info.minted = minted_amt; - info.latest_mint_number = minted_block_number; - self.simulate_index - .use_write_table(BRC20_TOKEN, |mut table| { - let binding = tick.to_lowercase().hex(); - let key = binding.as_str(); - let binding = rmp_serde::to_vec(&info).unwrap(); - let value = binding.as_slice(); - table.insert(key, value)?; - // let delta = MintTokenInfoDelta { - // origin_minted: origin, - // new_minted: info.minted, - // new_latest_mint_number: minted_block_number, - // }; - let trace = TraceNode { - trace_type: CacheTableIndex::BRC20_TOKEN, - // operation: TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()), - key: string_to_bytes(key), - }; - Ok(((), trace)) - })?; - Ok(()) + self.simulate.update_mint_token_info(tick, minted_amt, minted_block_number) } fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { - self.simulate_index - .use_write_table(BRC20_EVENTS, |mut table| { - let tx_id_value = txid.store(); - let key = tx_id_value.to_vec(); - let binding = rmp_serde::to_vec(receipt).unwrap(); - let value = binding.as_slice(); - table.insert(&txid.store(), value)?; - let trace = TraceNode { - trace_type: CacheTableIndex::BRC20_EVENTS, - key, - }; - Ok(((), trace)) - })?; - Ok(()) - // self.simulate.save_transaction_receipts(txid, receipt) + self.simulate.save_transaction_receipts(txid, receipt) } fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { - self.simulate_index - .use_write_table(BRC20_TRANSFERABLELOG, |mut table| { - let binding = script_tick_id_key(script, tick, &inscription.inscription_id); - let key = binding.as_str(); - let binding = rmp_serde::to_vec(inscription).unwrap(); - let value = binding.as_slice(); - table.insert(key, value)?; - let trace = TraceNode { - trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, - key: string_to_bytes(key), - }; - Ok(((), trace)) - })?; - Ok(()) + self.simulate.insert_transferable(script, tick, inscription) } fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - self.simulate_index.use_write_table(BRC20_TRANSFERABLELOG, |mut table| { - let binding = script_tick_id_key(script, tick, inscription_id); - let key = binding.as_str(); - table.remove(key)?; - let trace = TraceNode { - trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, - key: string_to_bytes(key), - }; - Ok(((), trace)) - })?; - Ok(()) + self.simulate.remove_transferable(script, tick, inscription_id) } fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { - self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { - let key = inscription_id.store(); - let key_bytes = InscriptionIdValue::as_bytes(&key); - let binding = rmp_serde::to_vec(&transfer_info).unwrap(); - let value = binding.as_slice(); - table.insert(&key, value)?; - let trace = TraceNode { - trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, - key: key_bytes, - }; - Ok(((), trace)) - })?; - Ok(()) + self.simulate.insert_inscribe_transfer_inscription(inscription_id, transfer_info) } fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { - let key = inscription_id.store(); - let key_bytes = InscriptionIdValue::as_bytes(&key); - table.remove(&key)?; - let trace = TraceNode { - trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, - key: key_bytes, - }; - Ok(((), trace)) - })?; - Ok(()) + self.simulate.remove_inscribe_transfer_inscription(inscription_id) } } @@ -373,7 +494,7 @@ fn test_write() { let mut wtx = db.begin_write().unwrap(); let mut table = wtx.open_table(table_definition).unwrap(); table.insert(1, 1).unwrap(); - let vv=table.get(&1).unwrap().unwrap().value(); + let vv = table.get(&1).unwrap().unwrap().value(); assert_eq!(vv, 1); } @@ -382,9 +503,9 @@ fn test_write() { let mut wtx = db.begin_write().unwrap(); let mut table = wtx.open_table(table_definition).unwrap(); table.insert(2, 2).unwrap(); - let vv=table.get(&2).unwrap().unwrap().value(); + let vv = table.get(&2).unwrap().unwrap().value(); assert_eq!(vv, 2); - let v1=table.get(&1).unwrap().unwrap().value(); + let v1 = table.get(&1).unwrap().unwrap().value(); assert_eq!(v1, 1); } From 9b6ac6d1d2f23ecf274ff0a36d23115ed2e72be3 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 11 Jan 2024 15:37:59 +0800 Subject: [PATCH 06/66] save --- src/index.rs | 1 + src/index/processor.rs | 190 ++++++++++++ src/index/simulate.rs | 370 ++++++++++++++++++----- src/index/updater/pending_updater.rs | 185 +----------- src/okx/datastore/cache.rs | 8 + src/okx/protocol/simulate.rs | 431 +++++++++++++++++++++------ 6 files changed, 851 insertions(+), 334 deletions(-) create mode 100644 src/index/processor.rs diff --git a/src/index.rs b/src/index.rs index d5573eff09..f142452026 100644 --- a/src/index.rs +++ b/src/index.rs @@ -53,6 +53,7 @@ pub(crate) mod updater; #[cfg(test)] pub(crate) mod testing; mod simulate; +mod processor; const SCHEMA_VERSION: u64 = 16; diff --git a/src/index/processor.rs b/src/index/processor.rs new file mode 100644 index 0000000000..906c9c093a --- /dev/null +++ b/src/index/processor.rs @@ -0,0 +1,190 @@ +use std::sync::Arc; +use bitcoin::{OutPoint, TxOut}; +use redb::RedbValue; +use crate::{Index, InscriptionId, SatPoint}; +use crate::index::entry::SatPointValue; +use crate::index::{InscriptionEntryValue, InscriptionIdValue, OutPointValue, TxidValue}; +use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; + +#[derive(Clone)] +pub struct StorageProcessor { + pub cache_writer: CacheWriter, + pub internal: Arc, +} + +impl StorageProcessor { + + pub fn get_lost_sats(&self)->crate::Result{ + todo!() + } + pub fn get_cursed_inscription_count(&self)->crate::Result{ + todo!() + } + pub fn get_blessed_inscription_count(&self)->crate::Result{ + todo!() + } + pub fn get_unbound_inscriptions(&self)->crate::Result{ + todo!() + } + pub fn get_next_sequence_number(&self)->crate::Result{ + todo!() + } + pub fn sat_to_satpoint_insert(&mut self,key:&u64,value:&SatPointValue)->crate::Result<()>{ + todo!() + } + pub fn get_txout_by_outpoint(&self, x: &OutPoint)->crate::Result>{ + todo!() + } + pub(crate) fn satpoint_to_sequence_number_remove_all(&mut self, v: &SatPointValue) -> crate::Result<()> { + // self + // .satpoint_to_sequence_number + // .remove_all(v)?; + // Ok(()) + todo!() + } + pub(crate) fn home_inscriptions_len(&self) -> u64 { + todo!() + } + pub(crate) fn sequence_number_to_satpoint_insert(&mut self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { + // self.sequence_number_to_satpoint.insert(sequence_number, sat_point)?; + + let key = u32::as_bytes(&sequence_number).to_vec(); + let value = sat_point.to_vec(); + self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_SATPOINT, |v| { + v.insert(key.to_vec(), value.to_vec()); + }); + Ok(()) + } + pub(crate) fn satpoint_to_sequence_number_insert(&mut self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { + // self.sequence_number_to_satpoint.insert(sequence, sat_point)?; + + let key = sat_point.to_vec(); + let value = u32::as_bytes(&sequence).to_vec(); + self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { + v.insert(key.to_vec(), value.to_vec()); + }); + Ok(()) + } + pub(crate) fn home_inscriptions_pop_first(&mut self) -> crate::Result<()> { + // self.home_inscriptions.pop_first()?; + + self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { + v.pop_first() + }); + Ok(()) + } + pub(crate) fn home_inscriptions_insert(&mut self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { + let key = u32::as_bytes(sequence_number).to_vec(); + let value = InscriptionIdValue::as_bytes(&value).to_vec(); + self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { + v.insert(key.to_vec(), value.to_vec()); + }); + Ok(()) + // self + // .home_inscriptions + // .insert(sequence_number, value)?; + // Ok(()) + } + pub(crate) fn id_to_sequence_number_insert(&mut self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { + // let key = rmp_serde::to_vec(value).unwrap(); + // let value = sequence.to_le_bytes().as_slice(); + // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + // self + // .id_to_sequence_number + // .insert(value, sequence_number)?; + Ok(()) + } + pub(crate) fn sequence_number_to_children_insert(&mut self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { + // let key = sequence.to_le_bytes().as_slice(); + // let value = rmp_serde::to_vec(value).unwrap(); + // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_CHILDREN, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + // self + // .sequence_number_to_children + // .insert(parent_sequence_number, sequence_number)?; + Ok(()) + } + pub(crate) fn sequence_number_to_entry_insert(&mut self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { + // let key = sequence.to_le_bytes().as_slice(); + // let value = rmp_serde::to_vec(value).unwrap(); + // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + // self.sequence_number_to_entry.insert(sequence, value)?; + Ok(()) + } + pub(crate) fn sat_to_sequence_number_insert(&mut self, n: &u64, sequence_number: &u32) -> crate::Result<()> { + // let key = n.to_le_bytes().as_slice(); + // let value = sequence.to_le_bytes().as_slice(); + // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + // self.sat_to_sequence_number.insert(n, sequence_number)?; + Ok(()) + } + pub(crate) fn inscription_number_to_sequence_number_insert(&mut self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { + // let key = inscription_number.to_le_bytes().as_slice(); + // let value = sequence_number.to_le_bytes().as_slice(); + // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + // self + // .inscription_number_to_sequence_number + // .insert(inscription_number, sequence_number)?; + Ok(()) + } + pub(crate) fn outpoint_to_entry_insert(&mut self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { + // self.outpoint_to_entry.insert(value, entry)?; + Ok(()) + // let key = rmp_serde::to_vec(value).unwrap(); + // let value = entry.to_vec(); + // self.cache_writer.use_cache_mut(CacheTableIndex::OUTPOINT_TO_ENTRY, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); + // Ok(()) + } + pub fn inscriptions_on_output(&mut self, prev_output: &OutPoint) -> crate::Result> { + // let ret = Index::inscriptions_on_output( + // self.satpoint_to_sequence_number, + // self.sequence_number_to_entry, + // prev_output.clone())?; + // TODO: twice + todo!() + } + + pub(crate) fn transaction_id_to_transaction_insert(&mut self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { + // self + // .transaction_id_to_transaction + // .insert(tx_id, value)?; + + Ok(()) + } + + pub(crate) fn id_to_sequence_number_get(&self, x: InscriptionIdValue) -> crate::Result> { + // TODO,twice + // let ret = self.id_to_sequence_number.get(x)?.unwrap().value(); + // Ok(Some(ret)) + todo!() + } + pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { + // TODO: twice + // let ret = self + // .sequence_number_to_entry + // .get(initial_inscription_sequence_number)? + // .unwrap() + // .value(); + // Ok(Some(ret)) + todo!() + } + pub fn new(cache_writer: CacheWriter, internal: Arc) -> Self { + Self { cache_writer, internal } + } +} \ No newline at end of file diff --git a/src/index/simulate.rs b/src/index/simulate.rs index 6a96456a99..433c42a540 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -11,7 +11,9 @@ use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; use crate::height::Height; use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; use crate::index::entry::{Entry, SatPointValue, SatRange}; +use crate::index::processor::StorageProcessor; use crate::index::updater::pending_updater::PendingUpdater; +use crate::okx::datastore::cache::CacheWriter; use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::lru::SimpleLru; use crate::okx::protocol::{BlockContext, ProtocolConfig, ProtocolManager}; @@ -22,11 +24,299 @@ pub struct Simulator { options: Options, simulate_index: IndexTracer, internal_index: Arc, + processor: StorageProcessor, } impl Simulator { pub fn simulate_tx(&self) {} + // fn index_block( + // &mut self, + // index: &Index, + // height: u32, + // outpoint_sender: &mut Sender, + // tx_out_receiver: &mut Receiver, + // block: BlockData, + // tx_out_cache: &mut SimpleLru, + // wtx: &mut WriteTransaction, + // ) -> crate::Result<()> { + // let start = Instant::now(); + // let mut sat_ranges_written = 0; + // let mut outputs_in_block = 0; + // + // // If value_receiver still has values something went wrong with the last block + // // Could be an assert, shouldn't recover from this and commit the last block + // let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { + // return Err(anyhow!("Previous block did not consume all input values")); + // }; + // + // let mut outpoint_to_entry = wtx.open_table(OUTPOINT_TO_ENTRY)?; + // + // let index_inscriptions = true; + // + // let fetching_outputs_count = AtomicUsize::new(0); + // let total_outputs_count = AtomicUsize::new(0); + // let cache_outputs_count = AtomicUsize::new(0); + // let miss_outputs_count = AtomicUsize::new(0); + // let meet_outputs_count = AtomicUsize::new(0); + // if index_inscriptions { + // // Send all missing input outpoints to be fetched right away + // let txids = block + // .txdata + // .iter() + // .map(|(_, txid)| txid) + // .collect::>(); + // use rayon::prelude::*; + // let tx_outs = block + // .txdata + // .par_iter() + // .flat_map(|(tx, _)| tx.input.par_iter()) + // .filter_map(|input| { + // total_outputs_count.fetch_add(1, Ordering::Relaxed); + // let prev_output = input.previous_output; + // // We don't need coinbase input value + // if prev_output.is_null() { + // None + // } else if txids.contains(&prev_output.txid) { + // meet_outputs_count.fetch_add(1, Ordering::Relaxed); + // None + // } else if tx_out_cache.contains(&prev_output) { + // cache_outputs_count.fetch_add(1, Ordering::Relaxed); + // None + // } else if let Some(txout) = + // get_txout_by_outpoint(&outpoint_to_entry, &prev_output).unwrap() + // { + // miss_outputs_count.fetch_add(1, Ordering::Relaxed); + // Some((prev_output, Some(txout))) + // } else { + // fetching_outputs_count.fetch_add(1, Ordering::Relaxed); + // Some((prev_output, None)) + // } + // }) + // .collect::>(); + // for (out_point, value) in tx_outs.into_iter() { + // if let Some(tx_out) = value { + // tx_out_cache.insert(out_point, tx_out); + // } else { + // outpoint_sender.blocking_send(out_point).unwrap(); + // } + // } + // } + // + // let time = timestamp(block.header.time); + // + // log::info!( + // "Block {} at {} with {} transactions, fetching previous outputs {}/{}…, {},{},{}, cost:{}ms", + // height, + // time, + // block.txdata.len(), + // fetching_outputs_count.load(Ordering::Relaxed), + // total_outputs_count.load(Ordering::Relaxed), + // miss_outputs_count.load(Ordering::Relaxed), + // meet_outputs_count.load(Ordering::Relaxed), + // cache_outputs_count.load(Ordering::Relaxed), + // start.elapsed().as_millis(), + // ); + // + // let mut height_to_block_header = wtx.open_table(HEIGHT_TO_BLOCK_HEADER)?; + // let mut height_to_last_sequence_number = wtx.open_table(HEIGHT_TO_LAST_SEQUENCE_NUMBER)?; + // let mut home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS)?; + // let mut inscription_id_to_sequence_number = + // wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; + // let mut inscription_number_to_sequence_number = + // wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER)?; + // let mut sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER)?; + // let mut satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; + // let mut sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN)?; + // let mut sequence_number_to_inscription_entry = + // wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; + // let mut sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT)?; + // let mut statistic_to_count = wtx.open_table(STATISTIC_TO_COUNT)?; + // let mut transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION)?; + // + // let mut lost_sats = statistic_to_count + // .get(&Statistic::LostSats.key())? + // .map(|lost_sats| lost_sats.value()) + // .unwrap_or(0); + // + // let cursed_inscription_count = statistic_to_count + // .get(&Statistic::CursedInscriptions.key())? + // .map(|count| count.value()) + // .unwrap_or(0); + // + // let blessed_inscription_count = statistic_to_count + // .get(&Statistic::BlessedInscriptions.key())? + // .map(|count| count.value()) + // .unwrap_or(0); + // + // let unbound_inscriptions = statistic_to_count + // .get(&Statistic::UnboundInscriptions.key())? + // .map(|unbound_inscriptions| unbound_inscriptions.value()) + // .unwrap_or(0); + // + // let next_sequence_number = sequence_number_to_inscription_entry + // .iter()? + // .next_back() + // .and_then(|result| result.ok()) + // .map(|(number, _id)| number.value() + 1) + // .unwrap_or(0); + // + // let mut operations = HashMap::new(); + // let mut processor = StorageProcessor::new(self.cache.clone(),self.internal_index.clone()); + // // let mut processor = crate::index::updater::pending_updater::PendingStorageProcessor::new( + // // &mut home_inscriptions, + // // &mut inscription_id_to_sequence_number, + // // &mut inscription_number_to_sequence_number, + // // &mut outpoint_to_entry, + // // &mut transaction_id_to_transaction, + // // &mut sat_to_sequence_number, + // // &mut satpoint_to_sequence_number, + // // &mut sequence_number_to_children, + // // &mut sequence_number_to_inscription_entry, + // // &mut sequence_number_to_satpoint, + // // ); + // let mut inscription_updater = PendingUpdater::new( + // &mut operations, + // blessed_inscription_count, + // self.internal_index.options.chain(), + // cursed_inscription_count, + // height, + // self.internal_index.index_transactions, + // next_sequence_number, + // lost_sats, + // block.header.time, + // unbound_inscriptions, + // tx_out_receiver, + // tx_out_cache, + // &mut processor, + // )?; + // + // let index_sats = true; + // if index_sats { + // let mut sat_to_satpoint = wtx.open_table(SAT_TO_SATPOINT)?; + // let mut outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES)?; + // + // let mut coinbase_inputs = VecDeque::new(); + // + // let h = Height(height); + // if h.subsidy() > 0 { + // let start = h.starting_sat(); + // coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); + // } + // + // for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { + // log::trace!("Indexing transaction {tx_offset}…"); + // + // let mut input_sat_ranges = VecDeque::new(); + // + // // TODO: make sure this is correct + // // for input in &tx.input { + // // let key = input.previous_output.store(); + // // let sat_ranges = match self.range_cache.remove(&key) { + // // Some(sat_ranges) => { + // // self.outputs_cached += 1; + // // sat_ranges + // // } + // // None => outpoint_to_sat_ranges + // // .remove(&key)? + // // .ok_or_else(|| anyhow!("Could not find outpoint {} in index", input.previous_output))? + // // .value() + // // .to_vec(), + // // }; + // // + // // for chunk in sat_ranges.chunks_exact(11) { + // // input_sat_ranges.push_back(SatRange::load(chunk.try_into().unwrap())); + // // } + // // } + // + // self.index_transaction_sats( + // tx, + // *txid, + // &mut sat_to_satpoint, + // &mut input_sat_ranges, + // &mut sat_ranges_written, + // &mut outputs_in_block, + // &mut inscription_updater, + // index_inscriptions, + // )?; + // + // coinbase_inputs.extend(input_sat_ranges); + // } + // + // if let Some((tx, txid)) = block.txdata.first() { + // self.index_transaction_sats( + // tx, + // *txid, + // &mut sat_to_satpoint, + // &mut coinbase_inputs, + // &mut sat_ranges_written, + // &mut outputs_in_block, + // &mut inscription_updater, + // index_inscriptions, + // )?; + // } + // + // if !coinbase_inputs.is_empty() { + // let mut lost_sat_ranges = outpoint_to_sat_ranges + // .remove(&OutPoint::null().store())? + // .map(|ranges| ranges.value().to_vec()) + // .unwrap_or_default(); + // + // for (start, end) in coinbase_inputs { + // if !Sat(start).common() { + // sat_to_satpoint.insert( + // &start, + // &SatPoint { + // outpoint: OutPoint::null(), + // offset: lost_sats, + // } + // .store(), + // )?; + // } + // + // lost_sat_ranges.extend_from_slice(&(start, end).store()); + // + // lost_sats += end - start; + // } + // + // outpoint_to_sat_ranges.insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; + // } + // } else if index_inscriptions { + // for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { + // inscription_updater.index_envelopes(tx, *txid, None)?; + // } + // } + // inscription_updater.flush_cache()?; + // + // let mut context = Context { + // chain: BlockContext { + // network: index.get_chain_network(), + // blockheight: height, + // blocktime: block.header.time, + // }, + // tx_out_cache, + // hit: 0, + // miss: 0, + // ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS)?, + // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, + // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx + // .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, + // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut sequence_number_to_inscription_entry, + // OUTPOINT_TO_ENTRY: &mut outpoint_to_entry, + // BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES)?, + // BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN)?, + // BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS)?, + // BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG)?, + // BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER)?, + // }; + // + // // Create a protocol manager to index the block of bitmap data. + // let config = ProtocolConfig::new_with_options(&index.options); + // ProtocolManager::new(config).index_block(&mut context, &block, operations)?; + // + // Ok(()) + // } + fn index_block( &mut self, index: &Index, @@ -35,7 +325,6 @@ impl Simulator { tx_out_receiver: &mut Receiver, block: BlockData, tx_out_cache: &mut SimpleLru, - wtx:&mut WriteTransaction, ) -> crate::Result<()> { let start = Instant::now(); let mut sat_ranges_written = 0; @@ -47,7 +336,6 @@ impl Simulator { return Err(anyhow!("Previous block did not consume all input values")); }; - let mut outpoint_to_entry = wtx.open_table(OUTPOINT_TO_ENTRY)?; let index_inscriptions = true; @@ -80,8 +368,7 @@ impl Simulator { } else if tx_out_cache.contains(&prev_output) { cache_outputs_count.fetch_add(1, Ordering::Relaxed); None - } else if let Some(txout) = - get_txout_by_outpoint(&outpoint_to_entry, &prev_output).unwrap() + } else if let Some(txout) =self.processor.get_txout_by_outpoint(&prev_output).unwrap() { miss_outputs_count.fetch_add(1, Ordering::Relaxed); Some((prev_output, Some(txout))) @@ -115,62 +402,18 @@ impl Simulator { start.elapsed().as_millis(), ); - let mut height_to_block_header = wtx.open_table(HEIGHT_TO_BLOCK_HEADER)?; - let mut height_to_last_sequence_number = wtx.open_table(HEIGHT_TO_LAST_SEQUENCE_NUMBER)?; - let mut home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS)?; - let mut inscription_id_to_sequence_number = - wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; - let mut inscription_number_to_sequence_number = - wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER)?; - let mut sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER)?; - let mut satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; - let mut sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN)?; - let mut sequence_number_to_inscription_entry = - wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; - let mut sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT)?; - let mut statistic_to_count = wtx.open_table(STATISTIC_TO_COUNT)?; - let mut transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION)?; - - let mut lost_sats = statistic_to_count - .get(&Statistic::LostSats.key())? - .map(|lost_sats| lost_sats.value()) - .unwrap_or(0); - - let cursed_inscription_count = statistic_to_count - .get(&Statistic::CursedInscriptions.key())? - .map(|count| count.value()) - .unwrap_or(0); - - let blessed_inscription_count = statistic_to_count - .get(&Statistic::BlessedInscriptions.key())? - .map(|count| count.value()) - .unwrap_or(0); - - let unbound_inscriptions = statistic_to_count - .get(&Statistic::UnboundInscriptions.key())? - .map(|unbound_inscriptions| unbound_inscriptions.value()) - .unwrap_or(0); - - let next_sequence_number = sequence_number_to_inscription_entry - .iter()? - .next_back() - .and_then(|result| result.ok()) - .map(|(number, _id)| number.value() + 1) - .unwrap_or(0); + let mut lost_sats = self.processor.get_lost_sats()?; + + let cursed_inscription_count = self.processor.get_cursed_inscription_count()?; + + let blessed_inscription_count = self.processor.get_blessed_inscription_count()?; + + let unbound_inscriptions = self.processor.get_unbound_inscriptions()?; + + let next_sequence_number = self.processor.next_sequence_number()?; let mut operations = HashMap::new(); - let mut processor = crate::index::updater::pending_updater::PendingStorageProcessor::new( - &mut home_inscriptions, - &mut inscription_id_to_sequence_number, - &mut inscription_number_to_sequence_number, - &mut outpoint_to_entry, - &mut transaction_id_to_transaction, - &mut sat_to_sequence_number, - &mut satpoint_to_sequence_number, - &mut sequence_number_to_children, - &mut sequence_number_to_inscription_entry, - &mut sequence_number_to_satpoint, - ); + let mut processor = self.processor.clone(); let mut inscription_updater = PendingUpdater::new( &mut operations, blessed_inscription_count, @@ -189,9 +432,6 @@ impl Simulator { let index_sats = true; if index_sats { - let mut sat_to_satpoint = wtx.open_table(SAT_TO_SATPOINT)?; - let mut outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES)?; - let mut coinbase_inputs = VecDeque::new(); let h = Height(height); @@ -228,7 +468,6 @@ impl Simulator { self.index_transaction_sats( tx, *txid, - &mut sat_to_satpoint, &mut input_sat_ranges, &mut sat_ranges_written, &mut outputs_in_block, @@ -243,7 +482,6 @@ impl Simulator { self.index_transaction_sats( tx, *txid, - &mut sat_to_satpoint, &mut coinbase_inputs, &mut sat_ranges_written, &mut outputs_in_block, @@ -312,12 +550,10 @@ impl Simulator { Ok(()) } - fn index_transaction_sats( &mut self, tx: &Transaction, txid: Txid, - sat_to_satpoint: &mut Table, input_sat_ranges: &mut VecDeque<(u64, u64)>, sat_ranges_written: &mut u64, outputs_traversed: &mut u64, @@ -342,11 +578,11 @@ impl Simulator { .ok_or_else(|| anyhow!("insufficient inputs for transaction outputs"))?; if !Sat(range.0).common() { - sat_to_satpoint.insert( + self.processor.sat_to_satpoint_insert( &range.0, &SatPoint { outpoint, - offset: output.value - remaining, + offset: 0, } .store(), )?; diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index abed951ccf..25282445f4 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -2,187 +2,12 @@ use { super::*, crate::okx::datastore::ord::operation::{Action, InscriptionOp}, }; +use crate::index::processor::StorageProcessor; use crate::index::updater::inscription_updater::{Flotsam, Origin}; -use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; - - -pub struct PendingStorageProcessor<'a, 'db, 'tx> { - // cache_writer: CacheWriter, - pub(super) home_inscriptions: &'a mut Table<'db, 'tx, u32, InscriptionIdValue>, - pub(super) id_to_sequence_number: &'a mut Table<'db, 'tx, InscriptionIdValue, u32>, - pub(super) inscription_number_to_sequence_number: &'a mut Table<'db, 'tx, i32, u32>, - pub(super) outpoint_to_entry: &'a mut Table<'db, 'tx, &'static OutPointValue, &'static [u8]>, - pub(super) transaction_id_to_transaction: - &'a mut Table<'db, 'tx, &'static TxidValue, &'static [u8]>, - pub(super) sat_to_sequence_number: &'a mut MultimapTable<'db, 'tx, u64, u32>, - pub(super) satpoint_to_sequence_number: - &'a mut MultimapTable<'db, 'tx, &'static SatPointValue, u32>, - pub(super) sequence_number_to_children: &'a mut MultimapTable<'db, 'tx, u32, u32>, - pub(super) sequence_number_to_entry: &'a mut Table<'db, 'tx, u32, InscriptionEntryValue>, - pub(super) sequence_number_to_satpoint: &'a mut Table<'db, 'tx, u32, &'static SatPointValue>, -} - - -impl<'a, 'db, 'tx> PendingStorageProcessor<'a, 'db, 'tx> { - pub(crate) fn satpoint_to_sequence_number_remove_all(&mut self, v: &SatPointValue) -> crate::Result<()> { - self - .satpoint_to_sequence_number - .remove_all(v)?; - Ok(()) - } - pub fn new(home_inscriptions: &'a mut Table<'db, 'tx, u32, InscriptionIdValue>, id_to_sequence_number: &'a mut Table<'db, 'tx, InscriptionIdValue, u32>, inscription_number_to_sequence_number: &'a mut Table<'db, 'tx, i32, u32>, outpoint_to_entry: &'a mut Table<'db, 'tx, &'static OutPointValue, &'static [u8]>, transaction_id_to_transaction: &'a mut Table<'db, 'tx, &'static TxidValue, &'static [u8]>, sat_to_sequence_number: &'a mut MultimapTable<'db, 'tx, u64, u32>, satpoint_to_sequence_number: &'a mut MultimapTable<'db, 'tx, &'static SatPointValue, u32>, sequence_number_to_children: &'a mut MultimapTable<'db, 'tx, u32, u32>, sequence_number_to_entry: &'a mut Table<'db, 'tx, u32, InscriptionEntryValue>, sequence_number_to_satpoint: &'a mut Table<'db, 'tx, u32, &'static SatPointValue>) -> Self { - Self { home_inscriptions, id_to_sequence_number, inscription_number_to_sequence_number, outpoint_to_entry, transaction_id_to_transaction, sat_to_sequence_number, satpoint_to_sequence_number, sequence_number_to_children, sequence_number_to_entry, sequence_number_to_satpoint } - } -} - -impl<'a, 'db, 'tx> PendingStorageProcessor<'a, 'db, 'tx> { - pub(crate) fn home_inscriptions_len(&self) -> u64 { - todo!() - } -} - - -impl<'a, 'db, 'tx> PendingStorageProcessor<'a, 'db, 'tx> { - pub(crate) fn sequence_number_to_satpoint_insert(&mut self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { - self.sequence_number_to_satpoint.insert(sequence_number, sat_point)?; - // let key = sequence_number.to_le_bytes().as_slice(); - // let value = rmp_serde::to_vec(sat_point).unwrap(); - // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_SATPOINT, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) - Ok(()) - } - pub(crate) fn satpoint_to_sequence_number_insert(&mut self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { - self.sequence_number_to_satpoint.insert(sequence, sat_point)?; - // let key = rmp_serde::to_vec(sat_point).unwrap(); - // let value = sequence.to_le_bytes().as_slice(); - // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - Ok(()) - } - pub(crate) fn home_inscriptions_pop_first(&mut self) -> crate::Result<()> { - self.home_inscriptions.pop_first()?; - // self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { - // v.pop_first() - // }); - // Ok(()) - Ok(()) - } - pub(crate) fn home_inscriptions_insert(&mut self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { - // let key = sequnce_number.to_le_bytes().as_slice(); - // let value = rmp_serde::to_vec(&value).unwrap(); - // self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) - self - .home_inscriptions - .insert(sequence_number, value)?; - Ok(()) - } - pub(crate) fn id_to_sequence_number_insert(&mut self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { - // let key = rmp_serde::to_vec(value).unwrap(); - // let value = sequence.to_le_bytes().as_slice(); - // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) - self - .id_to_sequence_number - .insert(value, sequence_number)?; - Ok(()) - } - pub(crate) fn sequence_number_to_children_insert(&mut self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { - // let key = sequence.to_le_bytes().as_slice(); - // let value = rmp_serde::to_vec(value).unwrap(); - // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_CHILDREN, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) - self - .sequence_number_to_children - .insert(parent_sequence_number, sequence_number)?; - Ok(()) - } - pub(crate) fn sequence_number_to_entry_insert(&mut self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { - // let key = sequence.to_le_bytes().as_slice(); - // let value = rmp_serde::to_vec(value).unwrap(); - // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) - self.sequence_number_to_entry.insert(sequence, value)?; - Ok(()) - } - pub(crate) fn sat_to_sequence_number_insert(&mut self, n: &u64, sequence_number: &u32) -> crate::Result<()> { - // let key = n.to_le_bytes().as_slice(); - // let value = sequence.to_le_bytes().as_slice(); - // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) - self.sat_to_sequence_number.insert(n, sequence_number)?; - Ok(()) - } - pub(crate) fn inscription_number_to_sequence_number_insert(&mut self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { - // let key = inscription_number.to_le_bytes().as_slice(); - // let value = sequence_number.to_le_bytes().as_slice(); - // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) - self - .inscription_number_to_sequence_number - .insert(inscription_number, sequence_number)?; - Ok(()) - } - pub(crate) fn outpoint_to_entry_insert(&mut self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { - self.outpoint_to_entry.insert(value, entry)?; - Ok(()) - // let key = rmp_serde::to_vec(value).unwrap(); - // let value = entry.to_vec(); - // self.cache_writer.use_cache_mut(CacheTableIndex::OUTPOINT_TO_ENTRY, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) - } - pub fn inscriptions_on_output(&mut self, prev_output: &OutPoint) -> crate::Result> { - let ret = Index::inscriptions_on_output( - self.satpoint_to_sequence_number, - self.sequence_number_to_entry, - prev_output.clone())?; - // TODO: twice - todo!() - } - pub(crate) fn transaction_id_to_transaction_insert(&mut self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { - self - .transaction_id_to_transaction - .insert(tx_id, value)?; - - Ok(()) - } - - pub(crate) fn id_to_sequence_number_get(&self, x: InscriptionIdValue) -> crate::Result> { - // TODO,twice - let ret = self.id_to_sequence_number.get(x)?.unwrap().value(); - Ok(Some(ret)) - } - pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { - // TODO: twice - let ret = self - .sequence_number_to_entry - .get(initial_inscription_sequence_number)? - .unwrap() - .value(); - Ok(Some(ret)) - } -} -pub struct PendingUpdater<'a, 'db, 'tx> { - processor: &'a mut PendingStorageProcessor<'a, 'db, 'tx>, +pub struct PendingUpdater<'a> { + processor: &'a mut StorageProcessor, pub(super) operations: &'a mut HashMap>, pub(super) blessed_inscription_count: u64, pub(super) chain: Chain, @@ -202,7 +27,7 @@ pub struct PendingUpdater<'a, 'db, 'tx> { pub(super) new_outpoints: Vec, } -impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { +impl<'a> PendingUpdater<'a> { pub fn new( operations: &'a mut HashMap>, blessed_inscription_count: u64, @@ -216,7 +41,7 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { unbound_inscriptions: u64, tx_out_receiver: &'a mut Receiver, tx_out_cache: &'a mut SimpleLru, - processor: &'a mut PendingStorageProcessor<'a, 'db, 'tx>, + processor: &'a mut StorageProcessor, ) -> Result { let home_inscriptions_len = processor.home_inscriptions_len(); Ok(Self { diff --git a/src/okx/datastore/cache.rs b/src/okx/datastore/cache.rs index 8094faedf9..94cf792444 100644 --- a/src/okx/datastore/cache.rs +++ b/src/okx/datastore/cache.rs @@ -45,6 +45,14 @@ impl CacheTable{ pub fn pop_first(&mut self){ } + pub fn get(&self, key:Vec) -> Option> { + self.data.get(&key).map_or(None,|v|{ + Some(v.clone()) + }) + } + pub fn remove(&mut self,key:Vec){ + self.data.remove(&key); + } } #[derive(Clone)] diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index 9c1b242fb5..9c07ad20e7 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -4,53 +4,52 @@ use bitcoin::{OutPoint, Txid, TxOut}; use redb::{Database, ReadableTable, ReadOnlyTable, ReadTransaction, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; use tempfile::NamedTempFile; use crate::{Index, InscriptionId}; -use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionIdValue, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY}; +use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionIdValue, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; use crate::index::entry::Entry; use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; use crate::okx::datastore::brc20::redb::{script_tick_id_key, script_tick_key}; use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick}; -use crate::okx::datastore::cache::CacheTableIndex; +use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; use crate::okx::datastore::ScriptKey; -use crate::okx::lru::SimpleLru; -use crate::okx::protocol::BlockContext; -use crate::okx::protocol::context::Context; use crate::okx::protocol::trace::{BalanceDelta, IndexTracer, MintTokenInfoDelta, string_to_bytes, TraceNode}; -pub struct SimulateContext<'a, 'db, 'txn> { - simulate: Context<'a, 'db, 'txn>, +pub struct SimulateContext { + simulate: CacheWriter, internal_index: Arc, - // simulate_index: IndexTracer, } -impl<'a, 'db, 'txn> SimulateContext<'a, 'db, 'txn> { - pub fn new( - internal_index: Arc, simulate: Context<'a, 'db, 'txn>) -> crate::Result { - // let mut simulate_tx = simulate_index.begin_write()?; - // let ctx = Context { - // chain, - // tx_out_cache, - // hit: 0, - // miss: 0, - // ORD_TX_TO_OPERATIONS: &mut simulate_tx.open_table(ORD_TX_TO_OPERATIONS)?, - // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut simulate_tx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, - // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut simulate_tx.open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, - // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut simulate_tx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?, - // OUTPOINT_TO_ENTRY: &mut simulate_tx.open_table(OUTPOINT_TO_ENTRY)?, - // BRC20_BALANCES: &mut simulate_tx.open_table(BRC20_BALANCES)?, - // BRC20_TOKEN: &mut simulate_tx.open_table(BRC20_TOKEN)?, - // BRC20_EVENTS: &mut simulate_tx.open_table(BRC20_EVENTS)?, - // BRC20_TRANSFERABLELOG: &mut simulate_tx.open_table(BRC20_TRANSFERABLELOG)?, - // BRC20_INSCRIBE_TRANSFER: &mut simulate_tx.open_table(BRC20_INSCRIBE_TRANSFER)?, - // }; - Ok(Self { - // simulate: ctx, - internal_index, - simulate, - }) +impl SimulateContext { + // pub fn new( + // internal_index: Arc, simulate: Context) -> crate::Result { + // // let mut simulate_tx = simulate_index.begin_write()?; + // // let ctx = Context { + // // chain, + // // tx_out_cache, + // // hit: 0, + // // miss: 0, + // // ORD_TX_TO_OPERATIONS: &mut simulate_tx.open_table(ORD_TX_TO_OPERATIONS)?, + // // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut simulate_tx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, + // // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut simulate_tx.open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, + // // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut simulate_tx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?, + // // OUTPOINT_TO_ENTRY: &mut simulate_tx.open_table(OUTPOINT_TO_ENTRY)?, + // // BRC20_BALANCES: &mut simulate_tx.open_table(BRC20_BALANCES)?, + // // BRC20_TOKEN: &mut simulate_tx.open_table(BRC20_TOKEN)?, + // // BRC20_EVENTS: &mut simulate_tx.open_table(BRC20_EVENTS)?, + // // BRC20_TRANSFERABLELOG: &mut simulate_tx.open_table(BRC20_TRANSFERABLELOG)?, + // // BRC20_INSCRIBE_TRANSFER: &mut simulate_tx.open_table(BRC20_INSCRIBE_TRANSFER)?, + // // }; + // Ok(Self { + // // simulate: ctx, + // internal_index, + // simulate, + // }) + // } + pub fn new(simulate: CacheWriter, internal_index: Arc) -> Self { + Self { simulate, internal_index } } } -impl<'a, 'db, 'txn> SimulateContext<'a, 'db, 'txn> { +impl SimulateContext { fn use_internal_table(&self, table_def: TableDefinition, f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { @@ -341,33 +340,188 @@ impl<'a, 'db, 'txn> SimulateContext<'a, 'db, 'txn> { // } // } -impl<'a, 'db, 'txn> Brc20Reader for SimulateContext<'a, 'db, 'txn> { +// impl Brc20Reader for SimulateContext { +// type Error = anyhow::Error; +// +// fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { +// let simulate = self.simulate.get_balances(script_key)?; +// let mut simulate_balances: HashMap = simulate.into_iter() +// .map(|v| { +// (v.tick.clone(), v.clone()) +// }).collect(); +// let internal = self.use_internal_table(BRC20_BALANCES, |v| { +// get_balances(&v, script_key) +// })?; +// for node in internal { +// let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); +// v.transferable_balance = v.transferable_balance + node.transferable_balance; +// v.overall_balance = v.overall_balance + node.overall_balance; +// } +// let ret = simulate_balances +// .into_iter() +// .map(|(k, v)| { +// v.clone() +// }).collect(); +// Ok(ret) +// } +// +// fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { +// let ret = self.simulate.get_balance(script_key, tick)?; +// if let Some(ret) = ret { +// return Ok(Some(ret)); +// } +// self.use_internal_table(BRC20_BALANCES, |table| { +// get_balance(&table, script_key, tick) +// }) +// } +// +// fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { +// let ret = self.simulate.get_token_info(tick)?; +// if let Some(ret) = ret { +// return Ok(Some(ret)); +// } +// self.use_internal_table(BRC20_TOKEN, |table| { +// get_token_info(&table, tick) +// }) +// } +// +// fn get_tokens_info(&self) -> crate::Result, Self::Error> { +// let simulate = self.simulate.get_tokens_info()?; +// let internal = self.use_internal_table(BRC20_TOKEN, |table| { +// get_tokens_info(&table) +// })?; +// // TODO:merge +// todo!() +// } +// +// fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { +// let simulate = self.simulate.get_transaction_receipts(txid)?; +// let internal = self.use_internal_table(BRC20_EVENTS, |table| { +// get_transaction_receipts(&table, txid) +// })?; +// // TODO:merge +// todo!() +// } +// +// fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { +// let simulate = self.simulate.get_transferable(script)?; +// let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// get_transferable(&table, script) +// })?; +// // TODO: merge +// todo!() +// } +// +// +// fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { +// let simulate = self.simulate.get_transferable_by_tick(script, tick)?; +// let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// get_transferable_by_tick(&table, script, tick) +// })?; +// // TODO:merge +// todo!() +// } +// +// fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { +// let simulate = self.simulate.get_transferable_by_id(script, inscription_id)?; +// if let Some(ret) = simulate { +// return Ok(Some(ret)); +// } +// self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// get_transferable_by_id(&table, script, inscription_id) +// }) +// } +// +// fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { +// let simulate = self.simulate.get_inscribe_transfer_inscription(inscription_id)?; +// if let Some(ret) = simulate { +// return Ok(Some(ret)); +// } +// self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { +// get_inscribe_transfer_inscription(&table, inscription_id) +// }) +// } +// } +// +// impl Brc20ReaderWriter for SimulateContext { +// fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { +// self.simulate.update_token_balance(script_key, new_balance) +// } +// +// fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { +// self.simulate.insert_token_info(tick, new_info) +// } +// +// +// fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { +// self.simulate.update_mint_token_info(tick, minted_amt, minted_block_number) +// } +// +// fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { +// self.simulate.save_transaction_receipts(txid, receipt) +// } +// +// fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { +// self.simulate.insert_transferable(script, tick, inscription) +// } +// +// fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { +// self.simulate.remove_transferable(script, tick, inscription_id) +// } +// +// fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { +// self.simulate.insert_inscribe_transfer_inscription(inscription_id, transfer_info) +// } +// +// fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { +// self.simulate.remove_inscribe_transfer_inscription(inscription_id) +// } +// } + +impl Brc20Reader for SimulateContext { type Error = anyhow::Error; fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { - let simulate = self.simulate.get_balances(script_key)?; - let mut simulate_balances: HashMap = simulate.into_iter() - .map(|v| { - (v.tick.clone(), v.clone()) - }).collect(); - let internal = self.use_internal_table(BRC20_BALANCES, |v| { - get_balances(&v, script_key) - })?; - for node in internal { - let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); - v.transferable_balance = v.transferable_balance + node.transferable_balance; - v.overall_balance = v.overall_balance + node.overall_balance; - } - let ret = simulate_balances - .into_iter() - .map(|(k, v)| { - v.clone() - }).collect(); - Ok(ret) + // self.simulate.use_cache_mut(CacheTableIndex::BRC20_BALANCES,|table|{ + // + // }) + // let simulate = self.simulate.get_balances(script_key)?; + // let mut simulate_balances: HashMap = simulate.into_iter() + // .map(|v| { + // (v.tick.clone(), v.clone()) + // }).collect(); + // let internal = self.use_internal_table(BRC20_BALANCES, |v| { + // get_balances(&v, script_key) + // })?; + // for node in internal { + // let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); + // v.transferable_balance = v.transferable_balance + node.transferable_balance; + // v.overall_balance = v.overall_balance + node.overall_balance; + // } + // let ret = simulate_balances + // .into_iter() + // .map(|(k, v)| { + // v.clone() + // }).collect(); + // Ok(ret) + todo!() } fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { - let ret = self.simulate.get_balance(script_key, tick)?; + let ret = self.simulate.use_cache(CacheTableIndex::BRC20_BALANCES, |table| { + if table.is_none() { + return Ok::, Self::Error>(None); + } + let key = script_tick_key(script_key, tick); + let key = key.as_str(); + let table = table.unwrap(); + let value = table.get(string_to_bytes(key)); + if value.is_none() { + return Ok::, Self::Error>(None); + } + let bal: Balance = rmp_serde::from_slice(&value.unwrap()).unwrap(); + Ok(Some(bal)) + })?; if let Some(ret) = ret { return Ok(Some(ret)); } @@ -377,7 +531,22 @@ impl<'a, 'db, 'txn> Brc20Reader for SimulateContext<'a, 'db, 'txn> { } fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { - let ret = self.simulate.get_token_info(tick)?; + let ret = self.simulate + .use_cache(CacheTableIndex::BRC20_TOKEN, |table| { + if table.is_none() { + return Ok::, Self::Error>(None); + } + let table = table.unwrap(); + let binding = tick.to_lowercase().hex(); + let key = binding.as_str(); + let value = table.get(string_to_bytes(key)); + if value.is_none() { + return Ok::, Self::Error>(None); + } + let value = value.unwrap(); + let info: TokenInfo = rmp_serde::from_slice(&value).unwrap(); + return Ok(Some(info)); + })?; if let Some(ret) = ret { return Ok(Some(ret)); } @@ -387,16 +556,32 @@ impl<'a, 'db, 'txn> Brc20Reader for SimulateContext<'a, 'db, 'txn> { } fn get_tokens_info(&self) -> crate::Result, Self::Error> { - let simulate = self.simulate.get_tokens_info()?; - let internal = self.use_internal_table(BRC20_TOKEN, |table| { - get_tokens_info(&table) - })?; + // let simulate = self.simulate.get_tokens_info()?; + // let internal = self.use_internal_table(BRC20_TOKEN, |table| { + // get_tokens_info(&table) + // })?; // TODO:merge todo!() } fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { - let simulate = self.simulate.get_transaction_receipts(txid)?; + let simulate = self.simulate + .use_cache(CacheTableIndex::BRC20_EVENTS, |table| { + if table.is_none() { + return Ok::>, Self::Error>(None); + } + let table = table.unwrap(); + let key = &txid.store(); + let key: Vec = key.to_vec(); + // let key = TxidValue::as_bytes(&key).as_ref(); + let value = table.get(key); + if value.is_none() { + return Ok::>, Self::Error>(None); + } + let value = value.unwrap(); + let ret = rmp_serde::from_slice::>(&value).unwrap(); + Ok(Some(ret)) + })?; let internal = self.use_internal_table(BRC20_EVENTS, |table| { get_transaction_receipts(&table, txid) })?; @@ -405,36 +590,53 @@ impl<'a, 'db, 'txn> Brc20Reader for SimulateContext<'a, 'db, 'txn> { } fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { - let simulate = self.simulate.get_transferable(script)?; - let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { - get_transferable(&table, script) - })?; + // let simulate = self.simulate.get_transferable(script)?; + // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + // get_transferable(&table, script) + // })?; // TODO: merge todo!() } fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { - let simulate = self.simulate.get_transferable_by_tick(script, tick)?; - let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { - get_transferable_by_tick(&table, script, tick) - })?; + // let simulate = self.simulate.get_transferable_by_tick(script, tick)?; + // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + // get_transferable_by_tick(&table, script, tick) + // })?; // TODO:merge todo!() } fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { - let simulate = self.simulate.get_transferable_by_id(script, inscription_id)?; - if let Some(ret) = simulate { - return Ok(Some(ret)); - } - self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { - get_transferable_by_id(&table, script, inscription_id) - }) + // let simulate = self.simulate.get_transferable_by_id(script, inscription_id)?; + // if let Some(ret) = simulate { + // return Ok(Some(ret)); + // } + // self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + // get_transferable_by_id(&table, script, inscription_id) + // }) + todo!() } fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { - let simulate = self.simulate.get_inscribe_transfer_inscription(inscription_id)?; + let simulate = self.simulate + .use_cache(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { + if table.is_none() { + return Ok::, Self::Error>(None); + } + let table = table.unwrap(); + let key = inscription_id.store(); + let key_bytes = InscriptionIdValue::as_bytes(&key); + let value = table.get(key_bytes); + if value.is_none() { + return Ok::, Self::Error>(None); + } + let value = value.unwrap(); + let ret: TransferInfo = rmp_serde::from_slice::(&value).unwrap(); + return Ok(Some(ret)); + })?; + // let simulate = self.simulate.get_inscribe_transfer_inscription(inscription_id)?; if let Some(ret) = simulate { return Ok(Some(ret)); } @@ -444,38 +646,93 @@ impl<'a, 'db, 'txn> Brc20Reader for SimulateContext<'a, 'db, 'txn> { } } -impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { +impl Brc20ReaderWriter for SimulateContext { fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { - self.simulate.update_token_balance(script_key, new_balance) + self.simulate.use_cache_mut(CacheTableIndex::BRC20_BALANCES, |table| { + let key = script_tick_key(script_key, &new_balance.tick); + let key = key.as_str(); + let binding = rmp_serde::to_vec(&new_balance).unwrap(); + let value = binding.as_slice(); + table.insert(string_to_bytes(key), value.to_vec()); + Ok(()) + }) } fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { - self.simulate.insert_token_info(tick, new_info) + self.simulate.use_cache_mut(CacheTableIndex::BRC20_TOKEN, |table| { + let binding = tick.to_lowercase().hex(); + let key = binding.as_str(); + let binding = rmp_serde::to_vec(new_info).unwrap(); + let value = binding.as_slice(); + table.insert(string_to_bytes(key), value.to_vec()); + Ok(()) + }) } fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { - self.simulate.update_mint_token_info(tick, minted_amt, minted_block_number) + let mut info = self. + get_token_info(tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); + info.minted = minted_amt; + info.latest_mint_number = minted_block_number; + self.simulate + .use_cache_mut(CacheTableIndex::BRC20_TOKEN, |table| { + let binding = tick.to_lowercase().hex(); + let key = binding.as_str(); + let value = rmp_serde::to_vec(&info).unwrap(); + table.insert(string_to_bytes(key), value.to_vec()); + Ok(()) + }) } - fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { - self.simulate.save_transaction_receipts(txid, receipt) + fn save_transaction_receipts(&mut self, txid: &Txid, receipts: &[Receipt]) -> crate::Result<(), Self::Error> { + self.simulate.use_cache_mut(CacheTableIndex::BRC20_EVENTS, |table| { + let v = txid.store(); + let key = v.to_vec(); + let value = rmp_serde::to_vec(receipts).unwrap(); + table.insert(key, value); + Ok(()) + }) } fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { - self.simulate.insert_transferable(script, tick, inscription) + self.simulate + .use_cache_mut(CacheTableIndex::BRC20_TRANSFERABLELOG, |table| { + let binding = script_tick_id_key(script, tick, &inscription.inscription_id); + let key = binding.as_str(); + let binding = rmp_serde::to_vec(inscription).unwrap(); + let value = binding.as_slice(); + table.insert(string_to_bytes(key), value.to_vec()); + Ok(()) + }) } fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - self.simulate.remove_transferable(script, tick, inscription_id) + self.simulate.use_cache_mut(CacheTableIndex::BRC20_TRANSFERABLELOG, |table| { + let binding = script_tick_id_key(script, tick, inscription_id); + let key = binding.as_str(); + table.remove(string_to_bytes(key)); + Ok(()) + }) } fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { - self.simulate.insert_inscribe_transfer_inscription(inscription_id, transfer_info) + self.simulate.use_cache_mut(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { + let key = inscription_id.store(); + let key_bytes = InscriptionIdValue::as_bytes(&key); + let value = rmp_serde::to_vec(&transfer_info).unwrap(); + table.insert(key_bytes, value); + Ok(()) + }) } fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - self.simulate.remove_inscribe_transfer_inscription(inscription_id) + self.simulate.use_cache_mut(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { + let key = inscription_id.store(); + let key_bytes = InscriptionIdValue::as_bytes(&key); + table.remove(key_bytes); + Ok(()) + }) } } From 1de852e79af5cee069780115cf54a9e026bdd1ca Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 11 Jan 2024 16:02:59 +0800 Subject: [PATCH 07/66] fk3 --- src/index/processor.rs | 40 +++++++++++++++++++++++++++++++++------- src/index/simulate.rs | 34 +++++----------------------------- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/index/processor.rs b/src/index/processor.rs index 906c9c093a..b01c96466f 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -5,34 +5,60 @@ use crate::{Index, InscriptionId, SatPoint}; use crate::index::entry::SatPointValue; use crate::index::{InscriptionEntryValue, InscriptionIdValue, OutPointValue, TxidValue}; use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; +use crate::okx::protocol::context::Context; #[derive(Clone)] pub struct StorageProcessor { pub cache_writer: CacheWriter, pub internal: Arc, } +unsafe impl Send for StorageProcessor{} +unsafe impl Sync for StorageProcessor{} impl StorageProcessor { + pub(crate) fn next_sequence_number(&self) -> crate::Result { + todo!() + } +} + +impl StorageProcessor { + pub(crate) fn create_context(&self) -> crate::Result { + todo!() + } +} - pub fn get_lost_sats(&self)->crate::Result{ +impl StorageProcessor { + pub(crate) fn outpoint_to_sat_ranges_insert(&self, value: &OutPointValue, data: &[u8]) -> crate::Result<()> { + todo!() + } +} + +impl StorageProcessor { + pub(crate) fn outpoint_to_sat_ranges_remove(&self, p0: &OutPointValue) -> crate::Result>> { + todo!() + } +} + +impl StorageProcessor { + pub fn get_lost_sats(&self) -> crate::Result { todo!() } - pub fn get_cursed_inscription_count(&self)->crate::Result{ + pub fn get_cursed_inscription_count(&self) -> crate::Result { todo!() } - pub fn get_blessed_inscription_count(&self)->crate::Result{ + pub fn get_blessed_inscription_count(&self) -> crate::Result { todo!() } - pub fn get_unbound_inscriptions(&self)->crate::Result{ + pub fn get_unbound_inscriptions(&self) -> crate::Result { todo!() } - pub fn get_next_sequence_number(&self)->crate::Result{ + pub fn get_next_sequence_number(&self) -> crate::Result { todo!() } - pub fn sat_to_satpoint_insert(&mut self,key:&u64,value:&SatPointValue)->crate::Result<()>{ + pub fn sat_to_satpoint_insert(&mut self, key: &u64, value: &SatPointValue) -> crate::Result<()> { todo!() } - pub fn get_txout_by_outpoint(&self, x: &OutPoint)->crate::Result>{ + pub fn get_txout_by_outpoint(&self, x: &OutPoint) -> crate::Result> { todo!() } pub(crate) fn satpoint_to_sequence_number_remove_all(&mut self, v: &SatPointValue) -> crate::Result<()> { diff --git a/src/index/simulate.rs b/src/index/simulate.rs index 433c42a540..47e0188164 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -368,7 +368,7 @@ impl Simulator { } else if tx_out_cache.contains(&prev_output) { cache_outputs_count.fetch_add(1, Ordering::Relaxed); None - } else if let Some(txout) =self.processor.get_txout_by_outpoint(&prev_output).unwrap() + } else if let Some(txout) = self.processor.get_txout_by_outpoint(&prev_output).unwrap() { miss_outputs_count.fetch_add(1, Ordering::Relaxed); Some((prev_output, Some(txout))) @@ -491,14 +491,12 @@ impl Simulator { } if !coinbase_inputs.is_empty() { - let mut lost_sat_ranges = outpoint_to_sat_ranges - .remove(&OutPoint::null().store())? - .map(|ranges| ranges.value().to_vec()) + let mut lost_sat_ranges = self.processor.outpoint_to_sat_ranges_remove(&OutPoint::null().store())?.map(|ranges| ranges.to_vec()) .unwrap_or_default(); for (start, end) in coinbase_inputs { if !Sat(start).common() { - sat_to_satpoint.insert( + self.processor.sat_to_satpoint_insert( &start, &SatPoint { outpoint: OutPoint::null(), @@ -512,8 +510,7 @@ impl Simulator { lost_sats += end - start; } - - outpoint_to_sat_ranges.insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; + self.processor.outpoint_to_sat_ranges_insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; } } else if index_inscriptions { for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { @@ -522,28 +519,7 @@ impl Simulator { } inscription_updater.flush_cache()?; - let mut context = Context { - chain: BlockContext { - network: index.get_chain_network(), - blockheight: height, - blocktime: block.header.time, - }, - tx_out_cache, - hit: 0, - miss: 0, - ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS)?, - COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, - COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx - .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, - SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut sequence_number_to_inscription_entry, - OUTPOINT_TO_ENTRY: &mut outpoint_to_entry, - BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES)?, - BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN)?, - BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS)?, - BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG)?, - BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER)?, - }; - + let mut context=self.processor.create_context()?; // Create a protocol manager to index the block of bitmap data. let config = ProtocolConfig::new_with_options(&index.options); ProtocolManager::new(config).index_block(&mut context, &block, operations)?; From 0f105011177d60b01e6327a20be1ccb4a5081478 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 11 Jan 2024 16:05:24 +0800 Subject: [PATCH 08/66] save1 --- src/index/processor.rs | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/index/processor.rs b/src/index/processor.rs index b01c96466f..ec9606665b 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -12,34 +12,25 @@ pub struct StorageProcessor { pub cache_writer: CacheWriter, pub internal: Arc, } -unsafe impl Send for StorageProcessor{} -unsafe impl Sync for StorageProcessor{} -impl StorageProcessor { - pub(crate) fn next_sequence_number(&self) -> crate::Result { - todo!() - } -} +unsafe impl Send for StorageProcessor {} + +unsafe impl Sync for StorageProcessor {} + impl StorageProcessor { pub(crate) fn create_context(&self) -> crate::Result { todo!() } -} - -impl StorageProcessor { + pub(crate) fn next_sequence_number(&self) -> crate::Result { + todo!() + } pub(crate) fn outpoint_to_sat_ranges_insert(&self, value: &OutPointValue, data: &[u8]) -> crate::Result<()> { todo!() } -} - -impl StorageProcessor { pub(crate) fn outpoint_to_sat_ranges_remove(&self, p0: &OutPointValue) -> crate::Result>> { todo!() } -} - -impl StorageProcessor { pub fn get_lost_sats(&self) -> crate::Result { todo!() } From 8d044811eebb197d177dc4b776883905e1ed0308 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 11 Jan 2024 19:17:13 +0800 Subject: [PATCH 09/66] 2 --- src/index/processor.rs | 44 ++++++------- src/index/simulate.rs | 97 ++++++++++------------------ src/index/updater/pending_updater.rs | 8 +-- 3 files changed, 59 insertions(+), 90 deletions(-) diff --git a/src/index/processor.rs b/src/index/processor.rs index ec9606665b..213dd0e324 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -1,24 +1,25 @@ use std::sync::Arc; use bitcoin::{OutPoint, TxOut}; -use redb::RedbValue; +use redb::{RedbValue, WriteTransaction}; use crate::{Index, InscriptionId, SatPoint}; use crate::index::entry::SatPointValue; use crate::index::{InscriptionEntryValue, InscriptionIdValue, OutPointValue, TxidValue}; use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; use crate::okx::protocol::context::Context; -#[derive(Clone)] -pub struct StorageProcessor { +pub struct StorageProcessor<'a, 'db> { pub cache_writer: CacheWriter, pub internal: Arc, + + pub wtx: &'a mut WriteTransaction<'db>, } -unsafe impl Send for StorageProcessor {} +unsafe impl<'a, 'db> Send for StorageProcessor<'a, 'db> {} -unsafe impl Sync for StorageProcessor {} +unsafe impl<'a, 'db> Sync for StorageProcessor<'a, 'db> {} -impl StorageProcessor { +impl<'a, 'db> StorageProcessor<'a, 'db> { pub(crate) fn create_context(&self) -> crate::Result { todo!() } @@ -46,13 +47,13 @@ impl StorageProcessor { pub fn get_next_sequence_number(&self) -> crate::Result { todo!() } - pub fn sat_to_satpoint_insert(&mut self, key: &u64, value: &SatPointValue) -> crate::Result<()> { + pub fn sat_to_satpoint_insert(&self, key: &u64, value: &SatPointValue) -> crate::Result<()> { todo!() } pub fn get_txout_by_outpoint(&self, x: &OutPoint) -> crate::Result> { todo!() } - pub(crate) fn satpoint_to_sequence_number_remove_all(&mut self, v: &SatPointValue) -> crate::Result<()> { + pub(crate) fn satpoint_to_sequence_number_remove_all(&self, v: &SatPointValue) -> crate::Result<()> { // self // .satpoint_to_sequence_number // .remove_all(v)?; @@ -62,7 +63,7 @@ impl StorageProcessor { pub(crate) fn home_inscriptions_len(&self) -> u64 { todo!() } - pub(crate) fn sequence_number_to_satpoint_insert(&mut self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { + pub(crate) fn sequence_number_to_satpoint_insert(&self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { // self.sequence_number_to_satpoint.insert(sequence_number, sat_point)?; let key = u32::as_bytes(&sequence_number).to_vec(); @@ -72,7 +73,7 @@ impl StorageProcessor { }); Ok(()) } - pub(crate) fn satpoint_to_sequence_number_insert(&mut self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { + pub(crate) fn satpoint_to_sequence_number_insert(&self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { // self.sequence_number_to_satpoint.insert(sequence, sat_point)?; let key = sat_point.to_vec(); @@ -82,7 +83,7 @@ impl StorageProcessor { }); Ok(()) } - pub(crate) fn home_inscriptions_pop_first(&mut self) -> crate::Result<()> { + pub(crate) fn home_inscriptions_pop_first(&self) -> crate::Result<()> { // self.home_inscriptions.pop_first()?; self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { @@ -90,7 +91,7 @@ impl StorageProcessor { }); Ok(()) } - pub(crate) fn home_inscriptions_insert(&mut self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { + pub(crate) fn home_inscriptions_insert(&self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { let key = u32::as_bytes(sequence_number).to_vec(); let value = InscriptionIdValue::as_bytes(&value).to_vec(); self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { @@ -102,7 +103,7 @@ impl StorageProcessor { // .insert(sequence_number, value)?; // Ok(()) } - pub(crate) fn id_to_sequence_number_insert(&mut self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { + pub(crate) fn id_to_sequence_number_insert(&self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { // let key = rmp_serde::to_vec(value).unwrap(); // let value = sequence.to_le_bytes().as_slice(); // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |v| { @@ -114,7 +115,7 @@ impl StorageProcessor { // .insert(value, sequence_number)?; Ok(()) } - pub(crate) fn sequence_number_to_children_insert(&mut self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { + pub(crate) fn sequence_number_to_children_insert(&self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { // let key = sequence.to_le_bytes().as_slice(); // let value = rmp_serde::to_vec(value).unwrap(); // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_CHILDREN, |v| { @@ -126,7 +127,7 @@ impl StorageProcessor { // .insert(parent_sequence_number, sequence_number)?; Ok(()) } - pub(crate) fn sequence_number_to_entry_insert(&mut self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { + pub(crate) fn sequence_number_to_entry_insert(&self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { // let key = sequence.to_le_bytes().as_slice(); // let value = rmp_serde::to_vec(value).unwrap(); // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |v| { @@ -136,7 +137,7 @@ impl StorageProcessor { // self.sequence_number_to_entry.insert(sequence, value)?; Ok(()) } - pub(crate) fn sat_to_sequence_number_insert(&mut self, n: &u64, sequence_number: &u32) -> crate::Result<()> { + pub(crate) fn sat_to_sequence_number_insert(&self, n: &u64, sequence_number: &u32) -> crate::Result<()> { // let key = n.to_le_bytes().as_slice(); // let value = sequence.to_le_bytes().as_slice(); // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { @@ -146,7 +147,7 @@ impl StorageProcessor { // self.sat_to_sequence_number.insert(n, sequence_number)?; Ok(()) } - pub(crate) fn inscription_number_to_sequence_number_insert(&mut self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { + pub(crate) fn inscription_number_to_sequence_number_insert(&self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { // let key = inscription_number.to_le_bytes().as_slice(); // let value = sequence_number.to_le_bytes().as_slice(); // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, |v| { @@ -158,7 +159,7 @@ impl StorageProcessor { // .insert(inscription_number, sequence_number)?; Ok(()) } - pub(crate) fn outpoint_to_entry_insert(&mut self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { + pub(crate) fn outpoint_to_entry_insert(&self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { // self.outpoint_to_entry.insert(value, entry)?; Ok(()) // let key = rmp_serde::to_vec(value).unwrap(); @@ -168,7 +169,7 @@ impl StorageProcessor { // }); // Ok(()) } - pub fn inscriptions_on_output(&mut self, prev_output: &OutPoint) -> crate::Result> { + pub fn inscriptions_on_output(&self, prev_output: &OutPoint) -> crate::Result> { // let ret = Index::inscriptions_on_output( // self.satpoint_to_sequence_number, // self.sequence_number_to_entry, @@ -177,7 +178,7 @@ impl StorageProcessor { todo!() } - pub(crate) fn transaction_id_to_transaction_insert(&mut self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { + pub(crate) fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { // self // .transaction_id_to_transaction // .insert(tx_id, value)?; @@ -201,7 +202,4 @@ impl StorageProcessor { // Ok(Some(ret)) todo!() } - pub fn new(cache_writer: CacheWriter, internal: Arc) -> Self { - Self { cache_writer, internal } - } } \ No newline at end of file diff --git a/src/index/simulate.rs b/src/index/simulate.rs index 47e0188164..dac8449e7d 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -1,4 +1,5 @@ use std::collections::{HashMap, HashSet, VecDeque}; +use std::marker::PhantomData; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Instant; @@ -14,20 +15,22 @@ use crate::index::entry::{Entry, SatPointValue, SatRange}; use crate::index::processor::StorageProcessor; use crate::index::updater::pending_updater::PendingUpdater; use crate::okx::datastore::cache::CacheWriter; +use crate::okx::datastore::ord::InscriptionOp; use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::lru::SimpleLru; use crate::okx::protocol::{BlockContext, ProtocolConfig, ProtocolManager}; use crate::okx::protocol::context::Context; use crate::okx::protocol::trace::IndexTracer; -pub struct Simulator { +pub struct Simulator<'a, 'db> { options: Options, simulate_index: IndexTracer, internal_index: Arc, - processor: StorageProcessor, + _marker_a: PhantomData<&'a ()>, + _marker_b: PhantomData<&'db ()>, } -impl Simulator { +impl<'a, 'db> Simulator<'a, 'db> { pub fn simulate_tx(&self) {} // fn index_block( @@ -321,10 +324,12 @@ impl Simulator { &mut self, index: &Index, height: u32, - outpoint_sender: &mut Sender, - tx_out_receiver: &mut Receiver, + outpoint_sender: &'a mut Sender, + tx_out_receiver: &'a mut Receiver, block: BlockData, - tx_out_cache: &mut SimpleLru, + tx_out_cache: &'a mut SimpleLru, + processor: &'db mut StorageProcessor<'a, 'db>, + operations: &'db mut HashMap> ) -> crate::Result<()> { let start = Instant::now(); let mut sat_ranges_written = 0; @@ -368,7 +373,7 @@ impl Simulator { } else if tx_out_cache.contains(&prev_output) { cache_outputs_count.fetch_add(1, Ordering::Relaxed); None - } else if let Some(txout) = self.processor.get_txout_by_outpoint(&prev_output).unwrap() + } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output).unwrap() { miss_outputs_count.fetch_add(1, Ordering::Relaxed); Some((prev_output, Some(txout))) @@ -387,35 +392,15 @@ impl Simulator { } } - let time = timestamp(block.header.time); + let mut lost_sats = processor.get_lost_sats()?; + let cursed_inscription_count = processor.get_cursed_inscription_count()?; + let blessed_inscription_count = processor.get_blessed_inscription_count()?; + let unbound_inscriptions = processor.get_unbound_inscriptions()?; + let next_sequence_number = processor.next_sequence_number()?; - log::info!( - "Block {} at {} with {} transactions, fetching previous outputs {}/{}…, {},{},{}, cost:{}ms", - height, - time, - block.txdata.len(), - fetching_outputs_count.load(Ordering::Relaxed), - total_outputs_count.load(Ordering::Relaxed), - miss_outputs_count.load(Ordering::Relaxed), - meet_outputs_count.load(Ordering::Relaxed), - cache_outputs_count.load(Ordering::Relaxed), - start.elapsed().as_millis(), - ); - - let mut lost_sats = self.processor.get_lost_sats()?; - - let cursed_inscription_count = self.processor.get_cursed_inscription_count()?; - - let blessed_inscription_count = self.processor.get_blessed_inscription_count()?; - - let unbound_inscriptions = self.processor.get_unbound_inscriptions()?; - - let next_sequence_number = self.processor.next_sequence_number()?; - - let mut operations = HashMap::new(); - let mut processor = self.processor.clone(); + // let processor = &mut self.processor; let mut inscription_updater = PendingUpdater::new( - &mut operations, + operations, blessed_inscription_count, self.internal_index.options.chain(), cursed_inscription_count, @@ -427,7 +412,7 @@ impl Simulator { unbound_inscriptions, tx_out_receiver, tx_out_cache, - &mut processor, + processor, )?; let index_sats = true; @@ -445,26 +430,6 @@ impl Simulator { let mut input_sat_ranges = VecDeque::new(); - // TODO: make sure this is correct - // for input in &tx.input { - // let key = input.previous_output.store(); - // let sat_ranges = match self.range_cache.remove(&key) { - // Some(sat_ranges) => { - // self.outputs_cached += 1; - // sat_ranges - // } - // None => outpoint_to_sat_ranges - // .remove(&key)? - // .ok_or_else(|| anyhow!("Could not find outpoint {} in index", input.previous_output))? - // .value() - // .to_vec(), - // }; - // - // for chunk in sat_ranges.chunks_exact(11) { - // input_sat_ranges.push_back(SatRange::load(chunk.try_into().unwrap())); - // } - // } - self.index_transaction_sats( tx, *txid, @@ -491,12 +456,12 @@ impl Simulator { } if !coinbase_inputs.is_empty() { - let mut lost_sat_ranges = self.processor.outpoint_to_sat_ranges_remove(&OutPoint::null().store())?.map(|ranges| ranges.to_vec()) + let mut lost_sat_ranges = processor.outpoint_to_sat_ranges_remove(&OutPoint::null().store())?.map(|ranges| ranges.to_vec()) .unwrap_or_default(); for (start, end) in coinbase_inputs { if !Sat(start).common() { - self.processor.sat_to_satpoint_insert( + processor.sat_to_satpoint_insert( &start, &SatPoint { outpoint: OutPoint::null(), @@ -510,7 +475,7 @@ impl Simulator { lost_sats += end - start; } - self.processor.outpoint_to_sat_ranges_insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; + processor.outpoint_to_sat_ranges_insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; } } else if index_inscriptions { for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { @@ -519,13 +484,19 @@ impl Simulator { } inscription_updater.flush_cache()?; - let mut context=self.processor.create_context()?; - // Create a protocol manager to index the block of bitmap data. - let config = ProtocolConfig::new_with_options(&index.options); - ProtocolManager::new(config).index_block(&mut context, &block, operations)?; + // TODO: + // let mut context = processor.create_context()?; + // // Create a protocol manager to index the block of bitmap data. + // let config = ProtocolConfig::new_with_options(&index.options); + // ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; Ok(()) } + + fn index_and_execute(&self,){ + + self.index_block() + } fn index_transaction_sats( &mut self, tx: &Transaction, @@ -554,7 +525,7 @@ impl Simulator { .ok_or_else(|| anyhow!("insufficient inputs for transaction outputs"))?; if !Sat(range.0).common() { - self.processor.sat_to_satpoint_insert( + inscription_updater.processor.sat_to_satpoint_insert( &range.0, &SatPoint { outpoint, diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index 25282445f4..da041510f1 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -6,8 +6,8 @@ use crate::index::processor::StorageProcessor; use crate::index::updater::inscription_updater::{Flotsam, Origin}; -pub struct PendingUpdater<'a> { - processor: &'a mut StorageProcessor, +pub struct PendingUpdater<'a, 'db> { + pub processor: &'a StorageProcessor<'a, 'db>, pub(super) operations: &'a mut HashMap>, pub(super) blessed_inscription_count: u64, pub(super) chain: Chain, @@ -27,7 +27,7 @@ pub struct PendingUpdater<'a> { pub(super) new_outpoints: Vec, } -impl<'a> PendingUpdater<'a> { +impl<'db: 'a, 'a> PendingUpdater<'a, 'db> { pub fn new( operations: &'a mut HashMap>, blessed_inscription_count: u64, @@ -41,7 +41,7 @@ impl<'a> PendingUpdater<'a> { unbound_inscriptions: u64, tx_out_receiver: &'a mut Receiver, tx_out_cache: &'a mut SimpleLru, - processor: &'a mut StorageProcessor, + processor: &'db StorageProcessor<'a, 'db>, ) -> Result { let home_inscriptions_len = processor.home_inscriptions_len(); Ok(Self { From 1f3d49a3268d9fe103630122324266941aeb557c Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 11 Jan 2024 19:52:09 +0800 Subject: [PATCH 10/66] fuck5 --- src/index/simulate.rs | 1118 ++++++++++++------------ src/okx/protocol/brc20/msg_executor.rs | 753 ++++++++-------- src/okx/protocol/brc20/msg_resolver.rs | 290 +++--- src/okx/protocol/context.rs | 473 +++++----- src/okx/protocol/execute_manager.rs | 4 +- src/okx/protocol/mod.rs | 53 +- src/okx/protocol/ord/bitmap.rs | 139 +-- src/okx/protocol/protocol_manager.rs | 13 +- src/okx/protocol/resolve_manager.rs | 100 +-- 9 files changed, 1492 insertions(+), 1451 deletions(-) diff --git a/src/index/simulate.rs b/src/index/simulate.rs index dac8449e7d..ced1977354 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -1,560 +1,558 @@ -use std::collections::{HashMap, HashSet, VecDeque}; -use std::marker::PhantomData; -use std::sync::Arc; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::time::Instant; -use anyhow::anyhow; -use bitcoin::{OutPoint, Transaction, Txid, TxOut}; -use redb::{ReadableTable, Table, WriteTransaction}; -use tokio::sync::mpsc::{Receiver, Sender}; -use tokio::sync::mpsc::error::TryRecvError; -use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; -use crate::height::Height; -use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; -use crate::index::entry::{Entry, SatPointValue, SatRange}; -use crate::index::processor::StorageProcessor; -use crate::index::updater::pending_updater::PendingUpdater; -use crate::okx::datastore::cache::CacheWriter; -use crate::okx::datastore::ord::InscriptionOp; -use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; -use crate::okx::lru::SimpleLru; -use crate::okx::protocol::{BlockContext, ProtocolConfig, ProtocolManager}; -use crate::okx::protocol::context::Context; -use crate::okx::protocol::trace::IndexTracer; - -pub struct Simulator<'a, 'db> { - options: Options, - simulate_index: IndexTracer, - internal_index: Arc, - _marker_a: PhantomData<&'a ()>, - _marker_b: PhantomData<&'db ()>, -} - -impl<'a, 'db> Simulator<'a, 'db> { - pub fn simulate_tx(&self) {} - - // fn index_block( - // &mut self, - // index: &Index, - // height: u32, - // outpoint_sender: &mut Sender, - // tx_out_receiver: &mut Receiver, - // block: BlockData, - // tx_out_cache: &mut SimpleLru, - // wtx: &mut WriteTransaction, - // ) -> crate::Result<()> { - // let start = Instant::now(); - // let mut sat_ranges_written = 0; - // let mut outputs_in_block = 0; - // - // // If value_receiver still has values something went wrong with the last block - // // Could be an assert, shouldn't recover from this and commit the last block - // let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { - // return Err(anyhow!("Previous block did not consume all input values")); - // }; - // - // let mut outpoint_to_entry = wtx.open_table(OUTPOINT_TO_ENTRY)?; - // - // let index_inscriptions = true; - // - // let fetching_outputs_count = AtomicUsize::new(0); - // let total_outputs_count = AtomicUsize::new(0); - // let cache_outputs_count = AtomicUsize::new(0); - // let miss_outputs_count = AtomicUsize::new(0); - // let meet_outputs_count = AtomicUsize::new(0); - // if index_inscriptions { - // // Send all missing input outpoints to be fetched right away - // let txids = block - // .txdata - // .iter() - // .map(|(_, txid)| txid) - // .collect::>(); - // use rayon::prelude::*; - // let tx_outs = block - // .txdata - // .par_iter() - // .flat_map(|(tx, _)| tx.input.par_iter()) - // .filter_map(|input| { - // total_outputs_count.fetch_add(1, Ordering::Relaxed); - // let prev_output = input.previous_output; - // // We don't need coinbase input value - // if prev_output.is_null() { - // None - // } else if txids.contains(&prev_output.txid) { - // meet_outputs_count.fetch_add(1, Ordering::Relaxed); - // None - // } else if tx_out_cache.contains(&prev_output) { - // cache_outputs_count.fetch_add(1, Ordering::Relaxed); - // None - // } else if let Some(txout) = - // get_txout_by_outpoint(&outpoint_to_entry, &prev_output).unwrap() - // { - // miss_outputs_count.fetch_add(1, Ordering::Relaxed); - // Some((prev_output, Some(txout))) - // } else { - // fetching_outputs_count.fetch_add(1, Ordering::Relaxed); - // Some((prev_output, None)) - // } - // }) - // .collect::>(); - // for (out_point, value) in tx_outs.into_iter() { - // if let Some(tx_out) = value { - // tx_out_cache.insert(out_point, tx_out); - // } else { - // outpoint_sender.blocking_send(out_point).unwrap(); - // } - // } - // } - // - // let time = timestamp(block.header.time); - // - // log::info!( - // "Block {} at {} with {} transactions, fetching previous outputs {}/{}…, {},{},{}, cost:{}ms", - // height, - // time, - // block.txdata.len(), - // fetching_outputs_count.load(Ordering::Relaxed), - // total_outputs_count.load(Ordering::Relaxed), - // miss_outputs_count.load(Ordering::Relaxed), - // meet_outputs_count.load(Ordering::Relaxed), - // cache_outputs_count.load(Ordering::Relaxed), - // start.elapsed().as_millis(), - // ); - // - // let mut height_to_block_header = wtx.open_table(HEIGHT_TO_BLOCK_HEADER)?; - // let mut height_to_last_sequence_number = wtx.open_table(HEIGHT_TO_LAST_SEQUENCE_NUMBER)?; - // let mut home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS)?; - // let mut inscription_id_to_sequence_number = - // wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; - // let mut inscription_number_to_sequence_number = - // wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER)?; - // let mut sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER)?; - // let mut satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; - // let mut sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN)?; - // let mut sequence_number_to_inscription_entry = - // wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; - // let mut sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT)?; - // let mut statistic_to_count = wtx.open_table(STATISTIC_TO_COUNT)?; - // let mut transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION)?; - // - // let mut lost_sats = statistic_to_count - // .get(&Statistic::LostSats.key())? - // .map(|lost_sats| lost_sats.value()) - // .unwrap_or(0); - // - // let cursed_inscription_count = statistic_to_count - // .get(&Statistic::CursedInscriptions.key())? - // .map(|count| count.value()) - // .unwrap_or(0); - // - // let blessed_inscription_count = statistic_to_count - // .get(&Statistic::BlessedInscriptions.key())? - // .map(|count| count.value()) - // .unwrap_or(0); - // - // let unbound_inscriptions = statistic_to_count - // .get(&Statistic::UnboundInscriptions.key())? - // .map(|unbound_inscriptions| unbound_inscriptions.value()) - // .unwrap_or(0); - // - // let next_sequence_number = sequence_number_to_inscription_entry - // .iter()? - // .next_back() - // .and_then(|result| result.ok()) - // .map(|(number, _id)| number.value() + 1) - // .unwrap_or(0); - // - // let mut operations = HashMap::new(); - // let mut processor = StorageProcessor::new(self.cache.clone(),self.internal_index.clone()); - // // let mut processor = crate::index::updater::pending_updater::PendingStorageProcessor::new( - // // &mut home_inscriptions, - // // &mut inscription_id_to_sequence_number, - // // &mut inscription_number_to_sequence_number, - // // &mut outpoint_to_entry, - // // &mut transaction_id_to_transaction, - // // &mut sat_to_sequence_number, - // // &mut satpoint_to_sequence_number, - // // &mut sequence_number_to_children, - // // &mut sequence_number_to_inscription_entry, - // // &mut sequence_number_to_satpoint, - // // ); - // let mut inscription_updater = PendingUpdater::new( - // &mut operations, - // blessed_inscription_count, - // self.internal_index.options.chain(), - // cursed_inscription_count, - // height, - // self.internal_index.index_transactions, - // next_sequence_number, - // lost_sats, - // block.header.time, - // unbound_inscriptions, - // tx_out_receiver, - // tx_out_cache, - // &mut processor, - // )?; - // - // let index_sats = true; - // if index_sats { - // let mut sat_to_satpoint = wtx.open_table(SAT_TO_SATPOINT)?; - // let mut outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES)?; - // - // let mut coinbase_inputs = VecDeque::new(); - // - // let h = Height(height); - // if h.subsidy() > 0 { - // let start = h.starting_sat(); - // coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); - // } - // - // for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { - // log::trace!("Indexing transaction {tx_offset}…"); - // - // let mut input_sat_ranges = VecDeque::new(); - // - // // TODO: make sure this is correct - // // for input in &tx.input { - // // let key = input.previous_output.store(); - // // let sat_ranges = match self.range_cache.remove(&key) { - // // Some(sat_ranges) => { - // // self.outputs_cached += 1; - // // sat_ranges - // // } - // // None => outpoint_to_sat_ranges - // // .remove(&key)? - // // .ok_or_else(|| anyhow!("Could not find outpoint {} in index", input.previous_output))? - // // .value() - // // .to_vec(), - // // }; - // // - // // for chunk in sat_ranges.chunks_exact(11) { - // // input_sat_ranges.push_back(SatRange::load(chunk.try_into().unwrap())); - // // } - // // } - // - // self.index_transaction_sats( - // tx, - // *txid, - // &mut sat_to_satpoint, - // &mut input_sat_ranges, - // &mut sat_ranges_written, - // &mut outputs_in_block, - // &mut inscription_updater, - // index_inscriptions, - // )?; - // - // coinbase_inputs.extend(input_sat_ranges); - // } - // - // if let Some((tx, txid)) = block.txdata.first() { - // self.index_transaction_sats( - // tx, - // *txid, - // &mut sat_to_satpoint, - // &mut coinbase_inputs, - // &mut sat_ranges_written, - // &mut outputs_in_block, - // &mut inscription_updater, - // index_inscriptions, - // )?; - // } - // - // if !coinbase_inputs.is_empty() { - // let mut lost_sat_ranges = outpoint_to_sat_ranges - // .remove(&OutPoint::null().store())? - // .map(|ranges| ranges.value().to_vec()) - // .unwrap_or_default(); - // - // for (start, end) in coinbase_inputs { - // if !Sat(start).common() { - // sat_to_satpoint.insert( - // &start, - // &SatPoint { - // outpoint: OutPoint::null(), - // offset: lost_sats, - // } - // .store(), - // )?; - // } - // - // lost_sat_ranges.extend_from_slice(&(start, end).store()); - // - // lost_sats += end - start; - // } - // - // outpoint_to_sat_ranges.insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; - // } - // } else if index_inscriptions { - // for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { - // inscription_updater.index_envelopes(tx, *txid, None)?; - // } - // } - // inscription_updater.flush_cache()?; - // - // let mut context = Context { - // chain: BlockContext { - // network: index.get_chain_network(), - // blockheight: height, - // blocktime: block.header.time, - // }, - // tx_out_cache, - // hit: 0, - // miss: 0, - // ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS)?, - // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, - // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx - // .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, - // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut sequence_number_to_inscription_entry, - // OUTPOINT_TO_ENTRY: &mut outpoint_to_entry, - // BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES)?, - // BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN)?, - // BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS)?, - // BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG)?, - // BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER)?, - // }; - // - // // Create a protocol manager to index the block of bitmap data. - // let config = ProtocolConfig::new_with_options(&index.options); - // ProtocolManager::new(config).index_block(&mut context, &block, operations)?; - // - // Ok(()) - // } - - fn index_block( - &mut self, - index: &Index, - height: u32, - outpoint_sender: &'a mut Sender, - tx_out_receiver: &'a mut Receiver, - block: BlockData, - tx_out_cache: &'a mut SimpleLru, - processor: &'db mut StorageProcessor<'a, 'db>, - operations: &'db mut HashMap> - ) -> crate::Result<()> { - let start = Instant::now(); - let mut sat_ranges_written = 0; - let mut outputs_in_block = 0; - - // If value_receiver still has values something went wrong with the last block - // Could be an assert, shouldn't recover from this and commit the last block - let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { - return Err(anyhow!("Previous block did not consume all input values")); - }; - - - let index_inscriptions = true; - - let fetching_outputs_count = AtomicUsize::new(0); - let total_outputs_count = AtomicUsize::new(0); - let cache_outputs_count = AtomicUsize::new(0); - let miss_outputs_count = AtomicUsize::new(0); - let meet_outputs_count = AtomicUsize::new(0); - if index_inscriptions { - // Send all missing input outpoints to be fetched right away - let txids = block - .txdata - .iter() - .map(|(_, txid)| txid) - .collect::>(); - use rayon::prelude::*; - let tx_outs = block - .txdata - .par_iter() - .flat_map(|(tx, _)| tx.input.par_iter()) - .filter_map(|input| { - total_outputs_count.fetch_add(1, Ordering::Relaxed); - let prev_output = input.previous_output; - // We don't need coinbase input value - if prev_output.is_null() { - None - } else if txids.contains(&prev_output.txid) { - meet_outputs_count.fetch_add(1, Ordering::Relaxed); - None - } else if tx_out_cache.contains(&prev_output) { - cache_outputs_count.fetch_add(1, Ordering::Relaxed); - None - } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output).unwrap() - { - miss_outputs_count.fetch_add(1, Ordering::Relaxed); - Some((prev_output, Some(txout))) - } else { - fetching_outputs_count.fetch_add(1, Ordering::Relaxed); - Some((prev_output, None)) - } - }) - .collect::>(); - for (out_point, value) in tx_outs.into_iter() { - if let Some(tx_out) = value { - tx_out_cache.insert(out_point, tx_out); - } else { - outpoint_sender.blocking_send(out_point).unwrap(); - } - } - } - - let mut lost_sats = processor.get_lost_sats()?; - let cursed_inscription_count = processor.get_cursed_inscription_count()?; - let blessed_inscription_count = processor.get_blessed_inscription_count()?; - let unbound_inscriptions = processor.get_unbound_inscriptions()?; - let next_sequence_number = processor.next_sequence_number()?; - - // let processor = &mut self.processor; - let mut inscription_updater = PendingUpdater::new( - operations, - blessed_inscription_count, - self.internal_index.options.chain(), - cursed_inscription_count, - height, - self.internal_index.index_transactions, - next_sequence_number, - lost_sats, - block.header.time, - unbound_inscriptions, - tx_out_receiver, - tx_out_cache, - processor, - )?; - - let index_sats = true; - if index_sats { - let mut coinbase_inputs = VecDeque::new(); - - let h = Height(height); - if h.subsidy() > 0 { - let start = h.starting_sat(); - coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); - } - - for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { - log::trace!("Indexing transaction {tx_offset}…"); - - let mut input_sat_ranges = VecDeque::new(); - - self.index_transaction_sats( - tx, - *txid, - &mut input_sat_ranges, - &mut sat_ranges_written, - &mut outputs_in_block, - &mut inscription_updater, - index_inscriptions, - )?; - - coinbase_inputs.extend(input_sat_ranges); - } - - if let Some((tx, txid)) = block.txdata.first() { - self.index_transaction_sats( - tx, - *txid, - &mut coinbase_inputs, - &mut sat_ranges_written, - &mut outputs_in_block, - &mut inscription_updater, - index_inscriptions, - )?; - } - - if !coinbase_inputs.is_empty() { - let mut lost_sat_ranges = processor.outpoint_to_sat_ranges_remove(&OutPoint::null().store())?.map(|ranges| ranges.to_vec()) - .unwrap_or_default(); - - for (start, end) in coinbase_inputs { - if !Sat(start).common() { - processor.sat_to_satpoint_insert( - &start, - &SatPoint { - outpoint: OutPoint::null(), - offset: lost_sats, - } - .store(), - )?; - } - - lost_sat_ranges.extend_from_slice(&(start, end).store()); - - lost_sats += end - start; - } - processor.outpoint_to_sat_ranges_insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; - } - } else if index_inscriptions { - for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { - inscription_updater.index_envelopes(tx, *txid, None)?; - } - } - inscription_updater.flush_cache()?; - - // TODO: - // let mut context = processor.create_context()?; - // // Create a protocol manager to index the block of bitmap data. - // let config = ProtocolConfig::new_with_options(&index.options); - // ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; - - Ok(()) - } - - fn index_and_execute(&self,){ - - self.index_block() - } - fn index_transaction_sats( - &mut self, - tx: &Transaction, - txid: Txid, - input_sat_ranges: &mut VecDeque<(u64, u64)>, - sat_ranges_written: &mut u64, - outputs_traversed: &mut u64, - inscription_updater: &mut PendingUpdater, - index_inscriptions: bool, - ) -> crate::Result { - if index_inscriptions { - inscription_updater.index_envelopes(tx, txid, Some(input_sat_ranges))?; - } - - for (vout, output) in tx.output.iter().enumerate() { - let outpoint = OutPoint { - vout: vout.try_into().unwrap(), - txid, - }; - let mut sats = Vec::new(); - - let mut remaining = output.value; - while remaining > 0 { - let range = input_sat_ranges - .pop_front() - .ok_or_else(|| anyhow!("insufficient inputs for transaction outputs"))?; - - if !Sat(range.0).common() { - inscription_updater.processor.sat_to_satpoint_insert( - &range.0, - &SatPoint { - outpoint, - offset: 0, - } - .store(), - )?; - } - - let count = range.1 - range.0; - - let assigned = if count > remaining { - let middle = range.0 + remaining; - input_sat_ranges.push_front((middle, range.1)); - (range.0, middle) - } else { - range - }; - - sats.extend_from_slice(&assigned.store()); - - remaining -= assigned.1 - assigned.0; - - *sat_ranges_written += 1; - } - - *outputs_traversed += 1; - } - - Ok(()) - } -} +// use std::collections::{HashMap, HashSet, VecDeque}; +// use std::marker::PhantomData; +// use std::sync::Arc; +// use std::sync::atomic::{AtomicUsize, Ordering}; +// use std::time::Instant; +// use anyhow::anyhow; +// use bitcoin::{OutPoint, Transaction, Txid, TxOut}; +// use redb::{ReadableTable, Table, WriteTransaction}; +// use tokio::sync::mpsc::{Receiver, Sender}; +// use tokio::sync::mpsc::error::TryRecvError; +// use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; +// use crate::height::Height; +// use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; +// use crate::index::entry::{Entry, SatPointValue, SatRange}; +// use crate::index::processor::StorageProcessor; +// use crate::index::updater::pending_updater::PendingUpdater; +// use crate::okx::datastore::cache::CacheWriter; +// use crate::okx::datastore::ord::InscriptionOp; +// use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; +// use crate::okx::lru::SimpleLru; +// use crate::okx::protocol::{BlockContext, ProtocolConfig, ProtocolManager}; +// use crate::okx::protocol::context::Context; +// use crate::okx::protocol::trace::IndexTracer; +// +// pub struct Simulator<'a, 'db> { +// options: Options, +// simulate_index: IndexTracer, +// internal_index: Arc, +// _marker_a: PhantomData<&'a ()>, +// _marker_b: PhantomData<&'db ()>, +// } +// +// impl<'a, 'db> Simulator<'a, 'db> { +// pub fn simulate_tx(&self) {} +// +// // fn index_block( +// // &mut self, +// // index: &Index, +// // height: u32, +// // outpoint_sender: &mut Sender, +// // tx_out_receiver: &mut Receiver, +// // block: BlockData, +// // tx_out_cache: &mut SimpleLru, +// // wtx: &mut WriteTransaction, +// // ) -> crate::Result<()> { +// // let start = Instant::now(); +// // let mut sat_ranges_written = 0; +// // let mut outputs_in_block = 0; +// // +// // // If value_receiver still has values something went wrong with the last block +// // // Could be an assert, shouldn't recover from this and commit the last block +// // let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { +// // return Err(anyhow!("Previous block did not consume all input values")); +// // }; +// // +// // let mut outpoint_to_entry = wtx.open_table(OUTPOINT_TO_ENTRY)?; +// // +// // let index_inscriptions = true; +// // +// // let fetching_outputs_count = AtomicUsize::new(0); +// // let total_outputs_count = AtomicUsize::new(0); +// // let cache_outputs_count = AtomicUsize::new(0); +// // let miss_outputs_count = AtomicUsize::new(0); +// // let meet_outputs_count = AtomicUsize::new(0); +// // if index_inscriptions { +// // // Send all missing input outpoints to be fetched right away +// // let txids = block +// // .txdata +// // .iter() +// // .map(|(_, txid)| txid) +// // .collect::>(); +// // use rayon::prelude::*; +// // let tx_outs = block +// // .txdata +// // .par_iter() +// // .flat_map(|(tx, _)| tx.input.par_iter()) +// // .filter_map(|input| { +// // total_outputs_count.fetch_add(1, Ordering::Relaxed); +// // let prev_output = input.previous_output; +// // // We don't need coinbase input value +// // if prev_output.is_null() { +// // None +// // } else if txids.contains(&prev_output.txid) { +// // meet_outputs_count.fetch_add(1, Ordering::Relaxed); +// // None +// // } else if tx_out_cache.contains(&prev_output) { +// // cache_outputs_count.fetch_add(1, Ordering::Relaxed); +// // None +// // } else if let Some(txout) = +// // get_txout_by_outpoint(&outpoint_to_entry, &prev_output).unwrap() +// // { +// // miss_outputs_count.fetch_add(1, Ordering::Relaxed); +// // Some((prev_output, Some(txout))) +// // } else { +// // fetching_outputs_count.fetch_add(1, Ordering::Relaxed); +// // Some((prev_output, None)) +// // } +// // }) +// // .collect::>(); +// // for (out_point, value) in tx_outs.into_iter() { +// // if let Some(tx_out) = value { +// // tx_out_cache.insert(out_point, tx_out); +// // } else { +// // outpoint_sender.blocking_send(out_point).unwrap(); +// // } +// // } +// // } +// // +// // let time = timestamp(block.header.time); +// // +// // log::info!( +// // "Block {} at {} with {} transactions, fetching previous outputs {}/{}…, {},{},{}, cost:{}ms", +// // height, +// // time, +// // block.txdata.len(), +// // fetching_outputs_count.load(Ordering::Relaxed), +// // total_outputs_count.load(Ordering::Relaxed), +// // miss_outputs_count.load(Ordering::Relaxed), +// // meet_outputs_count.load(Ordering::Relaxed), +// // cache_outputs_count.load(Ordering::Relaxed), +// // start.elapsed().as_millis(), +// // ); +// // +// // let mut height_to_block_header = wtx.open_table(HEIGHT_TO_BLOCK_HEADER)?; +// // let mut height_to_last_sequence_number = wtx.open_table(HEIGHT_TO_LAST_SEQUENCE_NUMBER)?; +// // let mut home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS)?; +// // let mut inscription_id_to_sequence_number = +// // wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; +// // let mut inscription_number_to_sequence_number = +// // wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER)?; +// // let mut sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER)?; +// // let mut satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; +// // let mut sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN)?; +// // let mut sequence_number_to_inscription_entry = +// // wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; +// // let mut sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT)?; +// // let mut statistic_to_count = wtx.open_table(STATISTIC_TO_COUNT)?; +// // let mut transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION)?; +// // +// // let mut lost_sats = statistic_to_count +// // .get(&Statistic::LostSats.key())? +// // .map(|lost_sats| lost_sats.value()) +// // .unwrap_or(0); +// // +// // let cursed_inscription_count = statistic_to_count +// // .get(&Statistic::CursedInscriptions.key())? +// // .map(|count| count.value()) +// // .unwrap_or(0); +// // +// // let blessed_inscription_count = statistic_to_count +// // .get(&Statistic::BlessedInscriptions.key())? +// // .map(|count| count.value()) +// // .unwrap_or(0); +// // +// // let unbound_inscriptions = statistic_to_count +// // .get(&Statistic::UnboundInscriptions.key())? +// // .map(|unbound_inscriptions| unbound_inscriptions.value()) +// // .unwrap_or(0); +// // +// // let next_sequence_number = sequence_number_to_inscription_entry +// // .iter()? +// // .next_back() +// // .and_then(|result| result.ok()) +// // .map(|(number, _id)| number.value() + 1) +// // .unwrap_or(0); +// // +// // let mut operations = HashMap::new(); +// // let mut processor = StorageProcessor::new(self.cache.clone(),self.internal_index.clone()); +// // // let mut processor = crate::index::updater::pending_updater::PendingStorageProcessor::new( +// // // &mut home_inscriptions, +// // // &mut inscription_id_to_sequence_number, +// // // &mut inscription_number_to_sequence_number, +// // // &mut outpoint_to_entry, +// // // &mut transaction_id_to_transaction, +// // // &mut sat_to_sequence_number, +// // // &mut satpoint_to_sequence_number, +// // // &mut sequence_number_to_children, +// // // &mut sequence_number_to_inscription_entry, +// // // &mut sequence_number_to_satpoint, +// // // ); +// // let mut inscription_updater = PendingUpdater::new( +// // &mut operations, +// // blessed_inscription_count, +// // self.internal_index.options.chain(), +// // cursed_inscription_count, +// // height, +// // self.internal_index.index_transactions, +// // next_sequence_number, +// // lost_sats, +// // block.header.time, +// // unbound_inscriptions, +// // tx_out_receiver, +// // tx_out_cache, +// // &mut processor, +// // )?; +// // +// // let index_sats = true; +// // if index_sats { +// // let mut sat_to_satpoint = wtx.open_table(SAT_TO_SATPOINT)?; +// // let mut outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES)?; +// // +// // let mut coinbase_inputs = VecDeque::new(); +// // +// // let h = Height(height); +// // if h.subsidy() > 0 { +// // let start = h.starting_sat(); +// // coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); +// // } +// // +// // for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { +// // log::trace!("Indexing transaction {tx_offset}…"); +// // +// // let mut input_sat_ranges = VecDeque::new(); +// // +// // // TODO: make sure this is correct +// // // for input in &tx.input { +// // // let key = input.previous_output.store(); +// // // let sat_ranges = match self.range_cache.remove(&key) { +// // // Some(sat_ranges) => { +// // // self.outputs_cached += 1; +// // // sat_ranges +// // // } +// // // None => outpoint_to_sat_ranges +// // // .remove(&key)? +// // // .ok_or_else(|| anyhow!("Could not find outpoint {} in index", input.previous_output))? +// // // .value() +// // // .to_vec(), +// // // }; +// // // +// // // for chunk in sat_ranges.chunks_exact(11) { +// // // input_sat_ranges.push_back(SatRange::load(chunk.try_into().unwrap())); +// // // } +// // // } +// // +// // self.index_transaction_sats( +// // tx, +// // *txid, +// // &mut sat_to_satpoint, +// // &mut input_sat_ranges, +// // &mut sat_ranges_written, +// // &mut outputs_in_block, +// // &mut inscription_updater, +// // index_inscriptions, +// // )?; +// // +// // coinbase_inputs.extend(input_sat_ranges); +// // } +// // +// // if let Some((tx, txid)) = block.txdata.first() { +// // self.index_transaction_sats( +// // tx, +// // *txid, +// // &mut sat_to_satpoint, +// // &mut coinbase_inputs, +// // &mut sat_ranges_written, +// // &mut outputs_in_block, +// // &mut inscription_updater, +// // index_inscriptions, +// // )?; +// // } +// // +// // if !coinbase_inputs.is_empty() { +// // let mut lost_sat_ranges = outpoint_to_sat_ranges +// // .remove(&OutPoint::null().store())? +// // .map(|ranges| ranges.value().to_vec()) +// // .unwrap_or_default(); +// // +// // for (start, end) in coinbase_inputs { +// // if !Sat(start).common() { +// // sat_to_satpoint.insert( +// // &start, +// // &SatPoint { +// // outpoint: OutPoint::null(), +// // offset: lost_sats, +// // } +// // .store(), +// // )?; +// // } +// // +// // lost_sat_ranges.extend_from_slice(&(start, end).store()); +// // +// // lost_sats += end - start; +// // } +// // +// // outpoint_to_sat_ranges.insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; +// // } +// // } else if index_inscriptions { +// // for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { +// // inscription_updater.index_envelopes(tx, *txid, None)?; +// // } +// // } +// // inscription_updater.flush_cache()?; +// // +// // let mut context = Context { +// // chain: BlockContext { +// // network: index.get_chain_network(), +// // blockheight: height, +// // blocktime: block.header.time, +// // }, +// // tx_out_cache, +// // hit: 0, +// // miss: 0, +// // ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS)?, +// // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, +// // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx +// // .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, +// // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut sequence_number_to_inscription_entry, +// // OUTPOINT_TO_ENTRY: &mut outpoint_to_entry, +// // BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES)?, +// // BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN)?, +// // BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS)?, +// // BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG)?, +// // BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER)?, +// // }; +// // +// // // Create a protocol manager to index the block of bitmap data. +// // let config = ProtocolConfig::new_with_options(&index.options); +// // ProtocolManager::new(config).index_block(&mut context, &block, operations)?; +// // +// // Ok(()) +// // } +// +// fn index_block( +// &mut self, +// index: &Index, +// height: u32, +// outpoint_sender: &'a mut Sender, +// tx_out_receiver: &'a mut Receiver, +// block: BlockData, +// tx_out_cache: &'a mut SimpleLru, +// processor: &'db mut StorageProcessor<'a, 'db>, +// operations: &'db mut HashMap> +// ) -> crate::Result<()> { +// let start = Instant::now(); +// let mut sat_ranges_written = 0; +// let mut outputs_in_block = 0; +// +// // If value_receiver still has values something went wrong with the last block +// // Could be an assert, shouldn't recover from this and commit the last block +// let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { +// return Err(anyhow!("Previous block did not consume all input values")); +// }; +// +// +// let index_inscriptions = true; +// +// let fetching_outputs_count = AtomicUsize::new(0); +// let total_outputs_count = AtomicUsize::new(0); +// let cache_outputs_count = AtomicUsize::new(0); +// let miss_outputs_count = AtomicUsize::new(0); +// let meet_outputs_count = AtomicUsize::new(0); +// if index_inscriptions { +// // Send all missing input outpoints to be fetched right away +// let txids = block +// .txdata +// .iter() +// .map(|(_, txid)| txid) +// .collect::>(); +// use rayon::prelude::*; +// let tx_outs = block +// .txdata +// .par_iter() +// .flat_map(|(tx, _)| tx.input.par_iter()) +// .filter_map(|input| { +// total_outputs_count.fetch_add(1, Ordering::Relaxed); +// let prev_output = input.previous_output; +// // We don't need coinbase input value +// if prev_output.is_null() { +// None +// } else if txids.contains(&prev_output.txid) { +// meet_outputs_count.fetch_add(1, Ordering::Relaxed); +// None +// } else if tx_out_cache.contains(&prev_output) { +// cache_outputs_count.fetch_add(1, Ordering::Relaxed); +// None +// } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output).unwrap() +// { +// miss_outputs_count.fetch_add(1, Ordering::Relaxed); +// Some((prev_output, Some(txout))) +// } else { +// fetching_outputs_count.fetch_add(1, Ordering::Relaxed); +// Some((prev_output, None)) +// } +// }) +// .collect::>(); +// for (out_point, value) in tx_outs.into_iter() { +// if let Some(tx_out) = value { +// tx_out_cache.insert(out_point, tx_out); +// } else { +// outpoint_sender.blocking_send(out_point).unwrap(); +// } +// } +// } +// +// let mut lost_sats = processor.get_lost_sats()?; +// let cursed_inscription_count = processor.get_cursed_inscription_count()?; +// let blessed_inscription_count = processor.get_blessed_inscription_count()?; +// let unbound_inscriptions = processor.get_unbound_inscriptions()?; +// let next_sequence_number = processor.next_sequence_number()?; +// +// // let processor = &mut self.processor; +// let mut inscription_updater = PendingUpdater::new( +// operations, +// blessed_inscription_count, +// self.internal_index.options.chain(), +// cursed_inscription_count, +// height, +// self.internal_index.index_transactions, +// next_sequence_number, +// lost_sats, +// block.header.time, +// unbound_inscriptions, +// tx_out_receiver, +// tx_out_cache, +// processor, +// )?; +// +// let index_sats = true; +// if index_sats { +// let mut coinbase_inputs = VecDeque::new(); +// +// let h = Height(height); +// if h.subsidy() > 0 { +// let start = h.starting_sat(); +// coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); +// } +// +// for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { +// log::trace!("Indexing transaction {tx_offset}…"); +// +// let mut input_sat_ranges = VecDeque::new(); +// +// self.index_transaction_sats( +// tx, +// *txid, +// &mut input_sat_ranges, +// &mut sat_ranges_written, +// &mut outputs_in_block, +// &mut inscription_updater, +// index_inscriptions, +// )?; +// +// coinbase_inputs.extend(input_sat_ranges); +// } +// +// if let Some((tx, txid)) = block.txdata.first() { +// self.index_transaction_sats( +// tx, +// *txid, +// &mut coinbase_inputs, +// &mut sat_ranges_written, +// &mut outputs_in_block, +// &mut inscription_updater, +// index_inscriptions, +// )?; +// } +// +// if !coinbase_inputs.is_empty() { +// let mut lost_sat_ranges = processor.outpoint_to_sat_ranges_remove(&OutPoint::null().store())?.map(|ranges| ranges.to_vec()) +// .unwrap_or_default(); +// +// for (start, end) in coinbase_inputs { +// if !Sat(start).common() { +// processor.sat_to_satpoint_insert( +// &start, +// &SatPoint { +// outpoint: OutPoint::null(), +// offset: lost_sats, +// } +// .store(), +// )?; +// } +// +// lost_sat_ranges.extend_from_slice(&(start, end).store()); +// +// lost_sats += end - start; +// } +// processor.outpoint_to_sat_ranges_insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; +// } +// } else if index_inscriptions { +// for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { +// inscription_updater.index_envelopes(tx, *txid, None)?; +// } +// } +// inscription_updater.flush_cache()?; +// +// // TODO: +// // let mut context = processor.create_context()?; +// // // Create a protocol manager to index the block of bitmap data. +// // let config = ProtocolConfig::new_with_options(&index.options); +// // ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; +// +// Ok(()) +// } +// +// fn index_and_execute(&self,){ +// } +// // fn index_transaction_sats( +// // &mut self, +// // tx: &Transaction, +// // txid: Txid, +// // input_sat_ranges: &mut VecDeque<(u64, u64)>, +// // sat_ranges_written: &mut u64, +// // outputs_traversed: &mut u64, +// // inscription_updater: &mut PendingUpdater, +// // index_inscriptions: bool, +// // ) -> crate::Result { +// // if index_inscriptions { +// // inscription_updater.index_envelopes(tx, txid, Some(input_sat_ranges))?; +// // } +// // +// // for (vout, output) in tx.output.iter().enumerate() { +// // let outpoint = OutPoint { +// // vout: vout.try_into().unwrap(), +// // txid, +// // }; +// // let mut sats = Vec::new(); +// // +// // let mut remaining = output.value; +// // while remaining > 0 { +// // let range = input_sat_ranges +// // .pop_front() +// // .ok_or_else(|| anyhow!("insufficient inputs for transaction outputs"))?; +// // +// // if !Sat(range.0).common() { +// // inscription_updater.processor.sat_to_satpoint_insert( +// // &range.0, +// // &SatPoint { +// // outpoint, +// // offset: 0, +// // } +// // .store(), +// // )?; +// // } +// // +// // let count = range.1 - range.0; +// // +// // let assigned = if count > remaining { +// // let middle = range.0 + remaining; +// // input_sat_ranges.push_front((middle, range.1)); +// // (range.0, middle) +// // } else { +// // range +// // }; +// // +// // sats.extend_from_slice(&assigned.store()); +// // +// // remaining -= assigned.1 - assigned.0; +// // +// // *sat_ranges_written += 1; +// // } +// // +// // *outputs_traversed += 1; +// // } +// // +// // Ok(()) +// // } +// } diff --git a/src/okx/protocol/brc20/msg_executor.rs b/src/okx/protocol/brc20/msg_executor.rs index 28491a26ef..dfaa5be6bd 100644 --- a/src/okx/protocol/brc20/msg_executor.rs +++ b/src/okx/protocol/brc20/msg_executor.rs @@ -1,405 +1,412 @@ use super::{ - params::{BIGDECIMAL_TEN, MAXIMUM_SUPPLY, MAX_DECIMAL_WIDTH}, - *, + params::{BIGDECIMAL_TEN, MAXIMUM_SUPPLY, MAX_DECIMAL_WIDTH}, + *, }; use crate::okx::datastore::brc20::{Brc20Reader, Brc20ReaderWriter}; use crate::okx::datastore::ord::OrdReader; use crate::okx::protocol::context::Context; use crate::{ - okx::{ - datastore::brc20::{ - BRC20Error, Balance, DeployEvent, Event, InscripbeTransferEvent, MintEvent, Receipt, Tick, - TokenInfo, TransferEvent, TransferInfo, TransferableLog, + okx::{ + datastore::brc20::{ + BRC20Error, Balance, DeployEvent, Event, InscripbeTransferEvent, MintEvent, Receipt, Tick, + TokenInfo, TransferEvent, TransferInfo, TransferableLog, + }, + protocol::brc20::{Message, Mint, Operation}, }, - protocol::brc20::{Message, Mint, Operation}, - }, - Result, + Result, }; use anyhow::anyhow; use bigdecimal::num_bigint::Sign; use bitcoin::Network; use std::str::FromStr; +use crate::okx::protocol::ContextTrait; #[derive(Debug, Clone, PartialEq)] pub struct ExecutionMessage { - pub(self) txid: Txid, - pub(self) inscription_id: InscriptionId, - pub(self) inscription_number: i32, - pub(self) old_satpoint: SatPoint, - pub(self) new_satpoint: SatPoint, - pub(self) from: ScriptKey, - pub(self) to: Option, - pub(self) op: Operation, + pub(self) txid: Txid, + pub(self) inscription_id: InscriptionId, + pub(self) inscription_number: i32, + pub(self) old_satpoint: SatPoint, + pub(self) new_satpoint: SatPoint, + pub(self) from: ScriptKey, + pub(self) to: Option, + pub(self) op: Operation, } impl ExecutionMessage { - pub fn from_message(context: &mut Context, msg: &Message, network: Network) -> Result { - Ok(Self { - txid: msg.txid, - inscription_id: msg.inscription_id, - inscription_number: context.get_inscription_number_by_sequence_number(msg.sequence_number)?, - old_satpoint: msg.old_satpoint, - new_satpoint: msg - .new_satpoint - .ok_or(anyhow!("new satpoint cannot be None"))?, - from: context.get_script_key_on_satpoint(&msg.old_satpoint, network)?, - to: if msg.sat_in_outputs { - Some(context.get_script_key_on_satpoint(msg.new_satpoint.as_ref().unwrap(), network)?) - } else { - None - }, - op: msg.op.clone(), - }) - } -} - -pub fn execute(context: &mut Context, msg: &ExecutionMessage) -> Result { - log::debug!("BRC20 execute message: {:?}", msg); - let event = match &msg.op { - Operation::Deploy(deploy) => process_deploy(context, msg, deploy.clone()), - Operation::Mint(mint) => process_mint(context, msg, mint.clone()), - Operation::InscribeTransfer(transfer) => { - process_inscribe_transfer(context, msg, transfer.clone()) + pub fn from_message(context: &mut T, msg: &Message, network: Network) -> Result { + Ok(Self { + txid: msg.txid, + inscription_id: msg.inscription_id, + inscription_number: context.get_inscription_number_by_sequence_number(msg.sequence_number).map_err(|e| { + anyhow!("failed to get inscription number from state! error: {e}") + })?, + old_satpoint: msg.old_satpoint, + new_satpoint: msg + .new_satpoint + .ok_or(anyhow!("new satpoint cannot be None"))?, + from: context.get_script_key_on_satpoint(&msg.old_satpoint, network).map_err(|e| { + anyhow!("failed to get script key from state! error: {e}") + })?, + to: if msg.sat_in_outputs { + Some(context.get_script_key_on_satpoint(msg.new_satpoint.as_ref().unwrap(), network).map_err(|e| { + anyhow!("failed to get script key from state! error: {e}") + })?) + } else { + None + }, + op: msg.op.clone(), + }) } - Operation::Transfer(_) => process_transfer(context, msg), - }; - - let receipt = Receipt { - inscription_id: msg.inscription_id, - inscription_number: msg.inscription_number, - old_satpoint: msg.old_satpoint, - new_satpoint: msg.new_satpoint, - from: msg.from.clone(), - // redirect receiver to sender if transfer to conibase. - to: msg.to.clone().map_or(msg.from.clone(), |v| v), - op: msg.op.op_type(), - result: match event { - Ok(event) => Ok(event), - Err(Error::BRC20Error(e)) => Err(e), - Err(e) => return Err(anyhow!("BRC20 execute exception: {e}")), - }, - }; +} - log::debug!("BRC20 message receipt: {:?}", receipt); - Ok(receipt) +pub fn execute(context: &mut T, msg: &ExecutionMessage) -> Result { + log::debug!("BRC20 execute message: {:?}", msg); + let event = match &msg.op { + Operation::Deploy(deploy) => process_deploy(context, msg, deploy.clone()), + Operation::Mint(mint) => process_mint(context, msg, mint.clone()), + Operation::InscribeTransfer(transfer) => { + process_inscribe_transfer(context, msg, transfer.clone()) + } + Operation::Transfer(_) => process_transfer(context, msg), + }; + + let receipt = Receipt { + inscription_id: msg.inscription_id, + inscription_number: msg.inscription_number, + old_satpoint: msg.old_satpoint, + new_satpoint: msg.new_satpoint, + from: msg.from.clone(), + // redirect receiver to sender if transfer to conibase. + to: msg.to.clone().map_or(msg.from.clone(), |v| v), + op: msg.op.op_type(), + result: match event { + Ok(event) => Ok(event), + Err(Error::BRC20Error(e)) => Err(e), + Err(e) => return Err(anyhow!("BRC20 execute exception: {e}")), + }, + }; + + log::debug!("BRC20 message receipt: {:?}", receipt); + Ok(receipt) } -fn process_deploy( - context: &mut Context, - msg: &ExecutionMessage, - deploy: Deploy, +fn process_deploy( + context: &mut T, + msg: &ExecutionMessage, + deploy: Deploy, ) -> Result { - // ignore inscribe inscription to coinbase. - let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; - - let tick = deploy.tick.parse::()?; - - if let Some(stored_tick_info) = context - .get_token_info(&tick) - .map_err(|e| Error::LedgerError(e))? - { - return Err(Error::BRC20Error(BRC20Error::DuplicateTick( - stored_tick_info.tick.to_string(), - ))); - } - - let dec = Num::from_str(&deploy.decimals.map_or(MAX_DECIMAL_WIDTH.to_string(), |v| v))? - .checked_to_u8()?; - if dec > MAX_DECIMAL_WIDTH { - return Err(Error::BRC20Error(BRC20Error::DecimalsTooLarge(dec))); - } - let base = BIGDECIMAL_TEN.checked_powu(u64::from(dec))?; - - let supply = Num::from_str(&deploy.max_supply)?; - - if supply.sign() == Sign::NoSign - || supply > MAXIMUM_SUPPLY.to_owned() - || supply.scale() > i64::from(dec) - { - return Err(Error::BRC20Error(BRC20Error::InvalidSupply( - supply.to_string(), - ))); - } - - let limit = Num::from_str(&deploy.mint_limit.map_or(deploy.max_supply, |v| v))?; - - if limit.sign() == Sign::NoSign - || limit > MAXIMUM_SUPPLY.to_owned() - || limit.scale() > i64::from(dec) - { - return Err(Error::BRC20Error(BRC20Error::MintLimitOutOfRange( - tick.to_lowercase().to_string(), - limit.to_string(), - ))); - } - - let supply = supply.checked_mul(&base)?.checked_to_u128()?; - let limit = limit.checked_mul(&base)?.checked_to_u128()?; - - let new_info = TokenInfo { - inscription_id: msg.inscription_id, - inscription_number: msg.inscription_number, - tick: tick.clone(), - decimal: dec, - supply, - limit_per_mint: limit, - minted: 0u128, - deploy_by: to_script_key, - deployed_number: context.chain.blockheight, - latest_mint_number: context.chain.blockheight, - deployed_timestamp: context.chain.blocktime, - }; - context - .insert_token_info(&tick, &new_info) - .map_err(|e| Error::LedgerError(e))?; - - Ok(Event::Deploy(DeployEvent { - supply, - limit_per_mint: limit, - decimal: dec, - tick: new_info.tick, - })) + // ignore inscribe inscription to coinbase. + let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; + + let tick = deploy.tick.parse::()?; + + if let Some(stored_tick_info) = context + .get_token_info(&tick) + .map_err(|e| Error::LedgerError(anyhow!("failed")))? + { + return Err(Error::BRC20Error(BRC20Error::DuplicateTick( + stored_tick_info.tick.to_string(), + ))); + } + + let dec = Num::from_str(&deploy.decimals.map_or(MAX_DECIMAL_WIDTH.to_string(), |v| v))? + .checked_to_u8()?; + if dec > MAX_DECIMAL_WIDTH { + return Err(Error::BRC20Error(BRC20Error::DecimalsTooLarge(dec))); + } + let base = BIGDECIMAL_TEN.checked_powu(u64::from(dec))?; + + let supply = Num::from_str(&deploy.max_supply)?; + + if supply.sign() == Sign::NoSign + || supply > MAXIMUM_SUPPLY.to_owned() + || supply.scale() > i64::from(dec) + { + return Err(Error::BRC20Error(BRC20Error::InvalidSupply( + supply.to_string(), + ))); + } + + let limit = Num::from_str(&deploy.mint_limit.map_or(deploy.max_supply, |v| v))?; + + if limit.sign() == Sign::NoSign + || limit > MAXIMUM_SUPPLY.to_owned() + || limit.scale() > i64::from(dec) + { + return Err(Error::BRC20Error(BRC20Error::MintLimitOutOfRange( + tick.to_lowercase().to_string(), + limit.to_string(), + ))); + } + + let supply = supply.checked_mul(&base)?.checked_to_u128()?; + let limit = limit.checked_mul(&base)?.checked_to_u128()?; + + let new_info = TokenInfo { + inscription_id: msg.inscription_id, + inscription_number: msg.inscription_number, + tick: tick.clone(), + decimal: dec, + supply, + limit_per_mint: limit, + minted: 0u128, + deploy_by: to_script_key, + deployed_number: context.block_height(), + latest_mint_number: context.block_height(), + deployed_timestamp: context.block_time(), + }; + context + .insert_token_info(&tick, &new_info) + .map_err(|e| Error::LedgerError(anyhow!("failed2")))?; + + Ok(Event::Deploy(DeployEvent { + supply, + limit_per_mint: limit, + decimal: dec, + tick: new_info.tick, + })) } -fn process_mint(context: &mut Context, msg: &ExecutionMessage, mint: Mint) -> Result { - // ignore inscribe inscription to coinbase. - let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; - - let tick = mint.tick.parse::()?; - - let token_info = context - .get_token_info(&tick) - .map_err(|e| Error::LedgerError(e))? - .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; - - let base = BIGDECIMAL_TEN.checked_powu(u64::from(token_info.decimal))?; - - let mut amt = Num::from_str(&mint.amount)?; - - if amt.scale() > i64::from(token_info.decimal) { - return Err(Error::BRC20Error(BRC20Error::AmountOverflow( - amt.to_string(), - ))); - } - - amt = amt.checked_mul(&base)?; - if amt.sign() == Sign::NoSign { - return Err(Error::BRC20Error(BRC20Error::InvalidZeroAmount)); - } - if amt > Into::::into(token_info.limit_per_mint) { - return Err(Error::BRC20Error(BRC20Error::AmountExceedLimit( - amt.to_string(), - ))); - } - let minted = Into::::into(token_info.minted); - let supply = Into::::into(token_info.supply); - - if minted >= supply { - return Err(Error::BRC20Error(BRC20Error::TickMinted( - token_info.tick.to_string(), - ))); - } - - // cut off any excess. - let mut out_msg = None; - amt = if amt.checked_add(&minted)? > supply { - let new = supply.checked_sub(&minted)?; - out_msg = Some(format!( - "amt has been cut off to fit the supply! origin: {}, now: {}", - amt, new - )); - new - } else { - amt - }; - - // get or initialize user balance. - let mut balance = context - .get_balance(&to_script_key, &tick) - .map_err(|e| Error::LedgerError(e))? - .map_or(Balance::new(&tick), |v| v); - - // add amount to available balance. - balance.overall_balance = Into::::into(balance.overall_balance) - .checked_add(&amt)? - .checked_to_u128()?; - - // store to database. - context - .update_token_balance(&to_script_key, balance) - .map_err(|e| Error::LedgerError(e))?; - - // update token minted. - let minted = minted.checked_add(&amt)?.checked_to_u128()?; - context - .update_mint_token_info(&tick, minted, context.chain.blockheight) - .map_err(|e| Error::LedgerError(e))?; - - Ok(Event::Mint(MintEvent { - tick: token_info.tick, - amount: amt.checked_to_u128()?, - msg: out_msg, - })) +fn process_mint(context: &mut T, msg: &ExecutionMessage, mint: Mint) -> Result { + // ignore inscribe inscription to coinbase. + let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; + + let tick = mint.tick.parse::()?; + + let token_info = context + .get_token_info(&tick) + .map_err(|e| Error::LedgerError(anyhow!("failed3")))? + .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; + + let base = BIGDECIMAL_TEN.checked_powu(u64::from(token_info.decimal))?; + + let mut amt = Num::from_str(&mint.amount)?; + + if amt.scale() > i64::from(token_info.decimal) { + return Err(Error::BRC20Error(BRC20Error::AmountOverflow( + amt.to_string(), + ))); + } + + amt = amt.checked_mul(&base)?; + if amt.sign() == Sign::NoSign { + return Err(Error::BRC20Error(BRC20Error::InvalidZeroAmount)); + } + if amt > Into::::into(token_info.limit_per_mint) { + return Err(Error::BRC20Error(BRC20Error::AmountExceedLimit( + amt.to_string(), + ))); + } + let minted = Into::::into(token_info.minted); + let supply = Into::::into(token_info.supply); + + if minted >= supply { + return Err(Error::BRC20Error(BRC20Error::TickMinted( + token_info.tick.to_string(), + ))); + } + + // cut off any excess. + let mut out_msg = None; + amt = if amt.checked_add(&minted)? > supply { + let new = supply.checked_sub(&minted)?; + out_msg = Some(format!( + "amt has been cut off to fit the supply! origin: {}, now: {}", + amt, new + )); + new + } else { + amt + }; + + // get or initialize user balance. + let mut balance = context + .get_balance(&to_script_key, &tick) + .map_err(|e| Error::LedgerError(anyhow!("failed4")))? + .map_or(Balance::new(&tick), |v| v); + + // add amount to available balance. + balance.overall_balance = Into::::into(balance.overall_balance) + .checked_add(&amt)? + .checked_to_u128()?; + + // store to database. + context + .update_token_balance(&to_script_key, balance) + .map_err(|e| Error::LedgerError(anyhow!("failed5")))?; + + // update token minted. + let minted = minted.checked_add(&amt)?.checked_to_u128()?; + context + .update_mint_token_info(&tick, minted, context.block_height()) + .map_err(|e| Error::LedgerError(anyhow!("failed6")))?; + + Ok(Event::Mint(MintEvent { + tick: token_info.tick, + amount: amt.checked_to_u128()?, + msg: out_msg, + })) } -fn process_inscribe_transfer( - context: &mut Context, - msg: &ExecutionMessage, - transfer: Transfer, +fn process_inscribe_transfer( + context: &mut T, + msg: &ExecutionMessage, + transfer: Transfer, ) -> Result { - // ignore inscribe inscription to coinbase. - let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; - - let tick = transfer.tick.parse::()?; - - let token_info = context - .get_token_info(&tick) - .map_err(|e| Error::LedgerError(e))? - .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; - - let base = BIGDECIMAL_TEN.checked_powu(u64::from(token_info.decimal))?; - - let mut amt = Num::from_str(&transfer.amount)?; - - if amt.scale() > i64::from(token_info.decimal) { - return Err(Error::BRC20Error(BRC20Error::AmountOverflow( - amt.to_string(), - ))); - } - - amt = amt.checked_mul(&base)?; - if amt.sign() == Sign::NoSign || amt > Into::::into(token_info.supply) { - return Err(Error::BRC20Error(BRC20Error::AmountOverflow( - amt.to_string(), - ))); - } - - let mut balance = context - .get_balance(&to_script_key, &tick) - .map_err(|e| Error::LedgerError(e))? - .map_or(Balance::new(&tick), |v| v); - - let overall = Into::::into(balance.overall_balance); - let transferable = Into::::into(balance.transferable_balance); - let available = overall.checked_sub(&transferable)?; - if available < amt { - return Err(Error::BRC20Error(BRC20Error::InsufficientBalance( - available.to_string(), - amt.to_string(), - ))); - } - - balance.transferable_balance = transferable.checked_add(&amt)?.checked_to_u128()?; - - let amt = amt.checked_to_u128()?; - context - .update_token_balance(&to_script_key, balance) - .map_err(|e| Error::LedgerError(e))?; - - let inscription = TransferableLog { - inscription_id: msg.inscription_id, - inscription_number: msg.inscription_number, - amount: amt, - tick: token_info.tick.clone(), - owner: to_script_key, - }; - - context - .insert_transferable(&inscription.owner, &tick, &inscription) - .map_err(|e| Error::LedgerError(e))?; - - context - .insert_inscribe_transfer_inscription( - &msg.inscription_id, - TransferInfo { - tick: token_info.tick, - amt, - }, - ) - .map_err(|e| Error::LedgerError(e))?; - - Ok(Event::InscribeTransfer(InscripbeTransferEvent { - tick: inscription.tick, - amount: amt, - })) + // ignore inscribe inscription to coinbase. + let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; + + let tick = transfer.tick.parse::()?; + + let token_info = context + .get_token_info(&tick) + .map_err(|e| Error::LedgerError(anyhow!("failed7")))? + .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; + + let base = BIGDECIMAL_TEN.checked_powu(u64::from(token_info.decimal))?; + + let mut amt = Num::from_str(&transfer.amount)?; + + if amt.scale() > i64::from(token_info.decimal) { + return Err(Error::BRC20Error(BRC20Error::AmountOverflow( + amt.to_string(), + ))); + } + + amt = amt.checked_mul(&base)?; + if amt.sign() == Sign::NoSign || amt > Into::::into(token_info.supply) { + return Err(Error::BRC20Error(BRC20Error::AmountOverflow( + amt.to_string(), + ))); + } + + let mut balance = context + .get_balance(&to_script_key, &tick) + .map_err(|e| Error::LedgerError(anyhow!("failed8")))? + .map_or(Balance::new(&tick), |v| v); + + let overall = Into::::into(balance.overall_balance); + let transferable = Into::::into(balance.transferable_balance); + let available = overall.checked_sub(&transferable)?; + if available < amt { + return Err(Error::BRC20Error(BRC20Error::InsufficientBalance( + available.to_string(), + amt.to_string(), + ))); + } + + balance.transferable_balance = transferable.checked_add(&amt)?.checked_to_u128()?; + + let amt = amt.checked_to_u128()?; + context + .update_token_balance(&to_script_key, balance) + .map_err(|e| Error::LedgerError(anyhow!("failed9")))?; + + let inscription = TransferableLog { + inscription_id: msg.inscription_id, + inscription_number: msg.inscription_number, + amount: amt, + tick: token_info.tick.clone(), + owner: to_script_key, + }; + + context + .insert_transferable(&inscription.owner, &tick, &inscription) + .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + + context + .insert_inscribe_transfer_inscription( + &msg.inscription_id, + TransferInfo { + tick: token_info.tick, + amt, + }, + ) + .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + + Ok(Event::InscribeTransfer(InscripbeTransferEvent { + tick: inscription.tick, + amount: amt, + })) } -fn process_transfer(context: &mut Context, msg: &ExecutionMessage) -> Result { - let transferable = context - .get_transferable_by_id(&msg.from, &msg.inscription_id) - .map_err(|e| Error::LedgerError(e))? - .ok_or(BRC20Error::TransferableNotFound(msg.inscription_id))?; - - let amt = Into::::into(transferable.amount); - - if transferable.owner != msg.from { - return Err(Error::BRC20Error(BRC20Error::TransferableOwnerNotMatch( - msg.inscription_id, - ))); - } - - let tick = transferable.tick; - - let token_info = context - .get_token_info(&tick) - .map_err(|e| Error::LedgerError(e))? - .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; - - // update from key balance. - let mut from_balance = context - .get_balance(&msg.from, &tick) - .map_err(|e| Error::LedgerError(e))? - .map_or(Balance::new(&tick), |v| v); - - let from_overall = Into::::into(from_balance.overall_balance); - let from_transferable = Into::::into(from_balance.transferable_balance); - - let from_overall = from_overall.checked_sub(&amt)?.checked_to_u128()?; - let from_transferable = from_transferable.checked_sub(&amt)?.checked_to_u128()?; - - from_balance.overall_balance = from_overall; - from_balance.transferable_balance = from_transferable; - - context - .update_token_balance(&msg.from, from_balance) - .map_err(|e| Error::LedgerError(e))?; - - // redirect receiver to sender if transfer to conibase. - let mut out_msg = None; - - let to_script_key = if msg.to.clone().is_none() { - out_msg = - Some("redirect receiver to sender, reason: transfer inscription to coinbase".to_string()); - msg.from.clone() - } else { - msg.to.clone().unwrap() - }; - - // update to key balance. - let mut to_balance = context - .get_balance(&to_script_key, &tick) - .map_err(|e| Error::LedgerError(e))? - .map_or(Balance::new(&tick), |v| v); - - let to_overall = Into::::into(to_balance.overall_balance); - to_balance.overall_balance = to_overall.checked_add(&amt)?.checked_to_u128()?; - - context - .update_token_balance(&to_script_key, to_balance) - .map_err(|e| Error::LedgerError(e))?; - - context - .remove_transferable(&msg.from, &tick, &msg.inscription_id) - .map_err(|e| Error::LedgerError(e))?; - - context - .remove_inscribe_transfer_inscription(&msg.inscription_id) - .map_err(|e| Error::LedgerError(e))?; - - Ok(Event::Transfer(TransferEvent { - msg: out_msg, - tick: token_info.tick, - amount: amt.checked_to_u128()?, - })) +fn process_transfer(context: &mut T, msg: &ExecutionMessage) -> Result { + let transferable = context + .get_transferable_by_id(&msg.from, &msg.inscription_id) + .map_err(|e| Error::LedgerError(anyhow!("failed10")))? + .ok_or(BRC20Error::TransferableNotFound(msg.inscription_id))?; + + let amt = Into::::into(transferable.amount); + + if transferable.owner != msg.from { + return Err(Error::BRC20Error(BRC20Error::TransferableOwnerNotMatch( + msg.inscription_id, + ))); + } + + let tick = transferable.tick; + + let token_info = context + .get_token_info(&tick) + .map_err(|e| Error::LedgerError(anyhow!("failed10")))? + .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; + + // update from key balance. + let mut from_balance = context + .get_balance(&msg.from, &tick) + .map_err(|e| Error::LedgerError(anyhow!("failed10")))? + .map_or(Balance::new(&tick), |v| v); + + let from_overall = Into::::into(from_balance.overall_balance); + let from_transferable = Into::::into(from_balance.transferable_balance); + + let from_overall = from_overall.checked_sub(&amt)?.checked_to_u128()?; + let from_transferable = from_transferable.checked_sub(&amt)?.checked_to_u128()?; + + from_balance.overall_balance = from_overall; + from_balance.transferable_balance = from_transferable; + + context + .update_token_balance(&msg.from, from_balance) + .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + + // redirect receiver to sender if transfer to conibase. + let mut out_msg = None; + + let to_script_key = if msg.to.clone().is_none() { + out_msg = + Some("redirect receiver to sender, reason: transfer inscription to coinbase".to_string()); + msg.from.clone() + } else { + msg.to.clone().unwrap() + }; + + // update to key balance. + let mut to_balance = context + .get_balance(&to_script_key, &tick) + .map_err(|e| Error::LedgerError(anyhow!("failed10")))? + .map_or(Balance::new(&tick), |v| v); + + let to_overall = Into::::into(to_balance.overall_balance); + to_balance.overall_balance = to_overall.checked_add(&amt)?.checked_to_u128()?; + + context + .update_token_balance(&to_script_key, to_balance) + .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + + context + .remove_transferable(&msg.from, &tick, &msg.inscription_id) + .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + + context + .remove_inscribe_transfer_inscription(&msg.inscription_id) + .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + + Ok(Event::Transfer(TransferEvent { + msg: out_msg, + tick: token_info.tick, + amount: amt.checked_to_u128()?, + })) } diff --git a/src/okx/protocol/brc20/msg_resolver.rs b/src/okx/protocol/brc20/msg_resolver.rs index affe6bc258..4c9aa20a94 100644 --- a/src/okx/protocol/brc20/msg_resolver.rs +++ b/src/okx/protocol/brc20/msg_resolver.rs @@ -11,6 +11,8 @@ use crate::{ }; use anyhow::anyhow; use redb::ReadableTable; +use crate::okx::datastore::brc20::Brc20ReaderWriter; +use crate::okx::protocol::ContextTrait; impl Message { pub(crate) fn resolve( @@ -19,7 +21,7 @@ impl Message { op: &InscriptionOp, ) -> Result> where - T: ReadableTable, + T: Brc20ReaderWriter, { log::debug!("BRC20 resolving the message from {:?}", op); let sat_in_outputs = op @@ -47,7 +49,7 @@ impl Message { } // Transfered inscription operation. // Attempt to retrieve the `InscribeTransfer` Inscription information from the data store of BRC20S. - Action::Transfer => match get_inscribe_transfer_inscription(table, &op.inscription_id) { + Action::Transfer => match table.get_inscribe_transfer_inscription(&op.inscription_id) { // Ignore non-first transfer operations. Ok(Some(transfer_info)) if op.inscription_id.txid == op.old_satpoint.outpoint.txid => { Operation::Transfer(Transfer { @@ -156,150 +158,150 @@ mod tests { } } - #[test] - fn test_invalid_protocol() { - let db_file = NamedTempFile::new().unwrap(); - let db = Database::create(db_file.path()).unwrap(); - let wtx = db.begin_write().unwrap(); - let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); + // #[test] + // fn test_invalid_protocol() { + // let db_file = NamedTempFile::new().unwrap(); + // let db = Database::create(db_file.path()).unwrap(); + // let wtx = db.begin_write().unwrap(); + // let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); + // + // let (inscriptions, op) = create_inscribe_operation( + // r#"{ "p": "brc-20s","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, + // ); + // assert_matches!(Message::resolve(&table, &inscriptions, &op), Ok(None)); + // } - let (inscriptions, op) = create_inscribe_operation( - r#"{ "p": "brc-20s","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, - ); - assert_matches!(Message::resolve(&table, &inscriptions, &op), Ok(None)); - } - - #[test] - fn test_cursed_or_unbound_inscription() { - let db_file = NamedTempFile::new().unwrap(); - let db = Database::create(db_file.path()).unwrap(); - let wtx = db.begin_write().unwrap(); - let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); - - let (inscriptions, op) = create_inscribe_operation( - r#"{ "p": "brc-20","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, - ); - let op = InscriptionOp { - action: Action::New { - cursed: true, - unbound: false, - inscription: inscriptions.get(0).unwrap().clone(), - vindicated: false, - }, - ..op - }; - assert_matches!(Message::resolve(&table, &inscriptions, &op), Ok(None)); - - let op2 = InscriptionOp { - action: Action::New { - cursed: false, - unbound: true, - inscription: inscriptions.get(0).unwrap().clone(), - vindicated: false, - }, - ..op - }; - assert_matches!(Message::resolve(&table, &inscriptions, &op2), Ok(None)); - let op3 = InscriptionOp { - action: Action::New { - cursed: true, - unbound: true, - inscription: inscriptions.get(0).unwrap().clone(), - vindicated: false, - }, - ..op - }; - assert_matches!(Message::resolve(&table, &inscriptions, &op3), Ok(None)); - } - - #[test] - fn test_valid_inscribe_operation() { - let db_file = NamedTempFile::new().unwrap(); - let db = Database::create(db_file.path()).unwrap(); - let wtx = db.begin_write().unwrap(); - let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); - - let (inscriptions, op) = create_inscribe_operation( - r#"{ "p": "brc-20","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, - ); - let _result_msg = Message { - txid: op.txid, - sequence_number: op.sequence_number, - inscription_id: op.inscription_id, - old_satpoint: op.old_satpoint, - new_satpoint: op.new_satpoint, - op: Operation::Deploy(Deploy { - tick: "ordi".to_string(), - max_supply: "1000".to_string(), - mint_limit: Some("10".to_string()), - decimals: None, - }), - sat_in_outputs: true, - }; - assert_matches!( - Message::resolve(&table, &inscriptions, &op), - Ok(Some(_result_msg)) - ); - } - - #[test] - fn test_invalid_transfer() { - let db_file = NamedTempFile::new().unwrap(); - let db = Database::create(db_file.path()).unwrap(); - let wtx = db.begin_write().unwrap(); - let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); - - // inscribe transfer not found - let op = create_transfer_operation(); - assert_matches!(Message::resolve(&table, &[], &op), Ok(None)); - - // non-first transfer operations. - let op1 = InscriptionOp { - old_satpoint: SatPoint { - outpoint: OutPoint { - txid: Txid::from_str("3111111111111111111111111111111111111111111111111111111111111111") - .unwrap(), - vout: 0, - }, - offset: 0, - }, - ..op - }; - assert_matches!(Message::resolve(&table, &[], &op1), Ok(None)); - } - - #[test] - fn test_valid_transfer() { - let db_file = NamedTempFile::new().unwrap(); - let db = Database::create(db_file.path()).unwrap(); - let wtx = db.begin_write().unwrap(); - let mut table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); + // #[test] + // fn test_cursed_or_unbound_inscription() { + // let db_file = NamedTempFile::new().unwrap(); + // let db = Database::create(db_file.path()).unwrap(); + // let wtx = db.begin_write().unwrap(); + // let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); + // + // let (inscriptions, op) = create_inscribe_operation( + // r#"{ "p": "brc-20","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, + // ); + // let op = InscriptionOp { + // action: Action::New { + // cursed: true, + // unbound: false, + // inscription: inscriptions.get(0).unwrap().clone(), + // vindicated: false, + // }, + // ..op + // }; + // assert_matches!(Message::resolve(&table, &inscriptions, &op), Ok(None)); + // + // let op2 = InscriptionOp { + // action: Action::New { + // cursed: false, + // unbound: true, + // inscription: inscriptions.get(0).unwrap().clone(), + // vindicated: false, + // }, + // ..op + // }; + // assert_matches!(Message::resolve(&table, &inscriptions, &op2), Ok(None)); + // let op3 = InscriptionOp { + // action: Action::New { + // cursed: true, + // unbound: true, + // inscription: inscriptions.get(0).unwrap().clone(), + // vindicated: false, + // }, + // ..op + // }; + // assert_matches!(Message::resolve(&table, &inscriptions, &op3), Ok(None)); + // } - // inscribe transfer not found - let op = create_transfer_operation(); + // #[test] + // fn test_valid_inscribe_operation() { + // let db_file = NamedTempFile::new().unwrap(); + // let db = Database::create(db_file.path()).unwrap(); + // let wtx = db.begin_write().unwrap(); + // let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); + // + // let (inscriptions, op) = create_inscribe_operation( + // r#"{ "p": "brc-20","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, + // ); + // let _result_msg = Message { + // txid: op.txid, + // sequence_number: op.sequence_number, + // inscription_id: op.inscription_id, + // old_satpoint: op.old_satpoint, + // new_satpoint: op.new_satpoint, + // op: Operation::Deploy(Deploy { + // tick: "ordi".to_string(), + // max_supply: "1000".to_string(), + // mint_limit: Some("10".to_string()), + // decimals: None, + // }), + // sat_in_outputs: true, + // }; + // assert_matches!( + // Message::resolve(&table, &inscriptions, &op), + // Ok(Some(_result_msg)) + // ); + // } - insert_inscribe_transfer_inscription( - &mut table, - &op.inscription_id, - TransferInfo { - tick: Tick::from_str("ordi").unwrap(), - amt: 100, - }, - ) - .unwrap(); - let _msg = Message { - txid: op.txid, - sequence_number: op.sequence_number, - inscription_id: op.inscription_id, - old_satpoint: op.old_satpoint, - new_satpoint: op.new_satpoint, - op: Operation::Transfer(Transfer { - tick: "ordi".to_string(), - amount: "100".to_string(), - }), - sat_in_outputs: true, - }; + // #[test] + // fn test_invalid_transfer() { + // let db_file = NamedTempFile::new().unwrap(); + // let db = Database::create(db_file.path()).unwrap(); + // let wtx = db.begin_write().unwrap(); + // let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); + // + // // inscribe transfer not found + // let op = create_transfer_operation(); + // assert_matches!(Message::resolve(&table, &[], &op), Ok(None)); + // + // // non-first transfer operations. + // let op1 = InscriptionOp { + // old_satpoint: SatPoint { + // outpoint: OutPoint { + // txid: Txid::from_str("3111111111111111111111111111111111111111111111111111111111111111") + // .unwrap(), + // vout: 0, + // }, + // offset: 0, + // }, + // ..op + // }; + // assert_matches!(Message::resolve(&table, &[], &op1), Ok(None)); + // } - assert_matches!(Message::resolve(&table, &[], &op), Ok(Some(_msg))); - } + // #[test] + // fn test_valid_transfer() { + // let db_file = NamedTempFile::new().unwrap(); + // let db = Database::create(db_file.path()).unwrap(); + // let wtx = db.begin_write().unwrap(); + // let mut table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); + // + // // inscribe transfer not found + // let op = create_transfer_operation(); + // + // insert_inscribe_transfer_inscription( + // &mut table, + // &op.inscription_id, + // TransferInfo { + // tick: Tick::from_str("ordi").unwrap(), + // amt: 100, + // }, + // ) + // .unwrap(); + // let _msg = Message { + // txid: op.txid, + // sequence_number: op.sequence_number, + // inscription_id: op.inscription_id, + // old_satpoint: op.old_satpoint, + // new_satpoint: op.new_satpoint, + // op: Operation::Transfer(Transfer { + // tick: "ordi".to_string(), + // amount: "100".to_string(), + // }), + // sat_in_outputs: true, + // }; + // + // assert_matches!(Message::resolve(&table, &[], &op), Ok(Some(_msg))); + // } } diff --git a/src/okx/protocol/context.rs b/src/okx/protocol/context.rs index 1d88af5478..f21654d94b 100644 --- a/src/okx/protocol/context.rs +++ b/src/okx/protocol/context.rs @@ -1,27 +1,27 @@ use crate::index::{InscriptionEntryValue, InscriptionIdValue, OutPointValue, TxidValue}; use crate::inscriptions::InscriptionId; use crate::okx::datastore::brc20::redb::table::{ - get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, - get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick, - insert_inscribe_transfer_inscription, insert_token_info, insert_transferable, - remove_inscribe_transfer_inscription, remove_transferable, save_transaction_receipts, - update_mint_token_info, update_token_balance, + get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, + get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick, + insert_inscribe_transfer_inscription, insert_token_info, insert_transferable, + remove_inscribe_transfer_inscription, remove_transferable, save_transaction_receipts, + update_mint_token_info, update_token_balance, }; use crate::okx::datastore::brc20::{ - Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferInfo, TransferableLog, + Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferInfo, TransferableLog, }; use crate::okx::datastore::ord::collections::CollectionKind; use crate::okx::datastore::ord::redb::table::{ - get_collection_inscription_id, get_collections_of_inscription, get_transaction_operations, - get_txout_by_outpoint, set_inscription_attributes, set_inscription_by_collection_key, + get_collection_inscription_id, get_collections_of_inscription, get_transaction_operations, + get_txout_by_outpoint, set_inscription_attributes, set_inscription_by_collection_key, }; use crate::okx::datastore::ord::redb::table::{ - get_inscription_number_by_sequence_number, save_transaction_operations, + get_inscription_number_by_sequence_number, save_transaction_operations, }; use crate::okx::datastore::ord::{InscriptionOp, OrdReader, OrdReaderWriter}; use crate::okx::datastore::ScriptKey; use crate::okx::lru::SimpleLru; -use crate::okx::protocol::BlockContext; +use crate::okx::protocol::{BlockContext, ContextTrait}; use crate::SatPoint; use anyhow::anyhow; use bitcoin::{Network, OutPoint, TxOut, Txid}; @@ -29,245 +29,260 @@ use redb::Table; #[allow(non_snake_case)] pub struct Context<'a, 'db, 'txn> { - pub(crate) chain: BlockContext, - pub(crate) tx_out_cache: &'a mut SimpleLru, - pub(crate) hit: u64, - pub(crate) miss: u64, - - // ord tables - pub(crate) ORD_TX_TO_OPERATIONS: &'a mut Table<'db, 'txn, &'static TxidValue, &'static [u8]>, - pub(crate) COLLECTIONS_KEY_TO_INSCRIPTION_ID: + pub(crate) chain: BlockContext, + pub(crate) tx_out_cache: &'a mut SimpleLru, + pub(crate) hit: u64, + pub(crate) miss: u64, + + // ord tables + pub(crate) ORD_TX_TO_OPERATIONS: &'a mut Table<'db, 'txn, &'static TxidValue, &'static [u8]>, + pub(crate) COLLECTIONS_KEY_TO_INSCRIPTION_ID: &'a mut Table<'db, 'txn, &'static str, InscriptionIdValue>, - pub(crate) COLLECTIONS_INSCRIPTION_ID_TO_KINDS: + pub(crate) COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &'a mut Table<'db, 'txn, InscriptionIdValue, &'static [u8]>, - pub(crate) SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: + pub(crate) SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &'a mut Table<'db, 'txn, u32, InscriptionEntryValue>, - pub(crate) OUTPOINT_TO_ENTRY: &'a mut Table<'db, 'txn, &'static OutPointValue, &'static [u8]>, - - // BRC20 tables - pub(crate) BRC20_BALANCES: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, - pub(crate) BRC20_TOKEN: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, - pub(crate) BRC20_EVENTS: &'a mut Table<'db, 'txn, &'static TxidValue, &'static [u8]>, - pub(crate) BRC20_TRANSFERABLELOG: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, - pub(crate) BRC20_INSCRIBE_TRANSFER: &'a mut Table<'db, 'txn, InscriptionIdValue, &'static [u8]>, + pub(crate) OUTPOINT_TO_ENTRY: &'a mut Table<'db, 'txn, &'static OutPointValue, &'static [u8]>, + + // BRC20 tables + pub(crate) BRC20_BALANCES: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, + pub(crate) BRC20_TOKEN: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, + pub(crate) BRC20_EVENTS: &'a mut Table<'db, 'txn, &'static TxidValue, &'static [u8]>, + pub(crate) BRC20_TRANSFERABLELOG: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, + pub(crate) BRC20_INSCRIBE_TRANSFER: &'a mut Table<'db, 'txn, InscriptionIdValue, &'static [u8]>, } impl<'a, 'db, 'txn> OrdReader for Context<'a, 'db, 'txn> { - type Error = anyhow::Error; - - fn get_inscription_number_by_sequence_number( - &self, - sequence_number: u32, - ) -> crate::Result { - get_inscription_number_by_sequence_number( - self.SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, - sequence_number, - ) - .map_err(|e| anyhow!("failed to get inscription number from state! error: {e}"))? - .ok_or(anyhow!( + type Error = anyhow::Error; + + fn get_inscription_number_by_sequence_number( + &self, + sequence_number: u32, + ) -> crate::Result { + get_inscription_number_by_sequence_number( + self.SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, + sequence_number, + ) + .map_err(|e| anyhow!("failed to get inscription number from state! error: {e}"))? + .ok_or(anyhow!( "failed to get inscription number! error: sequence number {} not found", sequence_number )) - } - - fn get_script_key_on_satpoint( - &mut self, - satpoint: &SatPoint, - network: Network, - ) -> crate::Result { - if let Some(tx_out) = self.tx_out_cache.get(&satpoint.outpoint) { - self.hit += 1; - Ok(ScriptKey::from_script(&tx_out.script_pubkey, network)) - } else if let Some(tx_out) = get_txout_by_outpoint(self.OUTPOINT_TO_ENTRY, &satpoint.outpoint)? - { - self.miss += 1; - Ok(ScriptKey::from_script(&tx_out.script_pubkey, network)) - } else { - Err(anyhow!( + } + + fn get_script_key_on_satpoint( + &mut self, + satpoint: &SatPoint, + network: Network, + ) -> crate::Result { + if let Some(tx_out) = self.tx_out_cache.get(&satpoint.outpoint) { + self.hit += 1; + Ok(ScriptKey::from_script(&tx_out.script_pubkey, network)) + } else if let Some(tx_out) = get_txout_by_outpoint(self.OUTPOINT_TO_ENTRY, &satpoint.outpoint)? + { + self.miss += 1; + Ok(ScriptKey::from_script(&tx_out.script_pubkey, network)) + } else { + Err(anyhow!( "failed to get tx out! error: outpoint {} not found", &satpoint.outpoint )) + } + } + + fn get_transaction_operations( + &self, + txid: &Txid, + ) -> crate::Result, Self::Error> { + get_transaction_operations(self.ORD_TX_TO_OPERATIONS, txid) + } + + fn get_collections_of_inscription( + &self, + inscription_id: &InscriptionId, + ) -> crate::Result>, Self::Error> { + get_collections_of_inscription(self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS, inscription_id) + } + + fn get_collection_inscription_id( + &self, + collection_key: &str, + ) -> crate::Result, Self::Error> { + get_collection_inscription_id(self.COLLECTIONS_KEY_TO_INSCRIPTION_ID, collection_key) } - } - - fn get_transaction_operations( - &self, - txid: &Txid, - ) -> crate::Result, Self::Error> { - get_transaction_operations(self.ORD_TX_TO_OPERATIONS, txid) - } - - fn get_collections_of_inscription( - &self, - inscription_id: &InscriptionId, - ) -> crate::Result>, Self::Error> { - get_collections_of_inscription(self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS, inscription_id) - } - - fn get_collection_inscription_id( - &self, - collection_key: &str, - ) -> crate::Result, Self::Error> { - get_collection_inscription_id(self.COLLECTIONS_KEY_TO_INSCRIPTION_ID, collection_key) - } } impl<'a, 'db, 'txn> OrdReaderWriter for Context<'a, 'db, 'txn> { - fn save_transaction_operations( - &mut self, - txid: &Txid, - operations: &[InscriptionOp], - ) -> crate::Result<(), Self::Error> { - save_transaction_operations(self.ORD_TX_TO_OPERATIONS, txid, operations) - } - - fn set_inscription_by_collection_key( - &mut self, - key: &str, - inscription_id: &InscriptionId, - ) -> crate::Result<(), Self::Error> { - set_inscription_by_collection_key(self.COLLECTIONS_KEY_TO_INSCRIPTION_ID, key, inscription_id) - } - - fn set_inscription_attributes( - &mut self, - inscription_id: &InscriptionId, - kind: &[CollectionKind], - ) -> crate::Result<(), Self::Error> { - set_inscription_attributes( - self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS, - inscription_id, - kind, - ) - } + fn save_transaction_operations( + &mut self, + txid: &Txid, + operations: &[InscriptionOp], + ) -> crate::Result<(), Self::Error> { + save_transaction_operations(self.ORD_TX_TO_OPERATIONS, txid, operations) + } + + fn set_inscription_by_collection_key( + &mut self, + key: &str, + inscription_id: &InscriptionId, + ) -> crate::Result<(), Self::Error> { + set_inscription_by_collection_key(self.COLLECTIONS_KEY_TO_INSCRIPTION_ID, key, inscription_id) + } + + fn set_inscription_attributes( + &mut self, + inscription_id: &InscriptionId, + kind: &[CollectionKind], + ) -> crate::Result<(), Self::Error> { + set_inscription_attributes( + self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS, + inscription_id, + kind, + ) + } } impl<'a, 'db, 'txn> Brc20Reader for Context<'a, 'db, 'txn> { - type Error = anyhow::Error; - - fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { - get_balances(self.BRC20_BALANCES, script_key) - } - - fn get_balance( - &self, - script_key: &ScriptKey, - tick: &Tick, - ) -> crate::Result, Self::Error> { - get_balance(self.BRC20_BALANCES, script_key, tick) - } - - fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { - get_token_info(self.BRC20_TOKEN, tick) - } - - fn get_tokens_info(&self) -> crate::Result, Self::Error> { - get_tokens_info(self.BRC20_TOKEN) - } - - fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { - get_transaction_receipts(self.BRC20_EVENTS, txid) - } - - fn get_transferable( - &self, - script: &ScriptKey, - ) -> crate::Result, Self::Error> { - get_transferable(self.BRC20_TRANSFERABLELOG, script) - } - - fn get_transferable_by_tick( - &self, - script: &ScriptKey, - tick: &Tick, - ) -> crate::Result, Self::Error> { - get_transferable_by_tick(self.BRC20_TRANSFERABLELOG, script, tick) - } - - fn get_transferable_by_id( - &self, - script: &ScriptKey, - inscription_id: &InscriptionId, - ) -> crate::Result, Self::Error> { - get_transferable_by_id(self.BRC20_TRANSFERABLELOG, script, inscription_id) - } - - fn get_inscribe_transfer_inscription( - &self, - inscription_id: &InscriptionId, - ) -> crate::Result, Self::Error> { - get_inscribe_transfer_inscription(self.BRC20_INSCRIBE_TRANSFER, inscription_id) - } + type Error = anyhow::Error; + + fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { + get_balances(self.BRC20_BALANCES, script_key) + } + + fn get_balance( + &self, + script_key: &ScriptKey, + tick: &Tick, + ) -> crate::Result, Self::Error> { + get_balance(self.BRC20_BALANCES, script_key, tick) + } + + fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { + get_token_info(self.BRC20_TOKEN, tick) + } + + fn get_tokens_info(&self) -> crate::Result, Self::Error> { + get_tokens_info(self.BRC20_TOKEN) + } + + fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { + get_transaction_receipts(self.BRC20_EVENTS, txid) + } + + fn get_transferable( + &self, + script: &ScriptKey, + ) -> crate::Result, Self::Error> { + get_transferable(self.BRC20_TRANSFERABLELOG, script) + } + + fn get_transferable_by_tick( + &self, + script: &ScriptKey, + tick: &Tick, + ) -> crate::Result, Self::Error> { + get_transferable_by_tick(self.BRC20_TRANSFERABLELOG, script, tick) + } + + fn get_transferable_by_id( + &self, + script: &ScriptKey, + inscription_id: &InscriptionId, + ) -> crate::Result, Self::Error> { + get_transferable_by_id(self.BRC20_TRANSFERABLELOG, script, inscription_id) + } + + fn get_inscribe_transfer_inscription( + &self, + inscription_id: &InscriptionId, + ) -> crate::Result, Self::Error> { + get_inscribe_transfer_inscription(self.BRC20_INSCRIBE_TRANSFER, inscription_id) + } } impl<'a, 'db, 'txn> Brc20ReaderWriter for Context<'a, 'db, 'txn> { - fn update_token_balance( - &mut self, - script_key: &ScriptKey, - new_balance: Balance, - ) -> crate::Result<(), Self::Error> { - update_token_balance(self.BRC20_BALANCES, script_key, new_balance) - } - - fn insert_token_info( - &mut self, - tick: &Tick, - new_info: &TokenInfo, - ) -> crate::Result<(), Self::Error> { - insert_token_info(self.BRC20_TOKEN, tick, new_info) - } - - fn update_mint_token_info( - &mut self, - tick: &Tick, - minted_amt: u128, - minted_block_number: u32, - ) -> crate::Result<(), Self::Error> { - update_mint_token_info(self.BRC20_TOKEN, tick, minted_amt, minted_block_number) - } - - fn save_transaction_receipts( - &mut self, - txid: &Txid, - receipt: &[Receipt], - ) -> crate::Result<(), Self::Error> { - save_transaction_receipts(self.BRC20_EVENTS, txid, receipt) - } - - fn insert_transferable( - &mut self, - script: &ScriptKey, - tick: &Tick, - inscription: &TransferableLog, - ) -> crate::Result<(), Self::Error> { - insert_transferable(self.BRC20_TRANSFERABLELOG, script, tick, inscription) - } - - fn remove_transferable( - &mut self, - script: &ScriptKey, - tick: &Tick, - inscription_id: &InscriptionId, - ) -> crate::Result<(), Self::Error> { - remove_transferable(self.BRC20_TRANSFERABLELOG, script, tick, inscription_id) - } - - fn insert_inscribe_transfer_inscription( - &mut self, - inscription_id: &InscriptionId, - transfer_info: TransferInfo, - ) -> crate::Result<(), Self::Error> { - insert_inscribe_transfer_inscription( - self.BRC20_INSCRIBE_TRANSFER, - inscription_id, - transfer_info, - ) - } - - fn remove_inscribe_transfer_inscription( - &mut self, - inscription_id: &InscriptionId, - ) -> crate::Result<(), Self::Error> { - remove_inscribe_transfer_inscription(self.BRC20_INSCRIBE_TRANSFER, inscription_id) - } + fn update_token_balance( + &mut self, + script_key: &ScriptKey, + new_balance: Balance, + ) -> crate::Result<(), Self::Error> { + update_token_balance(self.BRC20_BALANCES, script_key, new_balance) + } + + fn insert_token_info( + &mut self, + tick: &Tick, + new_info: &TokenInfo, + ) -> crate::Result<(), Self::Error> { + insert_token_info(self.BRC20_TOKEN, tick, new_info) + } + + fn update_mint_token_info( + &mut self, + tick: &Tick, + minted_amt: u128, + minted_block_number: u32, + ) -> crate::Result<(), Self::Error> { + update_mint_token_info(self.BRC20_TOKEN, tick, minted_amt, minted_block_number) + } + + fn save_transaction_receipts( + &mut self, + txid: &Txid, + receipt: &[Receipt], + ) -> crate::Result<(), Self::Error> { + save_transaction_receipts(self.BRC20_EVENTS, txid, receipt) + } + + fn insert_transferable( + &mut self, + script: &ScriptKey, + tick: &Tick, + inscription: &TransferableLog, + ) -> crate::Result<(), Self::Error> { + insert_transferable(self.BRC20_TRANSFERABLELOG, script, tick, inscription) + } + + fn remove_transferable( + &mut self, + script: &ScriptKey, + tick: &Tick, + inscription_id: &InscriptionId, + ) -> crate::Result<(), Self::Error> { + remove_transferable(self.BRC20_TRANSFERABLELOG, script, tick, inscription_id) + } + + fn insert_inscribe_transfer_inscription( + &mut self, + inscription_id: &InscriptionId, + transfer_info: TransferInfo, + ) -> crate::Result<(), Self::Error> { + insert_inscribe_transfer_inscription( + self.BRC20_INSCRIBE_TRANSFER, + inscription_id, + transfer_info, + ) + } + + fn remove_inscribe_transfer_inscription( + &mut self, + inscription_id: &InscriptionId, + ) -> crate::Result<(), Self::Error> { + remove_inscribe_transfer_inscription(self.BRC20_INSCRIBE_TRANSFER, inscription_id) + } } + + +impl<'a, 'db, 'txn> ContextTrait for Context<'a, 'db, 'txn> { + fn block_height(&self) -> u32 { + self.chain.blockheight + } + + fn network(&self) -> Network { + self.chain.network.clone() + } + + fn block_time(&self) -> u32 { + self.chain.blocktime + } +} \ No newline at end of file diff --git a/src/okx/protocol/execute_manager.rs b/src/okx/protocol/execute_manager.rs index 70d708e343..e4d7a1a50e 100644 --- a/src/okx/protocol/execute_manager.rs +++ b/src/okx/protocol/execute_manager.rs @@ -14,14 +14,14 @@ impl CallManager { Self {} } - pub fn execute_message(&self, context: &mut Context, txid: &Txid, msgs: &[Message]) -> Result { + pub fn execute_message(&self, context: &mut T, txid: &Txid, msgs: &[Message]) -> Result { let mut receipts = vec![]; // execute message for msg in msgs { match msg { Message::BRC20(brc_msg) => { let msg = - brc20_proto::ExecutionMessage::from_message(context, brc_msg, context.chain.network)?; + brc20_proto::ExecutionMessage::from_message(context, brc_msg, context.network())?; let receipt = brc20_proto::execute(context, &msg)?; receipts.push(receipt); } diff --git a/src/okx/protocol/mod.rs b/src/okx/protocol/mod.rs index 86e1b6b36b..b8998f0670 100644 --- a/src/okx/protocol/mod.rs +++ b/src/okx/protocol/mod.rs @@ -8,39 +8,50 @@ pub(crate) mod resolve_manager; mod simulate; pub mod trace; +use redb::ReadableTable; pub use self::protocol_manager::ProtocolManager; use { - self::{execute_manager::CallManager, message::Message, resolve_manager::MsgResolveManager}, - crate::Options, - bitcoin::Network, + self::{execute_manager::CallManager, message::Message, resolve_manager::MsgResolveManager}, + crate::Options, + bitcoin::Network, }; +use crate::okx::datastore::brc20::{Brc20ReaderWriter, TransferInfo}; +use crate::okx::datastore::ord::OrdReaderWriter; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct BlockContext { - pub network: Network, - pub blockheight: u32, - pub blocktime: u32, + pub network: Network, + pub blockheight: u32, + pub blocktime: u32, } + #[derive(Debug, Clone, Copy)] pub struct ProtocolConfig { - first_inscription_height: u32, - first_brc20_height: Option, - enable_ord_receipts: bool, - enable_index_bitmap: bool, + first_inscription_height: u32, + first_brc20_height: Option, + enable_ord_receipts: bool, + enable_index_bitmap: bool, } impl ProtocolConfig { - pub(crate) fn new_with_options(options: &Options) -> Self { - Self { - first_inscription_height: options.first_inscription_height(), - first_brc20_height: if options.enable_index_brc20 { - Some(options.first_brc20_height()) - } else { - None - }, - enable_ord_receipts: options.enable_save_ord_receipts, - enable_index_bitmap: options.enable_index_bitmap, + pub(crate) fn new_with_options(options: &Options) -> Self { + Self { + first_inscription_height: options.first_inscription_height(), + first_brc20_height: if options.enable_index_brc20 { + Some(options.first_brc20_height()) + } else { + None + }, + enable_ord_receipts: options.enable_save_ord_receipts, + enable_index_bitmap: options.enable_index_bitmap, + } } - } } + + +pub trait ContextTrait: Brc20ReaderWriter + OrdReaderWriter { + fn block_height(&self) -> u32; + fn network(&self) -> Network; + fn block_time(&self) -> u32; +} \ No newline at end of file diff --git a/src/okx/protocol/ord/bitmap.rs b/src/okx/protocol/ord/bitmap.rs index 57a4875f90..618323f870 100644 --- a/src/okx/protocol/ord/bitmap.rs +++ b/src/okx/protocol/ord/bitmap.rs @@ -1,96 +1,101 @@ use crate::okx::datastore::ord::{OrdReader, OrdReaderWriter}; use crate::okx::protocol::context::Context; use { - crate::{ - okx::datastore::ord::{ - bitmap::District, - collections::CollectionKind, - operation::{Action, InscriptionOp}, + crate::{ + okx::datastore::ord::{ + bitmap::District, + collections::CollectionKind, + operation::{Action, InscriptionOp}, + }, + Inscription, InscriptionId, Result, }, - Inscription, InscriptionId, Result, - }, - anyhow::anyhow, - bitcoin::Txid, - std::collections::HashMap, + anyhow::anyhow, + bitcoin::Txid, + std::collections::HashMap, }; +use crate::okx::protocol::ContextTrait; -pub fn index_bitmap( - context: &mut Context, - operations: &HashMap>, +pub fn index_bitmap( + context: &mut T, + operations: &HashMap>, ) -> Result { - let mut count = 0; + let mut count = 0; - // ignore transferred or cursed inscriptions. - let mut positive_inscriptions = operations - .values() - .flatten() - .cloned() - .filter(|op| { - !op.inscription_number.unwrap().is_negative() && matches!(op.action, Action::New { .. }) - }) - .collect::>(); + // ignore transferred or cursed inscriptions. + let mut positive_inscriptions = operations + .values() + .flatten() + .cloned() + .filter(|op| { + !op.inscription_number.unwrap().is_negative() && matches!(op.action, Action::New { .. }) + }) + .collect::>(); - // sort by inscription number. - positive_inscriptions.sort_by_key(|op| op.inscription_number.unwrap()); + // sort by inscription number. + positive_inscriptions.sort_by_key(|op| op.inscription_number.unwrap()); - for op in positive_inscriptions.into_iter() { - match op.action { - Action::New { - cursed: _, - unbound: _, - vindicated: _, - inscription, - } => { - if let Some((inscription_id, district)) = - index_district(context, inscription, op.inscription_id)? - { - let key = district.to_collection_key(); - context.set_inscription_by_collection_key(&key, &inscription_id)?; - context.set_inscription_attributes(&inscription_id, &[CollectionKind::BitMap])?; + for op in positive_inscriptions.into_iter() { + match op.action { + Action::New { + cursed: _, + unbound: _, + vindicated: _, + inscription, + } => { + if let Some((inscription_id, district)) = + index_district(context, inscription, op.inscription_id)? + { + let key = district.to_collection_key(); + context.set_inscription_by_collection_key(&key, &inscription_id).map_err(|e|{ + anyhow!("failed to set inscription by collection key! key: {key} inscription_id: {inscription_id} error: {e}") + })?; + context.set_inscription_attributes(&inscription_id, &[CollectionKind::BitMap]).map_err(|e|{ + anyhow!("failed to set inscription attributes! inscription_id: {inscription_id} error: {e}") + })?; - count += 1; + count += 1; + } + } + _ => unreachable!(), } - } - _ => unreachable!(), } - } - Ok(count) + Ok(count) } -fn index_district( - context: &mut Context, - inscription: Inscription, - inscription_id: InscriptionId, +fn index_district( + context: &mut T, + inscription: Inscription, + inscription_id: InscriptionId, ) -> Result> { - if let Some(content) = inscription.body() { - if let Ok(district) = District::parse(content) { - if district.number > context.chain.blockheight { - return Ok(None); - } - let collection_key = district.to_collection_key(); + if let Some(content) = inscription.body() { + if let Ok(district) = District::parse(content) { + if district.number > context.block_height() { + return Ok(None); + } + let collection_key = district.to_collection_key(); - if context - .get_collection_inscription_id(&collection_key) - .map_err(|e| { - anyhow!("failed to get collection inscription! key: {collection_key} error: {e}") - })? - .is_none() - { - log::info!( + if context + .get_collection_inscription_id(&collection_key) + .map_err(|e| { + anyhow!("failed to get collection inscription! key: {collection_key} error: {e}") + })? + .is_none() + { + log::info!( "found valid district! number: {} content: {} inscription_id {}", district.number, std::str::from_utf8(content).unwrap(), inscription_id, ); - return Ok(Some((inscription_id, district))); - } - log::info!( + return Ok(Some((inscription_id, district))); + } + log::info!( "duplicate district! number: {} content: {} inscription_id {}", district.number, std::str::from_utf8(content).unwrap(), inscription_id, ); + } } - } - Ok(None) + Ok(None) } diff --git a/src/okx/protocol/protocol_manager.rs b/src/okx/protocol/protocol_manager.rs index b1541088bd..fb55fcf2ce 100644 --- a/src/okx/protocol/protocol_manager.rs +++ b/src/okx/protocol/protocol_manager.rs @@ -1,3 +1,4 @@ +use anyhow::anyhow; use crate::okx::datastore::ord::OrdReaderWriter; use crate::okx::protocol::context::Context; use { @@ -27,9 +28,9 @@ impl ProtocolManager { } } - pub(crate) fn index_block( + pub(crate) fn index_block( &self, - context: &mut Context, + context: &mut T, block: &BlockData, operations: HashMap>, ) -> Result { @@ -54,10 +55,12 @@ impl ProtocolManager { if let Some(tx_operations) = operations.get(txid) { // save all transaction operations to ord database. if self.config.enable_ord_receipts - && context.chain.blockheight >= self.config.first_inscription_height + && context.block_height()>= self.config.first_inscription_height { let start = Instant::now(); - context.save_transaction_operations(txid, tx_operations)?; + context.save_transaction_operations(txid, tx_operations).map_err(|e|{ + anyhow!("failed to save transaction operations! error: {}", e) + })?; inscriptions_size += tx_operations.len(); cost1 += start.elapsed().as_micros(); } @@ -85,7 +88,7 @@ impl ProtocolManager { log::info!( "Protocol Manager indexed block {} with ord inscriptions {}, messages {}, bitmap {} in {} ms, {}/{}/{}/{}", - context.chain.blockheight, + context.block_height(), inscriptions_size, messages_size, bitmap_count, diff --git a/src/okx/protocol/resolve_manager.rs b/src/okx/protocol/resolve_manager.rs index 2a9d338440..353d4b9c4f 100644 --- a/src/okx/protocol/resolve_manager.rs +++ b/src/okx/protocol/resolve_manager.rs @@ -1,74 +1,74 @@ use crate::inscriptions::ParsedEnvelope; use crate::okx::protocol::context::Context; use { - super::*, - crate::{ - okx::{datastore::ord::operation::InscriptionOp, protocol::Message}, - Inscription, Result, - }, - bitcoin::Transaction, + super::*, + crate::{ + okx::{datastore::ord::operation::InscriptionOp, protocol::Message}, + Inscription, Result, + }, + bitcoin::Transaction, }; pub struct MsgResolveManager { - config: ProtocolConfig, + config: ProtocolConfig, } impl MsgResolveManager { - pub fn new(config: ProtocolConfig) -> Self { - Self { config } - } + pub fn new(config: ProtocolConfig) -> Self { + Self { config } + } - pub fn resolve_message( - &self, - context: &Context, - tx: &Transaction, - operations: &[InscriptionOp], - ) -> Result> { - log::debug!( + pub fn resolve_message( + &self, + context: &T, + tx: &Transaction, + operations: &[InscriptionOp], + ) -> Result> { + log::debug!( "Resolve Manager indexed transaction {}, operations size: {}, data: {:?}", tx.txid(), operations.len(), operations ); - let mut messages = Vec::new(); - let mut operation_iter = operations.iter().peekable(); - let new_inscriptions = ParsedEnvelope::from_transaction(tx) - .into_iter() - .map(|v| v.payload) - .collect::>(); + let mut messages = Vec::new(); + let mut operation_iter = operations.iter().peekable(); + let new_inscriptions = ParsedEnvelope::from_transaction(tx) + .into_iter() + .map(|v| v.payload) + .collect::>(); - for input in &tx.input { - // "operations" is a list of all the operations in the current block, and they are ordered. - // We just need to find the operation corresponding to the current transaction here. - while let Some(operation) = operation_iter.peek() { - if operation.old_satpoint.outpoint != input.previous_output { - break; - } - let operation = operation_iter.next().unwrap(); + for input in &tx.input { + // "operations" is a list of all the operations in the current block, and they are ordered. + // We just need to find the operation corresponding to the current transaction here. + while let Some(operation) = operation_iter.peek() { + if operation.old_satpoint.outpoint != input.previous_output { + break; + } + let operation = operation_iter.next().unwrap(); - // Parse BRC20 message through inscription operation. - if self - .config - .first_brc20_height - .map(|height| context.chain.blockheight >= height) - .unwrap_or(false) - { - if let Some(msg) = brc20::Message::resolve( - context.BRC20_INSCRIBE_TRANSFER, - &new_inscriptions, - operation, - )? { - log::debug!( + // Parse BRC20 message through inscription operation. + if self + .config + .first_brc20_height + .map(|height| context.block_height() >= height) + .unwrap_or(false) + { + if let Some(msg) = brc20::Message::resolve( + context, + &new_inscriptions, + operation, + )? { + log::debug!( "BRC20 resolved the message from {:?}, msg {:?}", operation, msg ); - messages.push(Message::BRC20(msg)); - continue; - } + messages.push(Message::BRC20(msg)); + continue; + } + } + } } - } + Ok(messages) } - Ok(messages) - } } From 45938787a13d6de9aaa17f2cfccae6a4a1de1fd5 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 11 Jan 2024 21:41:54 +0800 Subject: [PATCH 11/66] save2 --- src/index.rs | 1 + src/index/database_processor.rs | 51 ++ src/index/processor.rs | 287 ++++++- src/index/simulate.rs | 1169 ++++++++++++++------------ src/index/updater.rs | 1 + src/index/updater/pending2.rs | 496 +++++++++++ src/index/updater/pending_updater.rs | 8 +- src/okx/datastore/cache.rs | 19 +- 8 files changed, 1428 insertions(+), 604 deletions(-) create mode 100644 src/index/database_processor.rs create mode 100644 src/index/updater/pending2.rs diff --git a/src/index.rs b/src/index.rs index f142452026..1e77ba2083 100644 --- a/src/index.rs +++ b/src/index.rs @@ -54,6 +54,7 @@ pub(crate) mod updater; pub(crate) mod testing; mod simulate; mod processor; +mod database_processor; const SCHEMA_VERSION: u64 = 16; diff --git a/src/index/database_processor.rs b/src/index/database_processor.rs new file mode 100644 index 0000000000..145a15d236 --- /dev/null +++ b/src/index/database_processor.rs @@ -0,0 +1,51 @@ +use std::sync::Arc; +use bitcoin::{OutPoint, TxOut}; +use redb::{ReadTransaction, WriteTransaction}; +use crate::{Index, InscriptionId, SatPoint}; +use crate::index::{InscriptionEntryValue, InscriptionIdValue, TxidValue}; + +pub struct DataBaseProcessor<'a, 'db> { + rtx:&'a ReadTransaction<'db>, + wtx: &'a WriteTransaction<'db>, +} + +impl<'a, 'db> DataBaseProcessor<'a, 'db> { + pub(crate) fn tx_out_cache_insert(&self, p0: &OutPoint, p1: TxOut) -> crate::Result<()> { + todo!() + } +} + +impl<'a, 'db> DataBaseProcessor<'a, 'db> { + pub(crate) fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { + todo!() + } +} + +impl<'a, 'db> DataBaseProcessor<'a, 'db> { + pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { + todo!() + } +} + +impl<'a, 'db> DataBaseProcessor<'a, 'db> { + pub(crate) fn id_to_sequence_number_get(&self, x: InscriptionIdValue) -> crate::Result> { + todo!() + } +} + +impl<'a, 'db> DataBaseProcessor<'a, 'db> { + pub(crate) fn get_txout_by_outpoint(&self, p0: &OutPoint) -> crate::Result { + todo!() + } +} + +impl<'a, 'db> DataBaseProcessor<'a, 'db> { + pub fn inscriptions_on_output(&self, prev_output: &OutPoint) -> crate::Result> { + // let ret = Index::inscriptions_on_output( + // self.satpoint_to_sequence_number, + // self.sequence_number_to_entry, + // prev_output.clone())?; + // TODO: twice + todo!() + } +} diff --git a/src/index/processor.rs b/src/index/processor.rs index 213dd0e324..82b1956de9 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -1,25 +1,245 @@ +// use std::sync::Arc; +// use bitcoin::{OutPoint, TxOut}; +// use redb::{RedbValue, WriteTransaction}; +// use crate::{Index, InscriptionId, SatPoint}; +// use crate::index::entry::SatPointValue; +// use crate::index::{InscriptionEntryValue, InscriptionIdValue, OutPointValue, TxidValue}; +// use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; +// use crate::okx::protocol::context::Context; +// +// pub struct StorageProcessor<'a, 'db,'tx> { +// pub cache_writer: CacheWriter, +// pub internal: Arc, +// +// pub wtx: &'a mut WriteTransaction<'db>, +// } +// +// unsafe impl<'a, 'db,'tx> Send for StorageProcessor<'a, 'db,'tx> {} +// +// unsafe impl<'a, 'db,'tx> Sync for StorageProcessor<'a, 'db,'tx> {} +// +// +// impl<'a, 'db,'tx> StorageProcessor<'a, 'db,'tx> { +// pub(crate) fn create_context(&self) -> crate::Result { +// todo!() +// } +// pub(crate) fn next_sequence_number(&self) -> crate::Result { +// todo!() +// } +// pub(crate) fn outpoint_to_sat_ranges_insert(&self, value: &OutPointValue, data: &[u8]) -> crate::Result<()> { +// todo!() +// } +// pub(crate) fn outpoint_to_sat_ranges_remove(&self, p0: &OutPointValue) -> crate::Result>> { +// todo!() +// } +// pub fn get_lost_sats(&self) -> crate::Result { +// todo!() +// } +// pub fn get_cursed_inscription_count(&self) -> crate::Result { +// todo!() +// } +// pub fn get_blessed_inscription_count(&self) -> crate::Result { +// todo!() +// } +// pub fn get_unbound_inscriptions(&self) -> crate::Result { +// todo!() +// } +// pub fn get_next_sequence_number(&self) -> crate::Result { +// todo!() +// } +// pub fn sat_to_satpoint_insert(&self, key: &u64, value: &SatPointValue) -> crate::Result<()> { +// todo!() +// } +// pub fn get_txout_by_outpoint(&self, x: &OutPoint) -> crate::Result> { +// todo!() +// } +// pub(crate) fn satpoint_to_sequence_number_remove_all(&self, v: &SatPointValue) -> crate::Result<()> { +// // self +// // .satpoint_to_sequence_number +// // .remove_all(v)?; +// // Ok(()) +// todo!() +// } +// pub(crate) fn home_inscriptions_len(&self) -> u64 { +// todo!() +// } +// pub(crate) fn sequence_number_to_satpoint_insert(&self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { +// // self.sequence_number_to_satpoint.insert(sequence_number, sat_point)?; +// +// let key = u32::as_bytes(&sequence_number).to_vec(); +// let value = sat_point.to_vec(); +// self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_SATPOINT, |v| { +// v.insert(key.to_vec(), value.to_vec()); +// }); +// Ok(()) +// } +// pub(crate) fn satpoint_to_sequence_number_insert(&self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { +// // self.sequence_number_to_satpoint.insert(sequence, sat_point)?; +// +// let key = sat_point.to_vec(); +// let value = u32::as_bytes(&sequence).to_vec(); +// self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { +// v.insert(key.to_vec(), value.to_vec()); +// }); +// Ok(()) +// } +// pub(crate) fn home_inscriptions_pop_first(&self) -> crate::Result<()> { +// // self.home_inscriptions.pop_first()?; +// +// self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { +// v.pop_first() +// }); +// Ok(()) +// } +// pub(crate) fn home_inscriptions_insert(&self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { +// let key = u32::as_bytes(sequence_number).to_vec(); +// let value = InscriptionIdValue::as_bytes(&value).to_vec(); +// self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { +// v.insert(key.to_vec(), value.to_vec()); +// }); +// Ok(()) +// // self +// // .home_inscriptions +// // .insert(sequence_number, value)?; +// // Ok(()) +// } +// pub(crate) fn id_to_sequence_number_insert(&self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { +// // let key = rmp_serde::to_vec(value).unwrap(); +// // let value = sequence.to_le_bytes().as_slice(); +// // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |v| { +// // v.insert(key.to_vec(), value.to_vec()); +// // }); +// // Ok(()) +// // self +// // .id_to_sequence_number +// // .insert(value, sequence_number)?; +// Ok(()) +// } +// pub(crate) fn sequence_number_to_children_insert(&self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { +// // let key = sequence.to_le_bytes().as_slice(); +// // let value = rmp_serde::to_vec(value).unwrap(); +// // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_CHILDREN, |v| { +// // v.insert(key.to_vec(), value.to_vec()); +// // }); +// // Ok(()) +// // self +// // .sequence_number_to_children +// // .insert(parent_sequence_number, sequence_number)?; +// Ok(()) +// } +// pub(crate) fn sequence_number_to_entry_insert(&self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { +// // let key = sequence.to_le_bytes().as_slice(); +// // let value = rmp_serde::to_vec(value).unwrap(); +// // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |v| { +// // v.insert(key.to_vec(), value.to_vec()); +// // }); +// // Ok(()) +// // self.sequence_number_to_entry.insert(sequence, value)?; +// Ok(()) +// } +// pub(crate) fn sat_to_sequence_number_insert(&self, n: &u64, sequence_number: &u32) -> crate::Result<()> { +// // let key = n.to_le_bytes().as_slice(); +// // let value = sequence.to_le_bytes().as_slice(); +// // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { +// // v.insert(key.to_vec(), value.to_vec()); +// // }); +// // Ok(()) +// // self.sat_to_sequence_number.insert(n, sequence_number)?; +// Ok(()) +// } +// pub(crate) fn inscription_number_to_sequence_number_insert(&self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { +// // let key = inscription_number.to_le_bytes().as_slice(); +// // let value = sequence_number.to_le_bytes().as_slice(); +// // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, |v| { +// // v.insert(key.to_vec(), value.to_vec()); +// // }); +// // Ok(()) +// // self +// // .inscription_number_to_sequence_number +// // .insert(inscription_number, sequence_number)?; +// Ok(()) +// } +// pub(crate) fn outpoint_to_entry_insert(&self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { +// // self.outpoint_to_entry.insert(value, entry)?; +// Ok(()) +// // let key = rmp_serde::to_vec(value).unwrap(); +// // let value = entry.to_vec(); +// // self.cache_writer.use_cache_mut(CacheTableIndex::OUTPOINT_TO_ENTRY, |v| { +// // v.insert(key.to_vec(), value.to_vec()); +// // }); +// // Ok(()) +// } +// pub fn inscriptions_on_output(&self, prev_output: &OutPoint) -> crate::Result> { +// // let ret = Index::inscriptions_on_output( +// // self.satpoint_to_sequence_number, +// // self.sequence_number_to_entry, +// // prev_output.clone())?; +// // TODO: twice +// todo!() +// } +// +// pub(crate) fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { +// // self +// // .transaction_id_to_transaction +// // .insert(tx_id, value)?; +// +// Ok(()) +// } +// +// pub(crate) fn id_to_sequence_number_get(&self, x: InscriptionIdValue) -> crate::Result> { +// // TODO,twice +// // let ret = self.id_to_sequence_number.get(x)?.unwrap().value(); +// // Ok(Some(ret)) +// todo!() +// } +// pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { +// // TODO: twice +// // let ret = self +// // .sequence_number_to_entry +// // .get(initial_inscription_sequence_number)? +// // .unwrap() +// // .value(); +// // Ok(Some(ret)) +// todo!() +// } +// } +////////////////// + + use std::sync::Arc; use bitcoin::{OutPoint, TxOut}; -use redb::{RedbValue, WriteTransaction}; +use redb::{MultimapTable, RedbValue, Table, WriteTransaction}; use crate::{Index, InscriptionId, SatPoint}; use crate::index::entry::SatPointValue; use crate::index::{InscriptionEntryValue, InscriptionIdValue, OutPointValue, TxidValue}; use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; use crate::okx::protocol::context::Context; -pub struct StorageProcessor<'a, 'db> { - pub cache_writer: CacheWriter, +pub struct StorageProcessor<'a, 'db, 'tx> { pub internal: Arc, - pub wtx: &'a mut WriteTransaction<'db>, + // pub wtx: &'a mut WriteTransaction<'db>, + + pub(super) home_inscriptions: &'a mut Table<'db, 'tx, u32, InscriptionIdValue>, + pub(super) id_to_sequence_number: &'a mut Table<'db, 'tx, InscriptionIdValue, u32>, + pub(super) inscription_number_to_sequence_number: &'a mut Table<'db, 'tx, i32, u32>, + pub(super) outpoint_to_entry: &'a mut Table<'db, 'tx, &'static OutPointValue, &'static [u8]>, + pub(super) transaction_id_to_transaction: + &'a mut Table<'db, 'tx, &'static TxidValue, &'static [u8]>, + pub(super) sat_to_sequence_number: &'a mut MultimapTable<'db, 'tx, u64, u32>, + pub(super) satpoint_to_sequence_number: + &'a mut MultimapTable<'db, 'tx, &'static SatPointValue, u32>, + pub(super) sequence_number_to_children: &'a mut MultimapTable<'db, 'tx, u32, u32>, + pub(super) sequence_number_to_entry: &'a mut Table<'db, 'tx, u32, InscriptionEntryValue>, + pub(super) sequence_number_to_satpoint: &'a mut Table<'db, 'tx, u32, &'static SatPointValue>, } -unsafe impl<'a, 'db> Send for StorageProcessor<'a, 'db> {} +unsafe impl<'a, 'db, 'tx> Send for StorageProcessor<'a, 'db, 'tx> {} -unsafe impl<'a, 'db> Sync for StorageProcessor<'a, 'db> {} +unsafe impl<'a, 'db, 'tx> Sync for StorageProcessor<'a, 'db, 'tx> {} -impl<'a, 'db> StorageProcessor<'a, 'db> { +impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { pub(crate) fn create_context(&self) -> crate::Result { todo!() } @@ -64,44 +284,45 @@ impl<'a, 'db> StorageProcessor<'a, 'db> { todo!() } pub(crate) fn sequence_number_to_satpoint_insert(&self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { - // self.sequence_number_to_satpoint.insert(sequence_number, sat_point)?; + self.sequence_number_to_satpoint.insert(sequence_number, sat_point)?; - let key = u32::as_bytes(&sequence_number).to_vec(); - let value = sat_point.to_vec(); - self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_SATPOINT, |v| { - v.insert(key.to_vec(), value.to_vec()); - }); + // let key = u32::as_bytes(&sequence_number).to_vec(); + // let value = sat_point.to_vec(); + // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_SATPOINT, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); Ok(()) } pub(crate) fn satpoint_to_sequence_number_insert(&self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { - // self.sequence_number_to_satpoint.insert(sequence, sat_point)?; + self.sequence_number_to_satpoint.insert(sequence, sat_point)?; - let key = sat_point.to_vec(); - let value = u32::as_bytes(&sequence).to_vec(); - self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { - v.insert(key.to_vec(), value.to_vec()); - }); + // let key = sat_point.to_vec(); + // let value = u32::as_bytes(&sequence).to_vec(); + // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); Ok(()) } pub(crate) fn home_inscriptions_pop_first(&self) -> crate::Result<()> { - // self.home_inscriptions.pop_first()?; + self.home_inscriptions.pop_first()?; - self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { - v.pop_first() - }); + // self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { + // v.pop_first() + // }); Ok(()) } pub(crate) fn home_inscriptions_insert(&self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { - let key = u32::as_bytes(sequence_number).to_vec(); - let value = InscriptionIdValue::as_bytes(&value).to_vec(); - self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { - v.insert(key.to_vec(), value.to_vec()); - }); - Ok(()) - // self - // .home_inscriptions - // .insert(sequence_number, value)?; + // let key = u32::as_bytes(sequence_number).to_vec(); + // let value = InscriptionIdValue::as_bytes(&value).to_vec(); + // self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { + // v.insert(key.to_vec(), value.to_vec()); + // }); // Ok(()) + + self + .home_inscriptions + .insert(sequence_number, value)?; + Ok(()) } pub(crate) fn id_to_sequence_number_insert(&self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { // let key = rmp_serde::to_vec(value).unwrap(); @@ -160,7 +381,7 @@ impl<'a, 'db> StorageProcessor<'a, 'db> { Ok(()) } pub(crate) fn outpoint_to_entry_insert(&self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { - // self.outpoint_to_entry.insert(value, entry)?; + self.outpoint_to_entry.insert(value, entry)?; Ok(()) // let key = rmp_serde::to_vec(value).unwrap(); // let value = entry.to_vec(); diff --git a/src/index/simulate.rs b/src/index/simulate.rs index ced1977354..ab7f8348f9 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -1,558 +1,611 @@ -// use std::collections::{HashMap, HashSet, VecDeque}; -// use std::marker::PhantomData; -// use std::sync::Arc; -// use std::sync::atomic::{AtomicUsize, Ordering}; -// use std::time::Instant; -// use anyhow::anyhow; -// use bitcoin::{OutPoint, Transaction, Txid, TxOut}; -// use redb::{ReadableTable, Table, WriteTransaction}; -// use tokio::sync::mpsc::{Receiver, Sender}; -// use tokio::sync::mpsc::error::TryRecvError; -// use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; -// use crate::height::Height; -// use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; -// use crate::index::entry::{Entry, SatPointValue, SatRange}; -// use crate::index::processor::StorageProcessor; -// use crate::index::updater::pending_updater::PendingUpdater; -// use crate::okx::datastore::cache::CacheWriter; -// use crate::okx::datastore::ord::InscriptionOp; -// use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; -// use crate::okx::lru::SimpleLru; -// use crate::okx::protocol::{BlockContext, ProtocolConfig, ProtocolManager}; -// use crate::okx::protocol::context::Context; -// use crate::okx::protocol::trace::IndexTracer; -// -// pub struct Simulator<'a, 'db> { -// options: Options, -// simulate_index: IndexTracer, -// internal_index: Arc, -// _marker_a: PhantomData<&'a ()>, -// _marker_b: PhantomData<&'db ()>, -// } -// -// impl<'a, 'db> Simulator<'a, 'db> { -// pub fn simulate_tx(&self) {} -// -// // fn index_block( -// // &mut self, -// // index: &Index, -// // height: u32, -// // outpoint_sender: &mut Sender, -// // tx_out_receiver: &mut Receiver, -// // block: BlockData, -// // tx_out_cache: &mut SimpleLru, -// // wtx: &mut WriteTransaction, -// // ) -> crate::Result<()> { -// // let start = Instant::now(); -// // let mut sat_ranges_written = 0; -// // let mut outputs_in_block = 0; -// // -// // // If value_receiver still has values something went wrong with the last block -// // // Could be an assert, shouldn't recover from this and commit the last block -// // let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { -// // return Err(anyhow!("Previous block did not consume all input values")); -// // }; -// // -// // let mut outpoint_to_entry = wtx.open_table(OUTPOINT_TO_ENTRY)?; -// // -// // let index_inscriptions = true; -// // -// // let fetching_outputs_count = AtomicUsize::new(0); -// // let total_outputs_count = AtomicUsize::new(0); -// // let cache_outputs_count = AtomicUsize::new(0); -// // let miss_outputs_count = AtomicUsize::new(0); -// // let meet_outputs_count = AtomicUsize::new(0); -// // if index_inscriptions { -// // // Send all missing input outpoints to be fetched right away -// // let txids = block -// // .txdata -// // .iter() -// // .map(|(_, txid)| txid) -// // .collect::>(); -// // use rayon::prelude::*; -// // let tx_outs = block -// // .txdata -// // .par_iter() -// // .flat_map(|(tx, _)| tx.input.par_iter()) -// // .filter_map(|input| { -// // total_outputs_count.fetch_add(1, Ordering::Relaxed); -// // let prev_output = input.previous_output; -// // // We don't need coinbase input value -// // if prev_output.is_null() { -// // None -// // } else if txids.contains(&prev_output.txid) { -// // meet_outputs_count.fetch_add(1, Ordering::Relaxed); -// // None -// // } else if tx_out_cache.contains(&prev_output) { -// // cache_outputs_count.fetch_add(1, Ordering::Relaxed); -// // None -// // } else if let Some(txout) = -// // get_txout_by_outpoint(&outpoint_to_entry, &prev_output).unwrap() -// // { -// // miss_outputs_count.fetch_add(1, Ordering::Relaxed); -// // Some((prev_output, Some(txout))) -// // } else { -// // fetching_outputs_count.fetch_add(1, Ordering::Relaxed); -// // Some((prev_output, None)) -// // } -// // }) -// // .collect::>(); -// // for (out_point, value) in tx_outs.into_iter() { -// // if let Some(tx_out) = value { -// // tx_out_cache.insert(out_point, tx_out); -// // } else { -// // outpoint_sender.blocking_send(out_point).unwrap(); -// // } -// // } -// // } -// // -// // let time = timestamp(block.header.time); -// // -// // log::info!( -// // "Block {} at {} with {} transactions, fetching previous outputs {}/{}…, {},{},{}, cost:{}ms", -// // height, -// // time, -// // block.txdata.len(), -// // fetching_outputs_count.load(Ordering::Relaxed), -// // total_outputs_count.load(Ordering::Relaxed), -// // miss_outputs_count.load(Ordering::Relaxed), -// // meet_outputs_count.load(Ordering::Relaxed), -// // cache_outputs_count.load(Ordering::Relaxed), -// // start.elapsed().as_millis(), -// // ); -// // -// // let mut height_to_block_header = wtx.open_table(HEIGHT_TO_BLOCK_HEADER)?; -// // let mut height_to_last_sequence_number = wtx.open_table(HEIGHT_TO_LAST_SEQUENCE_NUMBER)?; -// // let mut home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS)?; -// // let mut inscription_id_to_sequence_number = -// // wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; -// // let mut inscription_number_to_sequence_number = -// // wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER)?; -// // let mut sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER)?; -// // let mut satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; -// // let mut sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN)?; -// // let mut sequence_number_to_inscription_entry = -// // wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; -// // let mut sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT)?; -// // let mut statistic_to_count = wtx.open_table(STATISTIC_TO_COUNT)?; -// // let mut transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION)?; -// // -// // let mut lost_sats = statistic_to_count -// // .get(&Statistic::LostSats.key())? -// // .map(|lost_sats| lost_sats.value()) -// // .unwrap_or(0); -// // -// // let cursed_inscription_count = statistic_to_count -// // .get(&Statistic::CursedInscriptions.key())? -// // .map(|count| count.value()) -// // .unwrap_or(0); -// // -// // let blessed_inscription_count = statistic_to_count -// // .get(&Statistic::BlessedInscriptions.key())? -// // .map(|count| count.value()) -// // .unwrap_or(0); -// // -// // let unbound_inscriptions = statistic_to_count -// // .get(&Statistic::UnboundInscriptions.key())? -// // .map(|unbound_inscriptions| unbound_inscriptions.value()) -// // .unwrap_or(0); -// // -// // let next_sequence_number = sequence_number_to_inscription_entry -// // .iter()? -// // .next_back() -// // .and_then(|result| result.ok()) -// // .map(|(number, _id)| number.value() + 1) -// // .unwrap_or(0); -// // -// // let mut operations = HashMap::new(); -// // let mut processor = StorageProcessor::new(self.cache.clone(),self.internal_index.clone()); -// // // let mut processor = crate::index::updater::pending_updater::PendingStorageProcessor::new( -// // // &mut home_inscriptions, -// // // &mut inscription_id_to_sequence_number, -// // // &mut inscription_number_to_sequence_number, -// // // &mut outpoint_to_entry, -// // // &mut transaction_id_to_transaction, -// // // &mut sat_to_sequence_number, -// // // &mut satpoint_to_sequence_number, -// // // &mut sequence_number_to_children, -// // // &mut sequence_number_to_inscription_entry, -// // // &mut sequence_number_to_satpoint, -// // // ); -// // let mut inscription_updater = PendingUpdater::new( -// // &mut operations, -// // blessed_inscription_count, -// // self.internal_index.options.chain(), -// // cursed_inscription_count, -// // height, -// // self.internal_index.index_transactions, -// // next_sequence_number, -// // lost_sats, -// // block.header.time, -// // unbound_inscriptions, -// // tx_out_receiver, -// // tx_out_cache, -// // &mut processor, -// // )?; -// // -// // let index_sats = true; -// // if index_sats { -// // let mut sat_to_satpoint = wtx.open_table(SAT_TO_SATPOINT)?; -// // let mut outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES)?; -// // -// // let mut coinbase_inputs = VecDeque::new(); -// // -// // let h = Height(height); -// // if h.subsidy() > 0 { -// // let start = h.starting_sat(); -// // coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); -// // } -// // -// // for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { -// // log::trace!("Indexing transaction {tx_offset}…"); -// // -// // let mut input_sat_ranges = VecDeque::new(); -// // -// // // TODO: make sure this is correct -// // // for input in &tx.input { -// // // let key = input.previous_output.store(); -// // // let sat_ranges = match self.range_cache.remove(&key) { -// // // Some(sat_ranges) => { -// // // self.outputs_cached += 1; -// // // sat_ranges -// // // } -// // // None => outpoint_to_sat_ranges -// // // .remove(&key)? -// // // .ok_or_else(|| anyhow!("Could not find outpoint {} in index", input.previous_output))? -// // // .value() -// // // .to_vec(), -// // // }; -// // // -// // // for chunk in sat_ranges.chunks_exact(11) { -// // // input_sat_ranges.push_back(SatRange::load(chunk.try_into().unwrap())); -// // // } -// // // } -// // -// // self.index_transaction_sats( -// // tx, -// // *txid, -// // &mut sat_to_satpoint, -// // &mut input_sat_ranges, -// // &mut sat_ranges_written, -// // &mut outputs_in_block, -// // &mut inscription_updater, -// // index_inscriptions, -// // )?; -// // -// // coinbase_inputs.extend(input_sat_ranges); -// // } -// // -// // if let Some((tx, txid)) = block.txdata.first() { -// // self.index_transaction_sats( -// // tx, -// // *txid, -// // &mut sat_to_satpoint, -// // &mut coinbase_inputs, -// // &mut sat_ranges_written, -// // &mut outputs_in_block, -// // &mut inscription_updater, -// // index_inscriptions, -// // )?; -// // } -// // -// // if !coinbase_inputs.is_empty() { -// // let mut lost_sat_ranges = outpoint_to_sat_ranges -// // .remove(&OutPoint::null().store())? -// // .map(|ranges| ranges.value().to_vec()) -// // .unwrap_or_default(); -// // -// // for (start, end) in coinbase_inputs { -// // if !Sat(start).common() { -// // sat_to_satpoint.insert( -// // &start, -// // &SatPoint { -// // outpoint: OutPoint::null(), -// // offset: lost_sats, -// // } -// // .store(), -// // )?; -// // } -// // -// // lost_sat_ranges.extend_from_slice(&(start, end).store()); -// // -// // lost_sats += end - start; -// // } -// // -// // outpoint_to_sat_ranges.insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; -// // } -// // } else if index_inscriptions { -// // for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { -// // inscription_updater.index_envelopes(tx, *txid, None)?; -// // } -// // } -// // inscription_updater.flush_cache()?; -// // -// // let mut context = Context { -// // chain: BlockContext { -// // network: index.get_chain_network(), -// // blockheight: height, -// // blocktime: block.header.time, -// // }, -// // tx_out_cache, -// // hit: 0, -// // miss: 0, -// // ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS)?, -// // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, -// // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx -// // .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, -// // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut sequence_number_to_inscription_entry, -// // OUTPOINT_TO_ENTRY: &mut outpoint_to_entry, -// // BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES)?, -// // BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN)?, -// // BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS)?, -// // BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG)?, -// // BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER)?, -// // }; -// // -// // // Create a protocol manager to index the block of bitmap data. -// // let config = ProtocolConfig::new_with_options(&index.options); -// // ProtocolManager::new(config).index_block(&mut context, &block, operations)?; -// // -// // Ok(()) -// // } -// -// fn index_block( -// &mut self, -// index: &Index, -// height: u32, -// outpoint_sender: &'a mut Sender, -// tx_out_receiver: &'a mut Receiver, -// block: BlockData, -// tx_out_cache: &'a mut SimpleLru, -// processor: &'db mut StorageProcessor<'a, 'db>, -// operations: &'db mut HashMap> -// ) -> crate::Result<()> { -// let start = Instant::now(); -// let mut sat_ranges_written = 0; -// let mut outputs_in_block = 0; -// -// // If value_receiver still has values something went wrong with the last block -// // Could be an assert, shouldn't recover from this and commit the last block -// let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { -// return Err(anyhow!("Previous block did not consume all input values")); -// }; -// -// -// let index_inscriptions = true; -// -// let fetching_outputs_count = AtomicUsize::new(0); -// let total_outputs_count = AtomicUsize::new(0); -// let cache_outputs_count = AtomicUsize::new(0); -// let miss_outputs_count = AtomicUsize::new(0); -// let meet_outputs_count = AtomicUsize::new(0); -// if index_inscriptions { -// // Send all missing input outpoints to be fetched right away -// let txids = block -// .txdata -// .iter() -// .map(|(_, txid)| txid) -// .collect::>(); -// use rayon::prelude::*; -// let tx_outs = block -// .txdata -// .par_iter() -// .flat_map(|(tx, _)| tx.input.par_iter()) -// .filter_map(|input| { -// total_outputs_count.fetch_add(1, Ordering::Relaxed); -// let prev_output = input.previous_output; -// // We don't need coinbase input value -// if prev_output.is_null() { -// None -// } else if txids.contains(&prev_output.txid) { -// meet_outputs_count.fetch_add(1, Ordering::Relaxed); -// None -// } else if tx_out_cache.contains(&prev_output) { -// cache_outputs_count.fetch_add(1, Ordering::Relaxed); -// None -// } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output).unwrap() -// { -// miss_outputs_count.fetch_add(1, Ordering::Relaxed); -// Some((prev_output, Some(txout))) -// } else { -// fetching_outputs_count.fetch_add(1, Ordering::Relaxed); -// Some((prev_output, None)) -// } -// }) -// .collect::>(); -// for (out_point, value) in tx_outs.into_iter() { -// if let Some(tx_out) = value { -// tx_out_cache.insert(out_point, tx_out); -// } else { -// outpoint_sender.blocking_send(out_point).unwrap(); -// } -// } -// } -// -// let mut lost_sats = processor.get_lost_sats()?; -// let cursed_inscription_count = processor.get_cursed_inscription_count()?; -// let blessed_inscription_count = processor.get_blessed_inscription_count()?; -// let unbound_inscriptions = processor.get_unbound_inscriptions()?; -// let next_sequence_number = processor.next_sequence_number()?; -// -// // let processor = &mut self.processor; -// let mut inscription_updater = PendingUpdater::new( -// operations, -// blessed_inscription_count, -// self.internal_index.options.chain(), -// cursed_inscription_count, -// height, -// self.internal_index.index_transactions, -// next_sequence_number, -// lost_sats, -// block.header.time, -// unbound_inscriptions, -// tx_out_receiver, -// tx_out_cache, -// processor, -// )?; -// -// let index_sats = true; -// if index_sats { -// let mut coinbase_inputs = VecDeque::new(); -// -// let h = Height(height); -// if h.subsidy() > 0 { -// let start = h.starting_sat(); -// coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); -// } -// -// for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { -// log::trace!("Indexing transaction {tx_offset}…"); -// -// let mut input_sat_ranges = VecDeque::new(); -// -// self.index_transaction_sats( -// tx, -// *txid, -// &mut input_sat_ranges, -// &mut sat_ranges_written, -// &mut outputs_in_block, -// &mut inscription_updater, -// index_inscriptions, -// )?; -// -// coinbase_inputs.extend(input_sat_ranges); -// } -// -// if let Some((tx, txid)) = block.txdata.first() { -// self.index_transaction_sats( -// tx, -// *txid, -// &mut coinbase_inputs, -// &mut sat_ranges_written, -// &mut outputs_in_block, -// &mut inscription_updater, -// index_inscriptions, -// )?; -// } -// -// if !coinbase_inputs.is_empty() { -// let mut lost_sat_ranges = processor.outpoint_to_sat_ranges_remove(&OutPoint::null().store())?.map(|ranges| ranges.to_vec()) -// .unwrap_or_default(); -// -// for (start, end) in coinbase_inputs { -// if !Sat(start).common() { -// processor.sat_to_satpoint_insert( -// &start, -// &SatPoint { -// outpoint: OutPoint::null(), -// offset: lost_sats, -// } -// .store(), -// )?; -// } -// -// lost_sat_ranges.extend_from_slice(&(start, end).store()); -// -// lost_sats += end - start; -// } -// processor.outpoint_to_sat_ranges_insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; -// } -// } else if index_inscriptions { -// for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { -// inscription_updater.index_envelopes(tx, *txid, None)?; -// } -// } -// inscription_updater.flush_cache()?; -// -// // TODO: -// // let mut context = processor.create_context()?; -// // // Create a protocol manager to index the block of bitmap data. -// // let config = ProtocolConfig::new_with_options(&index.options); -// // ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; -// -// Ok(()) -// } -// -// fn index_and_execute(&self,){ -// } -// // fn index_transaction_sats( -// // &mut self, -// // tx: &Transaction, -// // txid: Txid, -// // input_sat_ranges: &mut VecDeque<(u64, u64)>, -// // sat_ranges_written: &mut u64, -// // outputs_traversed: &mut u64, -// // inscription_updater: &mut PendingUpdater, -// // index_inscriptions: bool, -// // ) -> crate::Result { -// // if index_inscriptions { -// // inscription_updater.index_envelopes(tx, txid, Some(input_sat_ranges))?; -// // } -// // -// // for (vout, output) in tx.output.iter().enumerate() { -// // let outpoint = OutPoint { -// // vout: vout.try_into().unwrap(), -// // txid, -// // }; -// // let mut sats = Vec::new(); -// // -// // let mut remaining = output.value; -// // while remaining > 0 { -// // let range = input_sat_ranges -// // .pop_front() -// // .ok_or_else(|| anyhow!("insufficient inputs for transaction outputs"))?; -// // -// // if !Sat(range.0).common() { -// // inscription_updater.processor.sat_to_satpoint_insert( -// // &range.0, -// // &SatPoint { -// // outpoint, -// // offset: 0, -// // } -// // .store(), -// // )?; -// // } -// // -// // let count = range.1 - range.0; -// // -// // let assigned = if count > remaining { -// // let middle = range.0 + remaining; -// // input_sat_ranges.push_front((middle, range.1)); -// // (range.0, middle) -// // } else { -// // range -// // }; -// // -// // sats.extend_from_slice(&assigned.store()); -// // -// // remaining -= assigned.1 - assigned.0; -// // -// // *sat_ranges_written += 1; -// // } -// // -// // *outputs_traversed += 1; -// // } -// // -// // Ok(()) -// // } -// } +use std::collections::{HashMap, HashSet, VecDeque}; +use std::marker::PhantomData; +use std::path::PathBuf; +use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::time::Instant; +use anyhow::anyhow; +use bitcoin::{OutPoint, Transaction, Txid, TxOut}; +use redb::{ReadableTable, Table, WriteTransaction}; +use tokio::sync::mpsc::{Receiver, Sender}; +use tokio::sync::mpsc::error::TryRecvError; +use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; +use crate::height::Height; +use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; +use crate::index::entry::{Entry, SatPointValue, SatRange}; +use crate::index::processor::StorageProcessor; +use crate::index::updater::pending_updater::PendingUpdater; +use crate::okx::datastore::cache::CacheWriter; +use crate::okx::datastore::ord::InscriptionOp; +use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; +use crate::okx::lru::SimpleLru; +use crate::okx::protocol::{BlockContext, ProtocolConfig, ProtocolManager}; +use crate::okx::protocol::context::Context; +use crate::okx::protocol::trace::IndexTracer; + +pub struct Simulator<'a, 'db, 'tx> { + pub options: Options, + // pub simulate_index: IndexTracer, + pub internal_index: Arc, + _marker_a: PhantomData<&'a ()>, + _marker_b: PhantomData<&'db ()>, + _marker_tx: PhantomData<&'tx ()>, +} + +impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { + pub fn simulate_tx(&self) {} + + // fn index_block( + // &mut self, + // index: &Index, + // height: u32, + // outpoint_sender: &mut Sender, + // tx_out_receiver: &mut Receiver, + // block: BlockData, + // tx_out_cache: &mut SimpleLru, + // wtx: &mut WriteTransaction, + // ) -> crate::Result<()> { + // let start = Instant::now(); + // let mut sat_ranges_written = 0; + // let mut outputs_in_block = 0; + // + // // If value_receiver still has values something went wrong with the last block + // // Could be an assert, shouldn't recover from this and commit the last block + // let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { + // return Err(anyhow!("Previous block did not consume all input values")); + // }; + // + // let mut outpoint_to_entry = wtx.open_table(OUTPOINT_TO_ENTRY)?; + // + // let index_inscriptions = true; + // + // let fetching_outputs_count = AtomicUsize::new(0); + // let total_outputs_count = AtomicUsize::new(0); + // let cache_outputs_count = AtomicUsize::new(0); + // let miss_outputs_count = AtomicUsize::new(0); + // let meet_outputs_count = AtomicUsize::new(0); + // if index_inscriptions { + // // Send all missing input outpoints to be fetched right away + // let txids = block + // .txdata + // .iter() + // .map(|(_, txid)| txid) + // .collect::>(); + // use rayon::prelude::*; + // let tx_outs = block + // .txdata + // .par_iter() + // .flat_map(|(tx, _)| tx.input.par_iter()) + // .filter_map(|input| { + // total_outputs_count.fetch_add(1, Ordering::Relaxed); + // let prev_output = input.previous_output; + // // We don't need coinbase input value + // if prev_output.is_null() { + // None + // } else if txids.contains(&prev_output.txid) { + // meet_outputs_count.fetch_add(1, Ordering::Relaxed); + // None + // } else if tx_out_cache.contains(&prev_output) { + // cache_outputs_count.fetch_add(1, Ordering::Relaxed); + // None + // } else if let Some(txout) = + // get_txout_by_outpoint(&outpoint_to_entry, &prev_output).unwrap() + // { + // miss_outputs_count.fetch_add(1, Ordering::Relaxed); + // Some((prev_output, Some(txout))) + // } else { + // fetching_outputs_count.fetch_add(1, Ordering::Relaxed); + // Some((prev_output, None)) + // } + // }) + // .collect::>(); + // for (out_point, value) in tx_outs.into_iter() { + // if let Some(tx_out) = value { + // tx_out_cache.insert(out_point, tx_out); + // } else { + // outpoint_sender.blocking_send(out_point).unwrap(); + // } + // } + // } + // + // let time = timestamp(block.header.time); + // + // log::info!( + // "Block {} at {} with {} transactions, fetching previous outputs {}/{}…, {},{},{}, cost:{}ms", + // height, + // time, + // block.txdata.len(), + // fetching_outputs_count.load(Ordering::Relaxed), + // total_outputs_count.load(Ordering::Relaxed), + // miss_outputs_count.load(Ordering::Relaxed), + // meet_outputs_count.load(Ordering::Relaxed), + // cache_outputs_count.load(Ordering::Relaxed), + // start.elapsed().as_millis(), + // ); + // + // let mut height_to_block_header = wtx.open_table(HEIGHT_TO_BLOCK_HEADER)?; + // let mut height_to_last_sequence_number = wtx.open_table(HEIGHT_TO_LAST_SEQUENCE_NUMBER)?; + // let mut home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS)?; + // let mut inscription_id_to_sequence_number = + // wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; + // let mut inscription_number_to_sequence_number = + // wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER)?; + // let mut sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER)?; + // let mut satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; + // let mut sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN)?; + // let mut sequence_number_to_inscription_entry = + // wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; + // let mut sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT)?; + // let mut statistic_to_count = wtx.open_table(STATISTIC_TO_COUNT)?; + // let mut transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION)?; + // + // let mut lost_sats = statistic_to_count + // .get(&Statistic::LostSats.key())? + // .map(|lost_sats| lost_sats.value()) + // .unwrap_or(0); + // + // let cursed_inscription_count = statistic_to_count + // .get(&Statistic::CursedInscriptions.key())? + // .map(|count| count.value()) + // .unwrap_or(0); + // + // let blessed_inscription_count = statistic_to_count + // .get(&Statistic::BlessedInscriptions.key())? + // .map(|count| count.value()) + // .unwrap_or(0); + // + // let unbound_inscriptions = statistic_to_count + // .get(&Statistic::UnboundInscriptions.key())? + // .map(|unbound_inscriptions| unbound_inscriptions.value()) + // .unwrap_or(0); + // + // let next_sequence_number = sequence_number_to_inscription_entry + // .iter()? + // .next_back() + // .and_then(|result| result.ok()) + // .map(|(number, _id)| number.value() + 1) + // .unwrap_or(0); + // + // let mut operations = HashMap::new(); + // let mut processor = StorageProcessor::new(self.cache.clone(),self.internal_index.clone()); + // // let mut processor = crate::index::updater::pending_updater::PendingStorageProcessor::new( + // // &mut home_inscriptions, + // // &mut inscription_id_to_sequence_number, + // // &mut inscription_number_to_sequence_number, + // // &mut outpoint_to_entry, + // // &mut transaction_id_to_transaction, + // // &mut sat_to_sequence_number, + // // &mut satpoint_to_sequence_number, + // // &mut sequence_number_to_children, + // // &mut sequence_number_to_inscription_entry, + // // &mut sequence_number_to_satpoint, + // // ); + // let mut inscription_updater = PendingUpdater::new( + // &mut operations, + // blessed_inscription_count, + // self.internal_index.options.chain(), + // cursed_inscription_count, + // height, + // self.internal_index.index_transactions, + // next_sequence_number, + // lost_sats, + // block.header.time, + // unbound_inscriptions, + // tx_out_receiver, + // tx_out_cache, + // &mut processor, + // )?; + // + // let index_sats = true; + // if index_sats { + // let mut sat_to_satpoint = wtx.open_table(SAT_TO_SATPOINT)?; + // let mut outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES)?; + // + // let mut coinbase_inputs = VecDeque::new(); + // + // let h = Height(height); + // if h.subsidy() > 0 { + // let start = h.starting_sat(); + // coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); + // } + // + // for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { + // log::trace!("Indexing transaction {tx_offset}…"); + // + // let mut input_sat_ranges = VecDeque::new(); + // + // // TODO: make sure this is correct + // // for input in &tx.input { + // // let key = input.previous_output.store(); + // // let sat_ranges = match self.range_cache.remove(&key) { + // // Some(sat_ranges) => { + // // self.outputs_cached += 1; + // // sat_ranges + // // } + // // None => outpoint_to_sat_ranges + // // .remove(&key)? + // // .ok_or_else(|| anyhow!("Could not find outpoint {} in index", input.previous_output))? + // // .value() + // // .to_vec(), + // // }; + // // + // // for chunk in sat_ranges.chunks_exact(11) { + // // input_sat_ranges.push_back(SatRange::load(chunk.try_into().unwrap())); + // // } + // // } + // + // self.index_transaction_sats( + // tx, + // *txid, + // &mut sat_to_satpoint, + // &mut input_sat_ranges, + // &mut sat_ranges_written, + // &mut outputs_in_block, + // &mut inscription_updater, + // index_inscriptions, + // )?; + // + // coinbase_inputs.extend(input_sat_ranges); + // } + // + // if let Some((tx, txid)) = block.txdata.first() { + // self.index_transaction_sats( + // tx, + // *txid, + // &mut sat_to_satpoint, + // &mut coinbase_inputs, + // &mut sat_ranges_written, + // &mut outputs_in_block, + // &mut inscription_updater, + // index_inscriptions, + // )?; + // } + // + // if !coinbase_inputs.is_empty() { + // let mut lost_sat_ranges = outpoint_to_sat_ranges + // .remove(&OutPoint::null().store())? + // .map(|ranges| ranges.value().to_vec()) + // .unwrap_or_default(); + // + // for (start, end) in coinbase_inputs { + // if !Sat(start).common() { + // sat_to_satpoint.insert( + // &start, + // &SatPoint { + // outpoint: OutPoint::null(), + // offset: lost_sats, + // } + // .store(), + // )?; + // } + // + // lost_sat_ranges.extend_from_slice(&(start, end).store()); + // + // lost_sats += end - start; + // } + // + // outpoint_to_sat_ranges.insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; + // } + // } else if index_inscriptions { + // for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { + // inscription_updater.index_envelopes(tx, *txid, None)?; + // } + // } + // inscription_updater.flush_cache()?; + // + // let mut context = Context { + // chain: BlockContext { + // network: index.get_chain_network(), + // blockheight: height, + // blocktime: block.header.time, + // }, + // tx_out_cache, + // hit: 0, + // miss: 0, + // ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS)?, + // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, + // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx + // .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, + // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut sequence_number_to_inscription_entry, + // OUTPOINT_TO_ENTRY: &mut outpoint_to_entry, + // BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES)?, + // BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN)?, + // BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS)?, + // BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG)?, + // BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER)?, + // }; + // + // // Create a protocol manager to index the block of bitmap data. + // let config = ProtocolConfig::new_with_options(&index.options); + // ProtocolManager::new(config).index_block(&mut context, &block, operations)?; + // + // Ok(()) + // } + + fn index_block( + &mut self, + height: u32, + outpoint_sender: &'a mut Sender, + tx_out_receiver: &'a mut Receiver, + block: BlockData, + tx_out_cache: &'a mut SimpleLru, + processor: &'db mut StorageProcessor<'a, 'db, 'tx>, + operations: &'db mut HashMap>, + ) -> crate::Result<()> { + let start = Instant::now(); + let mut sat_ranges_written = 0; + let mut outputs_in_block = 0; + + // If value_receiver still has values something went wrong with the last block + // Could be an assert, shouldn't recover from this and commit the last block + let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { + return Err(anyhow!("Previous block did not consume all input values")); + }; + + + let index_inscriptions = true; + + let fetching_outputs_count = AtomicUsize::new(0); + let total_outputs_count = AtomicUsize::new(0); + let cache_outputs_count = AtomicUsize::new(0); + let miss_outputs_count = AtomicUsize::new(0); + let meet_outputs_count = AtomicUsize::new(0); + if index_inscriptions { + // Send all missing input outpoints to be fetched right away + let txids = block + .txdata + .iter() + .map(|(_, txid)| txid) + .collect::>(); + use rayon::prelude::*; + let tx_outs = block + .txdata + .par_iter() + .flat_map(|(tx, _)| tx.input.par_iter()) + .filter_map(|input| { + total_outputs_count.fetch_add(1, Ordering::Relaxed); + let prev_output = input.previous_output; + // We don't need coinbase input value + if prev_output.is_null() { + None + } else if txids.contains(&prev_output.txid) { + meet_outputs_count.fetch_add(1, Ordering::Relaxed); + None + } else if tx_out_cache.contains(&prev_output) { + cache_outputs_count.fetch_add(1, Ordering::Relaxed); + None + } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output).unwrap() + { + miss_outputs_count.fetch_add(1, Ordering::Relaxed); + Some((prev_output, Some(txout))) + } else { + fetching_outputs_count.fetch_add(1, Ordering::Relaxed); + Some((prev_output, None)) + } + }) + .collect::>(); + for (out_point, value) in tx_outs.into_iter() { + if let Some(tx_out) = value { + tx_out_cache.insert(out_point, tx_out); + } else { + outpoint_sender.blocking_send(out_point).unwrap(); + } + } + } + + let mut lost_sats = processor.get_lost_sats()?; + let cursed_inscription_count = processor.get_cursed_inscription_count()?; + let blessed_inscription_count = processor.get_blessed_inscription_count()?; + let unbound_inscriptions = processor.get_unbound_inscriptions()?; + let next_sequence_number = processor.next_sequence_number()?; + + // let processor = &mut self.processor; + let mut inscription_updater = PendingUpdater::new( + operations, + blessed_inscription_count, + self.internal_index.options.chain(), + cursed_inscription_count, + height, + self.internal_index.index_transactions, + next_sequence_number, + lost_sats, + block.header.time, + unbound_inscriptions, + tx_out_receiver, + tx_out_cache, + processor, + )?; + + let index_sats = true; + if index_sats { + let mut coinbase_inputs = VecDeque::new(); + + let h = Height(height); + if h.subsidy() > 0 { + let start = h.starting_sat(); + coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); + } + + for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { + log::trace!("Indexing transaction {tx_offset}…"); + + let mut input_sat_ranges = VecDeque::new(); + + self.index_transaction_sats( + tx, + *txid, + &mut input_sat_ranges, + &mut sat_ranges_written, + &mut outputs_in_block, + &mut inscription_updater, + index_inscriptions, + )?; + + coinbase_inputs.extend(input_sat_ranges); + } + + if let Some((tx, txid)) = block.txdata.first() { + self.index_transaction_sats( + tx, + *txid, + &mut coinbase_inputs, + &mut sat_ranges_written, + &mut outputs_in_block, + &mut inscription_updater, + index_inscriptions, + )?; + } + + if !coinbase_inputs.is_empty() { + let mut lost_sat_ranges = processor.outpoint_to_sat_ranges_remove(&OutPoint::null().store())?.map(|ranges| ranges.to_vec()) + .unwrap_or_default(); + + for (start, end) in coinbase_inputs { + if !Sat(start).common() { + processor.sat_to_satpoint_insert( + &start, + &SatPoint { + outpoint: OutPoint::null(), + offset: lost_sats, + } + .store(), + )?; + } + + lost_sat_ranges.extend_from_slice(&(start, end).store()); + + lost_sats += end - start; + } + processor.outpoint_to_sat_ranges_insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; + } + } else if index_inscriptions { + for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { + inscription_updater.index_envelopes(tx, *txid, None)?; + } + } + inscription_updater.flush_cache()?; + + // // TODO: + // let mut context = processor.create_context()?; + // // // Create a protocol manager to index the block of bitmap data. + // let config = ProtocolConfig::new_with_options(&index.options); + // ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; + + Ok(()) + } + + + fn index_and_execute(&self) {} + fn index_transaction_sats( + &mut self, + tx: &Transaction, + txid: Txid, + input_sat_ranges: &mut VecDeque<(u64, u64)>, + sat_ranges_written: &mut u64, + outputs_traversed: &mut u64, + inscription_updater: &mut PendingUpdater, + index_inscriptions: bool, + ) -> crate::Result { + if index_inscriptions { + inscription_updater.index_envelopes(tx, txid, Some(input_sat_ranges))?; + } + + for (vout, output) in tx.output.iter().enumerate() { + let outpoint = OutPoint { + vout: vout.try_into().unwrap(), + txid, + }; + let mut sats = Vec::new(); + + let mut remaining = output.value; + while remaining > 0 { + let range = input_sat_ranges + .pop_front() + .ok_or_else(|| anyhow!("insufficient inputs for transaction outputs"))?; + + if !Sat(range.0).common() { + inscription_updater.processor.sat_to_satpoint_insert( + &range.0, + &SatPoint { + outpoint, + offset: 0, + } + .store(), + )?; + } + + let count = range.1 - range.0; + + let assigned = if count > remaining { + let middle = range.0 + remaining; + input_sat_ranges.push_front((middle, range.1)); + (range.0, middle) + } else { + range + }; + + sats.extend_from_slice(&assigned.store()); + + remaining -= assigned.1 - assigned.0; + + *sat_ranges_written += 1; + } + + *outputs_traversed += 1; + } + + Ok(()) + } +} + +#[test] +pub fn test_simulate() { + let internal = Arc::new(Index::open(&Default::default()).unwrap()); + let sim = Simulator { + options: Default::default(), + // simulate_index: IndexTracer {}, + internal_index: internal.clone(), + _marker_a: Default::default(), + _marker_b: Default::default(), + _marker_tx: Default::default(), + }; + let simulate_index = Index::open(&Options { + index: Some(PathBuf::from("./simulate")), + index_runes: false, + index_sats: true, + index_transactions: true, + regtest: true, + enable_index_brc20: true, + ..Default::default() + }).unwrap(); + let mut wtx = simulate_index.begin_write().unwrap(); + + let mut home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS).unwrap(); + let mut inscription_id_to_sequence_number = + wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); + let mut inscription_number_to_sequence_number = + wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER).unwrap(); + let mut sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); + let mut satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); + let mut sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); + let mut sequence_number_to_inscription_entry = + wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(); + let mut sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); + let mut transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); + let mut outpoint_to_entry = wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(); + + let processor = StorageProcessor { + internal: internal.clone(), + // wtx: &mut wtx, + home_inscriptions: &mut home_inscriptions, + id_to_sequence_number: &mut inscription_id_to_sequence_number, + inscription_number_to_sequence_number: &mut inscription_number_to_sequence_number, + outpoint_to_entry: &mut outpoint_to_entry, + transaction_id_to_transaction: &mut transaction_id_to_transaction, + sat_to_sequence_number: &mut sat_to_sequence_number, + satpoint_to_sequence_number: &mut satpoint_to_sequence_number, + sequence_number_to_children: &mut sequence_number_to_children, + sequence_number_to_entry: &mut sequence_number_to_inscription_entry, + sequence_number_to_satpoint: &mut sequence_number_to_satpoint, + }; +} \ No newline at end of file diff --git a/src/index/updater.rs b/src/index/updater.rs index 5dd7cd840b..b1d4cd72f2 100644 --- a/src/index/updater.rs +++ b/src/index/updater.rs @@ -13,6 +13,7 @@ use crate::okx::lru::SimpleLru; mod rune_updater; pub mod pending_updater; +mod pending2; pub(crate) struct BlockData { pub(crate) header: Header, diff --git a/src/index/updater/pending2.rs b/src/index/updater/pending2.rs new file mode 100644 index 0000000000..b111d1067c --- /dev/null +++ b/src/index/updater/pending2.rs @@ -0,0 +1,496 @@ +// use std::collections::{BTreeMap, HashSet, VecDeque}; +// use anyhow::anyhow; +// use bitcoin::{OutPoint, Transaction, Txid}; +// use bitcoin::consensus::Encodable; +// use crate::height::Height; +// use crate::{Index, InscriptionId, Rarity, Sat, SatPoint, unbound_outpoint}; +// use crate::index::database_processor::DataBaseProcessor; +// use crate::index::entry::Entry; +// use crate::index::InscriptionEntry; +// use crate::index::processor::StorageProcessor; +// use crate::index::updater::inscription_updater::{Curse, Flotsam, Origin}; +// use crate::inscriptions::{Charm, ParsedEnvelope}; +// use crate::okx::datastore::ord::{Action, InscriptionOp}; +// +// pub struct PendingUpdater2<'a, 'db> { +// pub processor: &'a DataBaseProcessor<'a, 'db>, +// pub(super) flotsam: Vec, +// pub(super) lost_sats: u64, +// pub(super) reward: u64, +// } +// +// impl<'a,'db> PendingUpdater2<'a,'db> { +// pub(super) fn index_envelopes( +// &mut self, +// tx: &Transaction, +// txid: Txid, +// input_sat_ranges: Option<&VecDeque<(u64, u64)>>, +// ) -> crate::Result { +// let mut floating_inscriptions = Vec::new(); +// let mut id_counter = 0; +// let mut inscribed_offsets = BTreeMap::new(); +// let jubilant = true; +// let mut total_input_value = 0; +// let total_output_value = tx.output.iter().map(|txout| txout.value).sum::(); +// +// let envelopes = ParsedEnvelope::from_transaction(tx); +// let inscriptions = !envelopes.is_empty(); +// let mut envelopes = envelopes.into_iter().peekable(); +// +// for (input_index, tx_in) in tx.input.iter().enumerate() { +// // skip subsidy since no inscriptions possible +// if tx_in.previous_output.is_null() { +// continue; +// } +// +// // find existing inscriptions on input (transfers of inscriptions) +// +// for (old_satpoint, inscription_id) in self.processor.inscriptions_on_output(&tx_in.previous_output)? { +// let offset = total_input_value + old_satpoint.offset; +// floating_inscriptions.push(Flotsam { +// txid, +// offset, +// inscription_id, +// old_satpoint, +// origin: Origin::Old, +// }); +// +// inscribed_offsets +// .entry(offset) +// .or_insert((inscription_id, 0)) +// .1 += 1; +// } +// +// let offset = total_input_value; +// +// // multi-level cache for UTXO set to get to the input amount +// let current_input_value = self.processor.get_txout_by_outpoint(&tx_in.previous_output)?; +// +// total_input_value += current_input_value; +// +// // go through all inscriptions in this input +// while let Some(inscription) = envelopes.peek() { +// if inscription.input != u32::try_from(input_index).unwrap() { +// break; +// } +// +// let inscription_id = InscriptionId { +// txid, +// index: id_counter, +// }; +// +// let curse = if inscription.payload.unrecognized_even_field { +// Some(Curse::UnrecognizedEvenField) +// } else if inscription.payload.duplicate_field { +// Some(Curse::DuplicateField) +// } else if inscription.payload.incomplete_field { +// Some(Curse::IncompleteField) +// } else if inscription.input != 0 { +// Some(Curse::NotInFirstInput) +// } else if inscription.offset != 0 { +// Some(Curse::NotAtOffsetZero) +// } else if inscription.payload.pointer.is_some() { +// Some(Curse::Pointer) +// } else if inscription.pushnum { +// Some(Curse::Pushnum) +// } else if inscription.stutter { +// Some(Curse::Stutter) +// } else if let Some((id, count)) = inscribed_offsets.get(&offset) { +// if *count > 1 { +// Some(Curse::Reinscription) +// } else { +// let initial_inscription_sequence_number = +// self.processor.id_to_sequence_number_get(id.store())?.unwrap(); +// +// let entry = InscriptionEntry::load(self.processor.sequence_number_to_entry_get(initial_inscription_sequence_number)?.unwrap()); +// +// let initial_inscription_was_cursed_or_vindicated = +// entry.inscription_number < 0 || Charm::Vindicated.is_set(entry.charms); +// +// if initial_inscription_was_cursed_or_vindicated { +// None +// } else { +// Some(Curse::Reinscription) +// } +// } +// } else { +// None +// }; +// +// let unbound = current_input_value == 0 +// || curse == Some(Curse::UnrecognizedEvenField) +// || inscription.payload.unrecognized_even_field; +// +// let offset = inscription +// .payload +// .pointer() +// .filter(|&pointer| pointer < total_output_value) +// .unwrap_or(offset); +// +// floating_inscriptions.push(Flotsam { +// txid, +// inscription_id, +// offset, +// old_satpoint: SatPoint { +// outpoint: tx_in.previous_output, +// offset: 0, +// }, +// origin: Origin::New { +// cursed: curse.is_some() && !jubilant, +// fee: 0, +// hidden: inscription.payload.hidden(), +// parent: inscription.payload.parent(), +// pointer: inscription.payload.pointer(), +// reinscription: inscribed_offsets.get(&offset).is_some(), +// unbound, +// inscription: inscription.payload.clone(), +// vindicated: curse.is_some() && jubilant, +// }, +// }); +// +// inscribed_offsets +// .entry(offset) +// .or_insert((inscription_id, 0)) +// .1 += 1; +// +// envelopes.next(); +// id_counter += 1; +// } +// } +// +// if inscriptions { +// let mut transaction_buffer = vec![]; +// tx.consensus_encode(&mut transaction_buffer) +// .expect("in-memory writers don't error"); +// +// self.processor.transaction_id_to_transaction_insert(&txid.store(), transaction_buffer.as_slice())?; +// } +// +// let potential_parents = floating_inscriptions +// .iter() +// .map(|flotsam| flotsam.inscription_id) +// .collect::>(); +// +// for flotsam in &mut floating_inscriptions { +// if let Flotsam { +// origin: Origin::New { parent, .. }, +// .. +// } = flotsam +// { +// if let Some(purported_parent) = parent { +// if !potential_parents.contains(purported_parent) { +// *parent = None; +// } +// } +// } +// } +// +// // still have to normalize over inscription size +// for flotsam in &mut floating_inscriptions { +// if let Flotsam { +// origin: Origin::New { ref mut fee, .. }, +// .. +// } = flotsam +// { +// *fee = (total_input_value - total_output_value) / u64::from(id_counter); +// } +// } +// +// let is_coinbase = tx +// .input +// .first() +// .map(|tx_in| tx_in.previous_output.is_null()) +// .unwrap_or_default(); +// +// if is_coinbase { +// floating_inscriptions.append(&mut self.flotsam); +// } +// +// floating_inscriptions.sort_by_key(|flotsam| flotsam.offset); +// let mut inscriptions = floating_inscriptions.into_iter().peekable(); +// +// let mut range_to_vout = BTreeMap::new(); +// let mut new_locations = Vec::new(); +// let mut output_value = 0; +// for (vout, tx_out) in tx.output.iter().enumerate() { +// let end = output_value + tx_out.value; +// +// while let Some(flotsam) = inscriptions.peek() { +// if flotsam.offset >= end { +// break; +// } +// +// let new_satpoint = SatPoint { +// outpoint: OutPoint { +// txid, +// vout: vout.try_into().unwrap(), +// }, +// offset: flotsam.offset - output_value, +// }; +// +// new_locations.push((new_satpoint, inscriptions.next().unwrap())); +// } +// +// range_to_vout.insert((output_value, end), vout.try_into().unwrap()); +// +// output_value = end; +// +// self.processor.tx_out_cache_insert(&OutPoint { +// vout: vout.try_into().unwrap(), +// txid, +// }, tx_out.clone())?; +// } +// +// for (new_satpoint, mut flotsam) in new_locations.into_iter() { +// let new_satpoint = match flotsam.origin { +// Origin::New { +// pointer: Some(pointer), +// .. +// } if pointer < output_value => { +// match range_to_vout.iter().find_map(|((start, end), vout)| { +// (pointer >= *start && pointer < *end).then(|| (vout, pointer - start)) +// }) { +// Some((vout, offset)) => { +// flotsam.offset = pointer; +// SatPoint { +// outpoint: OutPoint { txid, vout: *vout }, +// offset, +// } +// } +// _ => new_satpoint, +// } +// } +// _ => new_satpoint, +// }; +// +// self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; +// } +// +// if is_coinbase { +// for flotsam in inscriptions { +// let new_satpoint = SatPoint { +// outpoint: OutPoint::null(), +// offset: self.lost_sats + flotsam.offset - output_value, +// }; +// self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; +// } +// self.lost_sats += self.reward - output_value; +// Ok(()) +// } else { +// self.flotsam.extend(inscriptions.map(|flotsam| Flotsam { +// offset: self.reward + flotsam.offset - output_value, +// ..flotsam +// })); +// self.reward += total_input_value - output_value; +// Ok(()) +// } +// } +// +// fn update_inscription_location( +// &mut self, +// input_sat_ranges: Option<&VecDeque<(u64, u64)>>, +// flotsam: Flotsam, +// new_satpoint: SatPoint, +// ) -> crate::Result { +// let inscription_id = flotsam.inscription_id; +// let (unbound, sequence_number) = match flotsam.origin { +// Origin::Old => { +// self +// .processor.satpoint_to_sequence_number_remove_all(&flotsam.old_satpoint.store())?; +// +// ( +// false, +// self +// .processor.id_to_sequence_number_get( +// inscription_id.store())? +// .unwrap() +// ) +// } +// Origin::New { +// cursed, +// fee, +// hidden, +// parent, +// pointer: _, +// reinscription, +// unbound, +// inscription: _, +// vindicated, +// } => { +// let inscription_number = if cursed { +// let number: i32 = self.cursed_inscription_count.try_into().unwrap(); +// self.cursed_inscription_count += 1; +// +// // because cursed numbers start at -1 +// -(number + 1) +// } else { +// let number: i32 = self.blessed_inscription_count.try_into().unwrap(); +// self.blessed_inscription_count += 1; +// +// number +// }; +// +// let sequence_number = self.next_sequence_number; +// self.next_sequence_number += 1; +// +// self +// .processor.inscription_number_to_sequence_number_insert( +// inscription_number, sequence_number)?; +// +// let sat = if unbound { +// None +// } else { +// Self::calculate_sat(input_sat_ranges, flotsam.offset) +// }; +// +// let mut charms = 0; +// +// if cursed { +// Charm::Cursed.set(&mut charms); +// } +// +// if reinscription { +// Charm::Reinscription.set(&mut charms); +// } +// +// if let Some(sat) = sat { +// if sat.nineball() { +// Charm::Nineball.set(&mut charms); +// } +// +// if sat.coin() { +// Charm::Coin.set(&mut charms); +// } +// +// match sat.rarity() { +// Rarity::Common | Rarity::Mythic => {} +// Rarity::Uncommon => Charm::Uncommon.set(&mut charms), +// Rarity::Rare => Charm::Rare.set(&mut charms), +// Rarity::Epic => Charm::Epic.set(&mut charms), +// Rarity::Legendary => Charm::Legendary.set(&mut charms), +// } +// } +// +// if new_satpoint.outpoint == OutPoint::null() { +// Charm::Lost.set(&mut charms); +// } +// +// if unbound { +// Charm::Unbound.set(&mut charms); +// } +// +// if vindicated { +// Charm::Vindicated.set(&mut charms); +// } +// +// if let Some(Sat(n)) = sat { +// self.processor.sat_to_sequence_number_insert(&n, &sequence_number)?; +// } +// +// let parent = match parent { +// Some(parent_id) => { +// let parent_sequence_number = self +// .processor.id_to_sequence_number_get( +// parent_id.store())? +// .unwrap(); +// self +// .processor.sequence_number_to_children_insert( +// parent_sequence_number, sequence_number)?; +// +// Some(parent_sequence_number) +// } +// None => None, +// }; +// +// self.processor.sequence_number_to_entry_insert( +// sequence_number, +// &InscriptionEntry { +// charms, +// fee, +// height: self.height, +// id: inscription_id, +// inscription_number, +// parent, +// sat, +// sequence_number, +// timestamp: self.timestamp, +// } +// .store(), +// )?; +// +// self +// .processor.id_to_sequence_number_insert( +// &inscription_id.store(), sequence_number)?; +// +// if !hidden { +// self +// .processor.home_inscriptions_insert( +// &sequence_number, inscription_id.store())?; +// +// if self.home_inscription_count == 100 { +// self.processor.home_inscriptions_pop_first()?; +// } else { +// self.home_inscription_count += 1; +// } +// } +// +// (unbound, sequence_number) +// } +// }; +// +// let satpoint = if unbound { +// let new_unbound_satpoint = SatPoint { +// outpoint: unbound_outpoint(), +// offset: self.unbound_inscriptions, +// }; +// self.unbound_inscriptions += 1; +// new_unbound_satpoint.store() +// } else { +// new_satpoint.store() +// }; +// +// self +// .operations +// .entry(flotsam.txid) +// .or_default() +// .push(InscriptionOp { +// txid: flotsam.txid, +// sequence_number, +// inscription_number: self +// .processor.sequence_number_to_entry_get( +// sequence_number)? +// .map(|entry| InscriptionEntry::load(entry).inscription_number), +// inscription_id: flotsam.inscription_id, +// action: match flotsam.origin { +// Origin::Old => Action::Transfer, +// Origin::New { +// cursed, +// fee: _, +// hidden: _, +// parent: _, +// pointer: _, +// reinscription: _, +// unbound, +// inscription, +// vindicated, +// } => Action::New { +// cursed, +// unbound, +// vindicated, +// inscription, +// }, +// }, +// old_satpoint: flotsam.old_satpoint, +// new_satpoint: Some(Entry::load(satpoint)), +// }); +// +// self +// .processor.satpoint_to_sequence_number_insert( +// &satpoint, sequence_number)?; +// self +// .processor.sequence_number_to_satpoint_insert( +// sequence_number, &satpoint)?; +// +// Ok(()) +// } +// } \ No newline at end of file diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index da041510f1..df7be54d57 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -6,8 +6,8 @@ use crate::index::processor::StorageProcessor; use crate::index::updater::inscription_updater::{Flotsam, Origin}; -pub struct PendingUpdater<'a, 'db> { - pub processor: &'a StorageProcessor<'a, 'db>, +pub struct PendingUpdater<'a, 'db, 'tx> { + pub processor: &'a StorageProcessor<'a, 'db, 'tx>, pub(super) operations: &'a mut HashMap>, pub(super) blessed_inscription_count: u64, pub(super) chain: Chain, @@ -27,7 +27,7 @@ pub struct PendingUpdater<'a, 'db> { pub(super) new_outpoints: Vec, } -impl<'db: 'a, 'a> PendingUpdater<'a, 'db> { +impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { pub fn new( operations: &'a mut HashMap>, blessed_inscription_count: u64, @@ -41,7 +41,7 @@ impl<'db: 'a, 'a> PendingUpdater<'a, 'db> { unbound_inscriptions: u64, tx_out_receiver: &'a mut Receiver, tx_out_cache: &'a mut SimpleLru, - processor: &'db StorageProcessor<'a, 'db>, + processor: &'db StorageProcessor<'a, 'db, 'tx>, ) -> Result { let home_inscriptions_len = processor.home_inscriptions_len(); Ok(Self { diff --git a/src/okx/datastore/cache.rs b/src/okx/datastore/cache.rs index 94cf792444..5c4c8816eb 100644 --- a/src/okx/datastore/cache.rs +++ b/src/okx/datastore/cache.rs @@ -38,19 +38,17 @@ pub struct CacheTable { pub data: HashMap, Vec>, } -impl CacheTable{ +impl CacheTable { pub fn insert(&mut self, key: Vec, value: Vec) { self.data.insert(key, value); } - pub fn pop_first(&mut self){ - - } - pub fn get(&self, key:Vec) -> Option> { - self.data.get(&key).map_or(None,|v|{ + pub fn pop_first(&mut self) {} + pub fn get(&self, key: Vec) -> Option> { + self.data.get(&key).map_or(None, |v| { Some(v.clone()) }) } - pub fn remove(&mut self,key:Vec){ + pub fn remove(&mut self, key: Vec) { self.data.remove(&key); } } @@ -58,7 +56,7 @@ impl CacheTable{ #[derive(Clone)] pub struct CacheWriter { cache: Rc>>, - pub index: Arc, + pub internal_index: Arc, } @@ -92,6 +90,9 @@ impl CacheWriter { ret } pub fn get_index(&self) -> Arc { - self.index.clone() + self.internal_index.clone() + } + pub fn new(internal_index: Arc) -> Self { + Self { cache: Default::default(), internal_index } } } \ No newline at end of file From 2bfa5964f3d1ad1f91a0fa0b59435e7502488969 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 11 Jan 2024 21:47:57 +0800 Subject: [PATCH 12/66] save --- src/index/processor.rs | 24 +++++++++++++++--------- src/index/simulate.rs | 8 +++++--- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/index/processor.rs b/src/index/processor.rs index 82b1956de9..79809f9384 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -206,6 +206,8 @@ ////////////////// +use std::cell::RefCell; +use std::rc::Rc; use std::sync::Arc; use bitcoin::{OutPoint, TxOut}; use redb::{MultimapTable, RedbValue, Table, WriteTransaction}; @@ -220,10 +222,10 @@ pub struct StorageProcessor<'a, 'db, 'tx> { // pub wtx: &'a mut WriteTransaction<'db>, - pub(super) home_inscriptions: &'a mut Table<'db, 'tx, u32, InscriptionIdValue>, + pub(super) home_inscriptions: Rc>>, pub(super) id_to_sequence_number: &'a mut Table<'db, 'tx, InscriptionIdValue, u32>, pub(super) inscription_number_to_sequence_number: &'a mut Table<'db, 'tx, i32, u32>, - pub(super) outpoint_to_entry: &'a mut Table<'db, 'tx, &'static OutPointValue, &'static [u8]>, + pub(super) outpoint_to_entry: Rc>>, pub(super) transaction_id_to_transaction: &'a mut Table<'db, 'tx, &'static TxidValue, &'static [u8]>, pub(super) sat_to_sequence_number: &'a mut MultimapTable<'db, 'tx, u64, u32>, @@ -231,7 +233,7 @@ pub struct StorageProcessor<'a, 'db, 'tx> { &'a mut MultimapTable<'db, 'tx, &'static SatPointValue, u32>, pub(super) sequence_number_to_children: &'a mut MultimapTable<'db, 'tx, u32, u32>, pub(super) sequence_number_to_entry: &'a mut Table<'db, 'tx, u32, InscriptionEntryValue>, - pub(super) sequence_number_to_satpoint: &'a mut Table<'db, 'tx, u32, &'static SatPointValue>, + pub(super) sequence_number_to_satpoint: Rc>>, } unsafe impl<'a, 'db, 'tx> Send for StorageProcessor<'a, 'db, 'tx> {} @@ -284,7 +286,8 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { todo!() } pub(crate) fn sequence_number_to_satpoint_insert(&self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { - self.sequence_number_to_satpoint.insert(sequence_number, sat_point)?; + let mut table = self.sequence_number_to_satpoint.borrow_mut(); + table.insert(sequence_number, sat_point)?; // let key = u32::as_bytes(&sequence_number).to_vec(); // let value = sat_point.to_vec(); @@ -294,7 +297,8 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { Ok(()) } pub(crate) fn satpoint_to_sequence_number_insert(&self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { - self.sequence_number_to_satpoint.insert(sequence, sat_point)?; + let mut table = self.sequence_number_to_satpoint.borrow_mut(); + table.insert(sequence, sat_point)?; // let key = sat_point.to_vec(); // let value = u32::as_bytes(&sequence).to_vec(); @@ -304,7 +308,8 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { Ok(()) } pub(crate) fn home_inscriptions_pop_first(&self) -> crate::Result<()> { - self.home_inscriptions.pop_first()?; + let mut table = self.home_inscriptions.borrow_mut(); + table.pop_first()?; // self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { // v.pop_first() @@ -319,8 +324,8 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // }); // Ok(()) - self - .home_inscriptions + let mut table = self.home_inscriptions.borrow_mut(); + table .insert(sequence_number, value)?; Ok(()) } @@ -381,7 +386,8 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { Ok(()) } pub(crate) fn outpoint_to_entry_insert(&self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { - self.outpoint_to_entry.insert(value, entry)?; + let mut table=self.outpoint_to_entry.borrow_mut(); + table.insert(value, entry)?; Ok(()) // let key = rmp_serde::to_vec(value).unwrap(); // let value = entry.to_vec(); diff --git a/src/index/simulate.rs b/src/index/simulate.rs index ab7f8348f9..29bbf6671c 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -1,6 +1,8 @@ +use std::cell::RefCell; use std::collections::{HashMap, HashSet, VecDeque}; use std::marker::PhantomData; use std::path::PathBuf; +use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Instant; @@ -597,15 +599,15 @@ pub fn test_simulate() { let processor = StorageProcessor { internal: internal.clone(), // wtx: &mut wtx, - home_inscriptions: &mut home_inscriptions, + home_inscriptions: Rc::new(RefCell::new(&mut home_inscriptions)), id_to_sequence_number: &mut inscription_id_to_sequence_number, inscription_number_to_sequence_number: &mut inscription_number_to_sequence_number, - outpoint_to_entry: &mut outpoint_to_entry, + outpoint_to_entry: Rc::new(RefCell::new(&mut outpoint_to_entry)), transaction_id_to_transaction: &mut transaction_id_to_transaction, sat_to_sequence_number: &mut sat_to_sequence_number, satpoint_to_sequence_number: &mut satpoint_to_sequence_number, sequence_number_to_children: &mut sequence_number_to_children, sequence_number_to_entry: &mut sequence_number_to_inscription_entry, - sequence_number_to_satpoint: &mut sequence_number_to_satpoint, + sequence_number_to_satpoint: Rc::new(RefCell::new(&mut sequence_number_to_satpoint)), }; } \ No newline at end of file From 9f310f7b69c3ddfe373e3496b32d5bc7ec297900 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 11 Jan 2024 21:57:29 +0800 Subject: [PATCH 13/66] fuck --- src/index/processor.rs | 24 +++++++++++++----------- src/index/simulate.rs | 23 ++++++++++++----------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/index/processor.rs b/src/index/processor.rs index 79809f9384..dfb2497ccc 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -207,6 +207,7 @@ use std::cell::RefCell; +use std::marker::PhantomData; use std::rc::Rc; use std::sync::Arc; use bitcoin::{OutPoint, TxOut}; @@ -222,18 +223,19 @@ pub struct StorageProcessor<'a, 'db, 'tx> { // pub wtx: &'a mut WriteTransaction<'db>, - pub(super) home_inscriptions: Rc>>, - pub(super) id_to_sequence_number: &'a mut Table<'db, 'tx, InscriptionIdValue, u32>, - pub(super) inscription_number_to_sequence_number: &'a mut Table<'db, 'tx, i32, u32>, - pub(super) outpoint_to_entry: Rc>>, + pub(super) home_inscriptions: Rc>>, + pub(super) id_to_sequence_number: Rc>>, + pub(super) inscription_number_to_sequence_number: Rc>>, + pub(super) outpoint_to_entry: Rc>>, pub(super) transaction_id_to_transaction: - &'a mut Table<'db, 'tx, &'static TxidValue, &'static [u8]>, - pub(super) sat_to_sequence_number: &'a mut MultimapTable<'db, 'tx, u64, u32>, + Rc>>, + pub(super) sat_to_sequence_number: Rc>>, pub(super) satpoint_to_sequence_number: - &'a mut MultimapTable<'db, 'tx, &'static SatPointValue, u32>, - pub(super) sequence_number_to_children: &'a mut MultimapTable<'db, 'tx, u32, u32>, - pub(super) sequence_number_to_entry: &'a mut Table<'db, 'tx, u32, InscriptionEntryValue>, - pub(super) sequence_number_to_satpoint: Rc>>, + Rc>>, + pub(super) sequence_number_to_children: Rc>>, + pub(super) sequence_number_to_entry: Rc>>, + pub(super) sequence_number_to_satpoint: Rc>>, + pub _marker_a: PhantomData<&'a ()>, } unsafe impl<'a, 'db, 'tx> Send for StorageProcessor<'a, 'db, 'tx> {} @@ -386,7 +388,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { Ok(()) } pub(crate) fn outpoint_to_entry_insert(&self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { - let mut table=self.outpoint_to_entry.borrow_mut(); + let mut table = self.outpoint_to_entry.borrow_mut(); table.insert(value, entry)?; Ok(()) // let key = rmp_serde::to_vec(value).unwrap(); diff --git a/src/index/simulate.rs b/src/index/simulate.rs index 29bbf6671c..e76996b08c 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -8,7 +8,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Instant; use anyhow::anyhow; use bitcoin::{OutPoint, Transaction, Txid, TxOut}; -use redb::{ReadableTable, Table, WriteTransaction}; +use redb::{ReadableTable}; use tokio::sync::mpsc::{Receiver, Sender}; use tokio::sync::mpsc::error::TryRecvError; use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; @@ -599,15 +599,16 @@ pub fn test_simulate() { let processor = StorageProcessor { internal: internal.clone(), // wtx: &mut wtx, - home_inscriptions: Rc::new(RefCell::new(&mut home_inscriptions)), - id_to_sequence_number: &mut inscription_id_to_sequence_number, - inscription_number_to_sequence_number: &mut inscription_number_to_sequence_number, - outpoint_to_entry: Rc::new(RefCell::new(&mut outpoint_to_entry)), - transaction_id_to_transaction: &mut transaction_id_to_transaction, - sat_to_sequence_number: &mut sat_to_sequence_number, - satpoint_to_sequence_number: &mut satpoint_to_sequence_number, - sequence_number_to_children: &mut sequence_number_to_children, - sequence_number_to_entry: &mut sequence_number_to_inscription_entry, - sequence_number_to_satpoint: Rc::new(RefCell::new(&mut sequence_number_to_satpoint)), + home_inscriptions: Rc::new(RefCell::new(home_inscriptions)), + id_to_sequence_number: Rc::new(RefCell::new(inscription_id_to_sequence_number)), + inscription_number_to_sequence_number: Rc::new(RefCell::new(inscription_number_to_sequence_number)), + outpoint_to_entry: Rc::new(RefCell::new(outpoint_to_entry)), + transaction_id_to_transaction: Rc::new(RefCell::new(transaction_id_to_transaction)), + sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), + satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), + sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), + sequence_number_to_entry: Rc::new(RefCell::new(sequence_number_to_inscription_entry)), + sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), + _marker_a: Default::default(), }; } \ No newline at end of file From 78344dc6307d62510b5cce9a990a2a9ea110b0f7 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 08:43:23 +0800 Subject: [PATCH 14/66] fk3 --- src/index/processor.rs | 5 + src/index/simulate.rs | 11 +- src/index/updater/pending_updater.rs | 4 +- src/okx/protocol/mod.rs | 2 +- src/okx/protocol/simulate.rs | 1552 ++++++++++++++++---------- 5 files changed, 985 insertions(+), 589 deletions(-) diff --git a/src/index/processor.rs b/src/index/processor.rs index dfb2497ccc..31c90cfb4b 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -217,7 +217,9 @@ use crate::index::entry::SatPointValue; use crate::index::{InscriptionEntryValue, InscriptionIdValue, OutPointValue, TxidValue}; use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; use crate::okx::protocol::context::Context; +use crate::okx::protocol::simulate::SimulateContext; +#[derive(Clone)] pub struct StorageProcessor<'a, 'db, 'tx> { pub internal: Arc, @@ -247,6 +249,9 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { pub(crate) fn create_context(&self) -> crate::Result { todo!() } + pub(crate) fn create_simulate_context(&self) -> crate::Result { + todo!() + } pub(crate) fn next_sequence_number(&self) -> crate::Result { todo!() } diff --git a/src/index/simulate.rs b/src/index/simulate.rs index e76996b08c..d017e17b39 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -327,11 +327,12 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { fn index_block( &mut self, height: u32, + index:Index, outpoint_sender: &'a mut Sender, tx_out_receiver: &'a mut Receiver, block: BlockData, tx_out_cache: &'a mut SimpleLru, - processor: &'db mut StorageProcessor<'a, 'db, 'tx>, + processor:StorageProcessor<'a, 'db, 'tx>, operations: &'db mut HashMap>, ) -> crate::Result<()> { let start = Instant::now(); @@ -415,7 +416,7 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { unbound_inscriptions, tx_out_receiver, tx_out_cache, - processor, + processor.clone(), )?; let index_sats = true; @@ -488,10 +489,10 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { inscription_updater.flush_cache()?; // // TODO: - // let mut context = processor.create_context()?; + let mut context = processor.create_context()?; // // // Create a protocol manager to index the block of bitmap data. - // let config = ProtocolConfig::new_with_options(&index.options); - // ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; + let config = ProtocolConfig::new_with_options(&index.options); + ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; Ok(()) } diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index df7be54d57..a51b93fafa 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -7,7 +7,7 @@ use crate::index::updater::inscription_updater::{Flotsam, Origin}; pub struct PendingUpdater<'a, 'db, 'tx> { - pub processor: &'a StorageProcessor<'a, 'db, 'tx>, + pub processor: StorageProcessor<'a, 'db, 'tx>, pub(super) operations: &'a mut HashMap>, pub(super) blessed_inscription_count: u64, pub(super) chain: Chain, @@ -41,7 +41,7 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { unbound_inscriptions: u64, tx_out_receiver: &'a mut Receiver, tx_out_cache: &'a mut SimpleLru, - processor: &'db StorageProcessor<'a, 'db, 'tx>, + processor: StorageProcessor<'a, 'db, 'tx>, ) -> Result { let home_inscriptions_len = processor.home_inscriptions_len(); Ok(Self { diff --git a/src/okx/protocol/mod.rs b/src/okx/protocol/mod.rs index b8998f0670..90bfe1a17d 100644 --- a/src/okx/protocol/mod.rs +++ b/src/okx/protocol/mod.rs @@ -5,7 +5,7 @@ pub(crate) mod message; pub(crate) mod ord; pub(crate) mod protocol_manager; pub(crate) mod resolve_manager; -mod simulate; +pub mod simulate; pub mod trace; use redb::ReadableTable; diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index 9c07ad20e7..01b74a03e5 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -1,95 +1,526 @@ -use std::collections::HashMap; -use std::sync::Arc; -use bitcoin::{OutPoint, Txid, TxOut}; -use redb::{Database, ReadableTable, ReadOnlyTable, ReadTransaction, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; -use tempfile::NamedTempFile; -use crate::{Index, InscriptionId}; -use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionIdValue, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; -use crate::index::entry::Entry; -use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; -use crate::okx::datastore::brc20::redb::{script_tick_id_key, script_tick_key}; -use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick}; -use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; -use crate::okx::datastore::ScriptKey; -use crate::okx::protocol::trace::{BalanceDelta, IndexTracer, MintTokenInfoDelta, string_to_bytes, TraceNode}; - -pub struct SimulateContext { - simulate: CacheWriter, - internal_index: Arc, -} - -impl SimulateContext { - // pub fn new( - // internal_index: Arc, simulate: Context) -> crate::Result { - // // let mut simulate_tx = simulate_index.begin_write()?; - // // let ctx = Context { - // // chain, - // // tx_out_cache, - // // hit: 0, - // // miss: 0, - // // ORD_TX_TO_OPERATIONS: &mut simulate_tx.open_table(ORD_TX_TO_OPERATIONS)?, - // // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut simulate_tx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, - // // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut simulate_tx.open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, - // // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut simulate_tx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?, - // // OUTPOINT_TO_ENTRY: &mut simulate_tx.open_table(OUTPOINT_TO_ENTRY)?, - // // BRC20_BALANCES: &mut simulate_tx.open_table(BRC20_BALANCES)?, - // // BRC20_TOKEN: &mut simulate_tx.open_table(BRC20_TOKEN)?, - // // BRC20_EVENTS: &mut simulate_tx.open_table(BRC20_EVENTS)?, - // // BRC20_TRANSFERABLELOG: &mut simulate_tx.open_table(BRC20_TRANSFERABLELOG)?, - // // BRC20_INSCRIBE_TRANSFER: &mut simulate_tx.open_table(BRC20_INSCRIBE_TRANSFER)?, - // // }; - // Ok(Self { - // // simulate: ctx, - // internal_index, - // simulate, - // }) - // } - pub fn new(simulate: CacheWriter, internal_index: Arc) -> Self { - Self { simulate, internal_index } - } -} - -impl SimulateContext { - fn use_internal_table(&self, - table_def: TableDefinition, - f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { - let rtx = self.internal_index.begin_read()?; - let table = rtx.0.open_table(table_def)?; - let ret = f(table); - ret - } -} - +// use std::collections::HashMap; +// use std::sync::Arc; +// use bitcoin::{OutPoint, Txid, TxOut}; +// use redb::{Database, ReadableTable, ReadOnlyTable, ReadTransaction, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; +// use tempfile::NamedTempFile; +// use crate::{Index, InscriptionId}; +// use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionIdValue, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; +// use crate::index::entry::Entry; +// use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; +// use crate::okx::datastore::brc20::redb::{script_tick_id_key, script_tick_key}; +// use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick}; +// use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; +// use crate::okx::datastore::ScriptKey; +// use crate::okx::protocol::trace::{BalanceDelta, IndexTracer, MintTokenInfoDelta, string_to_bytes, TraceNode}; +// +// pub struct SimulateContext { +// simulate: CacheWriter, +// internal_index: Arc, +// } +// +// impl SimulateContext { +// // pub fn new( +// // internal_index: Arc, simulate: Context) -> crate::Result { +// // // let mut simulate_tx = simulate_index.begin_write()?; +// // // let ctx = Context { +// // // chain, +// // // tx_out_cache, +// // // hit: 0, +// // // miss: 0, +// // // ORD_TX_TO_OPERATIONS: &mut simulate_tx.open_table(ORD_TX_TO_OPERATIONS)?, +// // // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut simulate_tx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, +// // // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut simulate_tx.open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, +// // // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut simulate_tx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?, +// // // OUTPOINT_TO_ENTRY: &mut simulate_tx.open_table(OUTPOINT_TO_ENTRY)?, +// // // BRC20_BALANCES: &mut simulate_tx.open_table(BRC20_BALANCES)?, +// // // BRC20_TOKEN: &mut simulate_tx.open_table(BRC20_TOKEN)?, +// // // BRC20_EVENTS: &mut simulate_tx.open_table(BRC20_EVENTS)?, +// // // BRC20_TRANSFERABLELOG: &mut simulate_tx.open_table(BRC20_TRANSFERABLELOG)?, +// // // BRC20_INSCRIBE_TRANSFER: &mut simulate_tx.open_table(BRC20_INSCRIBE_TRANSFER)?, +// // // }; +// // Ok(Self { +// // // simulate: ctx, +// // internal_index, +// // simulate, +// // }) +// // } +// pub fn new(simulate: CacheWriter, internal_index: Arc) -> Self { +// Self { simulate, internal_index } +// } +// } +// +// impl SimulateContext { +// fn use_internal_table(&self, +// table_def: TableDefinition, +// f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { +// let rtx = self.internal_index.begin_read()?; +// let table = rtx.0.open_table(table_def)?; +// let ret = f(table); +// ret +// } +// } +// +// // impl Brc20Reader for SimulateContext { +// // type Error = anyhow::Error; +// // +// // fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { +// // let simulate = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { +// // get_balances(&table, script_key) +// // })?; +// // let mut simulate_balances: HashMap = simulate.into_iter() +// // .map(|v| { +// // (v.tick.clone(), v.clone()) +// // }).collect(); +// // let internal = self.use_internal_table(BRC20_BALANCES, |v| { +// // get_balances(&v, script_key) +// // })?; +// // for node in internal { +// // let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); +// // v.transferable_balance = v.transferable_balance + node.transferable_balance; +// // v.overall_balance = v.overall_balance + node.overall_balance; +// // } +// // let ret = simulate_balances +// // .into_iter() +// // .map(|(k, v)| { +// // v.clone() +// // }).collect(); +// // Ok(ret) +// // } +// // +// // fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { +// // let ret = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { +// // get_balance(&table, script_key, tick) +// // })?; +// // if let Some(ret) = ret { +// // return Ok(Some(ret)); +// // } +// // self.use_internal_table(BRC20_BALANCES, |table| { +// // get_balance(&table, script_key, tick) +// // }) +// // } +// // +// // fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { +// // let ret = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { +// // get_token_info(&table, tick) +// // })?; +// // if let Some(ret) = ret { +// // return Ok(Some(ret)); +// // } +// // self.use_internal_table(BRC20_TOKEN, |table| { +// // get_token_info(&table, tick) +// // }) +// // } +// // +// // fn get_tokens_info(&self) -> crate::Result, Self::Error> { +// // let simulate = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { +// // get_tokens_info(&table) +// // })?; +// // let internal = self.use_internal_table(BRC20_TOKEN, |table| { +// // get_tokens_info(&table) +// // })?; +// // // TODO:merge +// // todo!() +// // } +// // +// // fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { +// // let simulate = self.simulate_index.use_read_table(BRC20_EVENTS, |table| { +// // get_transaction_receipts(&table, txid) +// // })?; +// // let internal = self.use_internal_table(BRC20_EVENTS, |table| { +// // get_transaction_receipts(&table, txid) +// // })?; +// // // TODO:merge +// // todo!() +// // } +// // +// // fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { +// // let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable(&table, script) +// // })?; +// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable(&table, script) +// // })?; +// // // TODO: merge +// // todo!() +// // } +// // +// // +// // fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { +// // let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable_by_tick(&table, script, tick) +// // })?; +// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable_by_tick(&table, script, tick) +// // })?; +// // // TODO:merge +// // todo!() +// // } +// // +// // fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { +// // let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable_by_id(&table, script, inscription_id) +// // })?; +// // if let Some(ret) = simulate { +// // return Ok(Some(ret)); +// // } +// // self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable_by_id(&table, script, inscription_id) +// // }) +// // } +// // +// // fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { +// // let simulate = self.simulate_index.use_read_table(BRC20_INSCRIBE_TRANSFER, |table| { +// // get_inscribe_transfer_inscription(&table, inscription_id) +// // })?; +// // if let Some(ret) = simulate { +// // return Ok(Some(ret)); +// // } +// // self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { +// // get_inscribe_transfer_inscription(&table, inscription_id) +// // }) +// // } +// // } +// // +// // impl Brc20ReaderWriter for SimulateContext { +// // fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { +// // self.simulate_index +// // .use_write_table(BRC20_BALANCES, |mut table| { +// // let binding = script_tick_key(script_key, &new_balance.tick); +// // let key = binding.as_str(); +// // let binding = rmp_serde::to_vec(&new_balance).unwrap(); +// // let value = binding.as_slice(); +// // // let origin = table.get(key)?.map_or(None, |v| { +// // // Some(v.value().to_vec()) +// // // }); +// // table.insert(key, value)?; +// // // let mut delta = BalanceDelta::default(); +// // // if let Some(origin) = origin { +// // // let origin: Balance = rmp_serde::from_slice(&origin).unwrap(); +// // // delta.origin_transferable_balance_delta = origin.transferable_balance; +// // // delta.origin_overall_balance_delta = origin.overall_balance; +// // // delta.new_overall_balance_delta = new_balance.overall_balance; +// // // delta.new_transferable_balance_delta = new_balance.transferable_balance; +// // // } else { +// // // delta.origin_transferable_balance_delta = 0; +// // // delta.origin_overall_balance_delta = 0; +// // // delta.new_overall_balance_delta = new_balance.overall_balance; +// // // delta.new_transferable_balance_delta = new_balance.transferable_balance; +// // // } +// // // let op = TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()); +// // let node = TraceNode { trace_type: CacheTableIndex::BRC20_BALANCES, key: string_to_bytes(key) }; +// // Ok(((), node)) +// // })?; +// // Ok(()) +// // } +// // +// // fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { +// // self.simulate_index +// // .use_write_table(BRC20_TOKEN, |mut table| { +// // let binding = tick.to_lowercase().hex(); +// // let key = binding.as_str(); +// // let binding = rmp_serde::to_vec(new_info).unwrap(); +// // let value = binding.as_slice(); +// // table.insert(key, value)?; +// // +// // let trace = TraceNode { +// // trace_type: CacheTableIndex::BRC20_TOKEN, +// // // operation: TraceOperation::Insert, +// // key: string_to_bytes(key), +// // }; +// // Ok(((), trace)) +// // })?; +// // Ok(()) +// // } +// // +// // +// // fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { +// // let mut info = self.get_token_info(tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); +// // let origin = info.minted; +// // info.minted = minted_amt; +// // info.latest_mint_number = minted_block_number; +// // self.simulate_index +// // .use_write_table(BRC20_TOKEN, |mut table| { +// // let binding = tick.to_lowercase().hex(); +// // let key = binding.as_str(); +// // let binding = rmp_serde::to_vec(&info).unwrap(); +// // let value = binding.as_slice(); +// // table.insert(key, value)?; +// // // let delta = MintTokenInfoDelta { +// // // origin_minted: origin, +// // // new_minted: info.minted, +// // // new_latest_mint_number: minted_block_number, +// // // }; +// // let trace = TraceNode { +// // trace_type: CacheTableIndex::BRC20_TOKEN, +// // // operation: TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()), +// // key: string_to_bytes(key), +// // }; +// // Ok(((), trace)) +// // })?; +// // Ok(()) +// // } +// // +// // fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { +// // self.simulate_index +// // .use_write_table(BRC20_EVENTS, |mut table| { +// // let tx_id_value = txid.store(); +// // let key = tx_id_value.to_vec(); +// // let binding = rmp_serde::to_vec(receipt).unwrap(); +// // let value = binding.as_slice(); +// // table.insert(&txid.store(), value)?; +// // let trace = TraceNode { +// // trace_type: CacheTableIndex::BRC20_EVENTS, +// // key, +// // }; +// // Ok(((), trace)) +// // })?; +// // Ok(()) +// // // self.simulate.save_transaction_receipts(txid, receipt) +// // } +// // +// // fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { +// // self.simulate_index +// // .use_write_table(BRC20_TRANSFERABLELOG, |mut table| { +// // let binding = script_tick_id_key(script, tick, &inscription.inscription_id); +// // let key = binding.as_str(); +// // let binding = rmp_serde::to_vec(inscription).unwrap(); +// // let value = binding.as_slice(); +// // table.insert(key, value)?; +// // let trace = TraceNode { +// // trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, +// // key: string_to_bytes(key), +// // }; +// // Ok(((), trace)) +// // })?; +// // Ok(()) +// // } +// // +// // fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { +// // self.simulate_index.use_write_table(BRC20_TRANSFERABLELOG, |mut table| { +// // let binding = script_tick_id_key(script, tick, inscription_id); +// // let key = binding.as_str(); +// // table.remove(key)?; +// // let trace = TraceNode { +// // trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, +// // key: string_to_bytes(key), +// // }; +// // Ok(((), trace)) +// // })?; +// // Ok(()) +// // } +// // +// // fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { +// // self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { +// // let key = inscription_id.store(); +// // let key_bytes = InscriptionIdValue::as_bytes(&key); +// // let binding = rmp_serde::to_vec(&transfer_info).unwrap(); +// // let value = binding.as_slice(); +// // table.insert(&key, value)?; +// // let trace = TraceNode { +// // trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, +// // key: key_bytes, +// // }; +// // Ok(((), trace)) +// // })?; +// // Ok(()) +// // } +// // +// // fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { +// // self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { +// // let key = inscription_id.store(); +// // let key_bytes = InscriptionIdValue::as_bytes(&key); +// // table.remove(&key)?; +// // let trace = TraceNode { +// // trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, +// // key: key_bytes, +// // }; +// // Ok(((), trace)) +// // })?; +// // Ok(()) +// // } +// // } +// +// // impl Brc20Reader for SimulateContext { +// // type Error = anyhow::Error; +// // +// // fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { +// // let simulate = self.simulate.get_balances(script_key)?; +// // let mut simulate_balances: HashMap = simulate.into_iter() +// // .map(|v| { +// // (v.tick.clone(), v.clone()) +// // }).collect(); +// // let internal = self.use_internal_table(BRC20_BALANCES, |v| { +// // get_balances(&v, script_key) +// // })?; +// // for node in internal { +// // let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); +// // v.transferable_balance = v.transferable_balance + node.transferable_balance; +// // v.overall_balance = v.overall_balance + node.overall_balance; +// // } +// // let ret = simulate_balances +// // .into_iter() +// // .map(|(k, v)| { +// // v.clone() +// // }).collect(); +// // Ok(ret) +// // } +// // +// // fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { +// // let ret = self.simulate.get_balance(script_key, tick)?; +// // if let Some(ret) = ret { +// // return Ok(Some(ret)); +// // } +// // self.use_internal_table(BRC20_BALANCES, |table| { +// // get_balance(&table, script_key, tick) +// // }) +// // } +// // +// // fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { +// // let ret = self.simulate.get_token_info(tick)?; +// // if let Some(ret) = ret { +// // return Ok(Some(ret)); +// // } +// // self.use_internal_table(BRC20_TOKEN, |table| { +// // get_token_info(&table, tick) +// // }) +// // } +// // +// // fn get_tokens_info(&self) -> crate::Result, Self::Error> { +// // let simulate = self.simulate.get_tokens_info()?; +// // let internal = self.use_internal_table(BRC20_TOKEN, |table| { +// // get_tokens_info(&table) +// // })?; +// // // TODO:merge +// // todo!() +// // } +// // +// // fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { +// // let simulate = self.simulate.get_transaction_receipts(txid)?; +// // let internal = self.use_internal_table(BRC20_EVENTS, |table| { +// // get_transaction_receipts(&table, txid) +// // })?; +// // // TODO:merge +// // todo!() +// // } +// // +// // fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { +// // let simulate = self.simulate.get_transferable(script)?; +// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable(&table, script) +// // })?; +// // // TODO: merge +// // todo!() +// // } +// // +// // +// // fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { +// // let simulate = self.simulate.get_transferable_by_tick(script, tick)?; +// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable_by_tick(&table, script, tick) +// // })?; +// // // TODO:merge +// // todo!() +// // } +// // +// // fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { +// // let simulate = self.simulate.get_transferable_by_id(script, inscription_id)?; +// // if let Some(ret) = simulate { +// // return Ok(Some(ret)); +// // } +// // self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable_by_id(&table, script, inscription_id) +// // }) +// // } +// // +// // fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { +// // let simulate = self.simulate.get_inscribe_transfer_inscription(inscription_id)?; +// // if let Some(ret) = simulate { +// // return Ok(Some(ret)); +// // } +// // self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { +// // get_inscribe_transfer_inscription(&table, inscription_id) +// // }) +// // } +// // } +// // +// // impl Brc20ReaderWriter for SimulateContext { +// // fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { +// // self.simulate.update_token_balance(script_key, new_balance) +// // } +// // +// // fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { +// // self.simulate.insert_token_info(tick, new_info) +// // } +// // +// // +// // fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { +// // self.simulate.update_mint_token_info(tick, minted_amt, minted_block_number) +// // } +// // +// // fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { +// // self.simulate.save_transaction_receipts(txid, receipt) +// // } +// // +// // fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { +// // self.simulate.insert_transferable(script, tick, inscription) +// // } +// // +// // fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { +// // self.simulate.remove_transferable(script, tick, inscription_id) +// // } +// // +// // fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { +// // self.simulate.insert_inscribe_transfer_inscription(inscription_id, transfer_info) +// // } +// // +// // fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { +// // self.simulate.remove_inscribe_transfer_inscription(inscription_id) +// // } +// // } +// // impl Brc20Reader for SimulateContext { // type Error = anyhow::Error; // // fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { -// let simulate = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { -// get_balances(&table, script_key) -// })?; -// let mut simulate_balances: HashMap = simulate.into_iter() -// .map(|v| { -// (v.tick.clone(), v.clone()) -// }).collect(); -// let internal = self.use_internal_table(BRC20_BALANCES, |v| { -// get_balances(&v, script_key) -// })?; -// for node in internal { -// let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); -// v.transferable_balance = v.transferable_balance + node.transferable_balance; -// v.overall_balance = v.overall_balance + node.overall_balance; -// } -// let ret = simulate_balances -// .into_iter() -// .map(|(k, v)| { -// v.clone() -// }).collect(); -// Ok(ret) +// // self.simulate.use_cache_mut(CacheTableIndex::BRC20_BALANCES,|table|{ +// // +// // }) +// // let simulate = self.simulate.get_balances(script_key)?; +// // let mut simulate_balances: HashMap = simulate.into_iter() +// // .map(|v| { +// // (v.tick.clone(), v.clone()) +// // }).collect(); +// // let internal = self.use_internal_table(BRC20_BALANCES, |v| { +// // get_balances(&v, script_key) +// // })?; +// // for node in internal { +// // let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); +// // v.transferable_balance = v.transferable_balance + node.transferable_balance; +// // v.overall_balance = v.overall_balance + node.overall_balance; +// // } +// // let ret = simulate_balances +// // .into_iter() +// // .map(|(k, v)| { +// // v.clone() +// // }).collect(); +// // Ok(ret) +// todo!() // } // // fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { -// let ret = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { -// get_balance(&table, script_key, tick) +// let ret = self.simulate.use_cache(CacheTableIndex::BRC20_BALANCES, |table| { +// if table.is_none() { +// return Ok::, Self::Error>(None); +// } +// let key = script_tick_key(script_key, tick); +// let key = key.as_str(); +// let table = table.unwrap(); +// let value = table.get(string_to_bytes(key)); +// if value.is_none() { +// return Ok::, Self::Error>(None); +// } +// let bal: Balance = rmp_serde::from_slice(&value.unwrap()).unwrap(); +// Ok(Some(bal)) // })?; // if let Some(ret) = ret { // return Ok(Some(ret)); @@ -100,9 +531,22 @@ impl SimulateContext { // } // // fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { -// let ret = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { -// get_token_info(&table, tick) -// })?; +// let ret = self.simulate +// .use_cache(CacheTableIndex::BRC20_TOKEN, |table| { +// if table.is_none() { +// return Ok::, Self::Error>(None); +// } +// let table = table.unwrap(); +// let binding = tick.to_lowercase().hex(); +// let key = binding.as_str(); +// let value = table.get(string_to_bytes(key)); +// if value.is_none() { +// return Ok::, Self::Error>(None); +// } +// let value = value.unwrap(); +// let info: TokenInfo = rmp_serde::from_slice(&value).unwrap(); +// return Ok(Some(info)); +// })?; // if let Some(ret) = ret { // return Ok(Some(ret)); // } @@ -112,20 +556,32 @@ impl SimulateContext { // } // // fn get_tokens_info(&self) -> crate::Result, Self::Error> { -// let simulate = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { -// get_tokens_info(&table) -// })?; -// let internal = self.use_internal_table(BRC20_TOKEN, |table| { -// get_tokens_info(&table) -// })?; +// // let simulate = self.simulate.get_tokens_info()?; +// // let internal = self.use_internal_table(BRC20_TOKEN, |table| { +// // get_tokens_info(&table) +// // })?; // // TODO:merge // todo!() // } // // fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { -// let simulate = self.simulate_index.use_read_table(BRC20_EVENTS, |table| { -// get_transaction_receipts(&table, txid) -// })?; +// let simulate = self.simulate +// .use_cache(CacheTableIndex::BRC20_EVENTS, |table| { +// if table.is_none() { +// return Ok::>, Self::Error>(None); +// } +// let table = table.unwrap(); +// let key = &txid.store(); +// let key: Vec = key.to_vec(); +// // let key = TxidValue::as_bytes(&key).as_ref(); +// let value = table.get(key); +// if value.is_none() { +// return Ok::>, Self::Error>(None); +// } +// let value = value.unwrap(); +// let ret = rmp_serde::from_slice::>(&value).unwrap(); +// Ok(Some(ret)) +// })?; // let internal = self.use_internal_table(BRC20_EVENTS, |table| { // get_transaction_receipts(&table, txid) // })?; @@ -134,44 +590,53 @@ impl SimulateContext { // } // // fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { -// let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { -// get_transferable(&table, script) -// })?; -// let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// get_transferable(&table, script) -// })?; +// // let simulate = self.simulate.get_transferable(script)?; +// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable(&table, script) +// // })?; // // TODO: merge // todo!() // } // // // fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { -// let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { -// get_transferable_by_tick(&table, script, tick) -// })?; -// let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// get_transferable_by_tick(&table, script, tick) -// })?; +// // let simulate = self.simulate.get_transferable_by_tick(script, tick)?; +// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable_by_tick(&table, script, tick) +// // })?; // // TODO:merge // todo!() // } // // fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { -// let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { -// get_transferable_by_id(&table, script, inscription_id) -// })?; -// if let Some(ret) = simulate { -// return Ok(Some(ret)); -// } -// self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// get_transferable_by_id(&table, script, inscription_id) -// }) +// // let simulate = self.simulate.get_transferable_by_id(script, inscription_id)?; +// // if let Some(ret) = simulate { +// // return Ok(Some(ret)); +// // } +// // self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { +// // get_transferable_by_id(&table, script, inscription_id) +// // }) +// todo!() // } // // fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { -// let simulate = self.simulate_index.use_read_table(BRC20_INSCRIBE_TRANSFER, |table| { -// get_inscribe_transfer_inscription(&table, inscription_id) -// })?; +// let simulate = self.simulate +// .use_cache(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { +// if table.is_none() { +// return Ok::, Self::Error>(None); +// } +// let table = table.unwrap(); +// let key = inscription_id.store(); +// let key_bytes = InscriptionIdValue::as_bytes(&key); +// let value = table.get(key_bytes); +// if value.is_none() { +// return Ok::, Self::Error>(None); +// } +// let value = value.unwrap(); +// let ret: TransferInfo = rmp_serde::from_slice::(&value).unwrap(); +// return Ok(Some(ret)); +// })?; +// // let simulate = self.simulate.get_inscribe_transfer_inscription(inscription_id)?; // if let Some(ret) = simulate { // return Ok(Some(ret)); // } @@ -183,345 +648,206 @@ impl SimulateContext { // // impl Brc20ReaderWriter for SimulateContext { // fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { -// self.simulate_index -// .use_write_table(BRC20_BALANCES, |mut table| { -// let binding = script_tick_key(script_key, &new_balance.tick); -// let key = binding.as_str(); -// let binding = rmp_serde::to_vec(&new_balance).unwrap(); -// let value = binding.as_slice(); -// // let origin = table.get(key)?.map_or(None, |v| { -// // Some(v.value().to_vec()) -// // }); -// table.insert(key, value)?; -// // let mut delta = BalanceDelta::default(); -// // if let Some(origin) = origin { -// // let origin: Balance = rmp_serde::from_slice(&origin).unwrap(); -// // delta.origin_transferable_balance_delta = origin.transferable_balance; -// // delta.origin_overall_balance_delta = origin.overall_balance; -// // delta.new_overall_balance_delta = new_balance.overall_balance; -// // delta.new_transferable_balance_delta = new_balance.transferable_balance; -// // } else { -// // delta.origin_transferable_balance_delta = 0; -// // delta.origin_overall_balance_delta = 0; -// // delta.new_overall_balance_delta = new_balance.overall_balance; -// // delta.new_transferable_balance_delta = new_balance.transferable_balance; -// // } -// // let op = TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()); -// let node = TraceNode { trace_type: CacheTableIndex::BRC20_BALANCES, key: string_to_bytes(key) }; -// Ok(((), node)) -// })?; -// Ok(()) +// self.simulate.use_cache_mut(CacheTableIndex::BRC20_BALANCES, |table| { +// let key = script_tick_key(script_key, &new_balance.tick); +// let key = key.as_str(); +// let binding = rmp_serde::to_vec(&new_balance).unwrap(); +// let value = binding.as_slice(); +// table.insert(string_to_bytes(key), value.to_vec()); +// Ok(()) +// }) // } // // fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { -// self.simulate_index -// .use_write_table(BRC20_TOKEN, |mut table| { -// let binding = tick.to_lowercase().hex(); -// let key = binding.as_str(); -// let binding = rmp_serde::to_vec(new_info).unwrap(); -// let value = binding.as_slice(); -// table.insert(key, value)?; -// -// let trace = TraceNode { -// trace_type: CacheTableIndex::BRC20_TOKEN, -// // operation: TraceOperation::Insert, -// key: string_to_bytes(key), -// }; -// Ok(((), trace)) -// })?; -// Ok(()) +// self.simulate.use_cache_mut(CacheTableIndex::BRC20_TOKEN, |table| { +// let binding = tick.to_lowercase().hex(); +// let key = binding.as_str(); +// let binding = rmp_serde::to_vec(new_info).unwrap(); +// let value = binding.as_slice(); +// table.insert(string_to_bytes(key), value.to_vec()); +// Ok(()) +// }) // } // // // fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { -// let mut info = self.get_token_info(tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); -// let origin = info.minted; +// let mut info = self. +// get_token_info(tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); // info.minted = minted_amt; // info.latest_mint_number = minted_block_number; -// self.simulate_index -// .use_write_table(BRC20_TOKEN, |mut table| { +// self.simulate +// .use_cache_mut(CacheTableIndex::BRC20_TOKEN, |table| { // let binding = tick.to_lowercase().hex(); // let key = binding.as_str(); -// let binding = rmp_serde::to_vec(&info).unwrap(); -// let value = binding.as_slice(); -// table.insert(key, value)?; -// // let delta = MintTokenInfoDelta { -// // origin_minted: origin, -// // new_minted: info.minted, -// // new_latest_mint_number: minted_block_number, -// // }; -// let trace = TraceNode { -// trace_type: CacheTableIndex::BRC20_TOKEN, -// // operation: TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()), -// key: string_to_bytes(key), -// }; -// Ok(((), trace)) -// })?; -// Ok(()) +// let value = rmp_serde::to_vec(&info).unwrap(); +// table.insert(string_to_bytes(key), value.to_vec()); +// Ok(()) +// }) // } // -// fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { -// self.simulate_index -// .use_write_table(BRC20_EVENTS, |mut table| { -// let tx_id_value = txid.store(); -// let key = tx_id_value.to_vec(); -// let binding = rmp_serde::to_vec(receipt).unwrap(); -// let value = binding.as_slice(); -// table.insert(&txid.store(), value)?; -// let trace = TraceNode { -// trace_type: CacheTableIndex::BRC20_EVENTS, -// key, -// }; -// Ok(((), trace)) -// })?; -// Ok(()) -// // self.simulate.save_transaction_receipts(txid, receipt) +// fn save_transaction_receipts(&mut self, txid: &Txid, receipts: &[Receipt]) -> crate::Result<(), Self::Error> { +// self.simulate.use_cache_mut(CacheTableIndex::BRC20_EVENTS, |table| { +// let v = txid.store(); +// let key = v.to_vec(); +// let value = rmp_serde::to_vec(receipts).unwrap(); +// table.insert(key, value); +// Ok(()) +// }) // } // // fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { -// self.simulate_index -// .use_write_table(BRC20_TRANSFERABLELOG, |mut table| { +// self.simulate +// .use_cache_mut(CacheTableIndex::BRC20_TRANSFERABLELOG, |table| { // let binding = script_tick_id_key(script, tick, &inscription.inscription_id); // let key = binding.as_str(); // let binding = rmp_serde::to_vec(inscription).unwrap(); // let value = binding.as_slice(); -// table.insert(key, value)?; -// let trace = TraceNode { -// trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, -// key: string_to_bytes(key), -// }; -// Ok(((), trace)) -// })?; -// Ok(()) +// table.insert(string_to_bytes(key), value.to_vec()); +// Ok(()) +// }) // } // // fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { -// self.simulate_index.use_write_table(BRC20_TRANSFERABLELOG, |mut table| { +// self.simulate.use_cache_mut(CacheTableIndex::BRC20_TRANSFERABLELOG, |table| { // let binding = script_tick_id_key(script, tick, inscription_id); // let key = binding.as_str(); -// table.remove(key)?; -// let trace = TraceNode { -// trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, -// key: string_to_bytes(key), -// }; -// Ok(((), trace)) -// })?; -// Ok(()) +// table.remove(string_to_bytes(key)); +// Ok(()) +// }) // } // // fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { -// self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { +// self.simulate.use_cache_mut(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { // let key = inscription_id.store(); // let key_bytes = InscriptionIdValue::as_bytes(&key); -// let binding = rmp_serde::to_vec(&transfer_info).unwrap(); -// let value = binding.as_slice(); -// table.insert(&key, value)?; -// let trace = TraceNode { -// trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, -// key: key_bytes, -// }; -// Ok(((), trace)) -// })?; -// Ok(()) +// let value = rmp_serde::to_vec(&transfer_info).unwrap(); +// table.insert(key_bytes, value); +// Ok(()) +// }) // } // // fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { -// self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { +// self.simulate.use_cache_mut(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { // let key = inscription_id.store(); // let key_bytes = InscriptionIdValue::as_bytes(&key); -// table.remove(&key)?; -// let trace = TraceNode { -// trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, -// key: key_bytes, -// }; -// Ok(((), trace)) -// })?; -// Ok(()) -// } -// } - -// impl Brc20Reader for SimulateContext { -// type Error = anyhow::Error; -// -// fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { -// let simulate = self.simulate.get_balances(script_key)?; -// let mut simulate_balances: HashMap = simulate.into_iter() -// .map(|v| { -// (v.tick.clone(), v.clone()) -// }).collect(); -// let internal = self.use_internal_table(BRC20_BALANCES, |v| { -// get_balances(&v, script_key) -// })?; -// for node in internal { -// let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); -// v.transferable_balance = v.transferable_balance + node.transferable_balance; -// v.overall_balance = v.overall_balance + node.overall_balance; -// } -// let ret = simulate_balances -// .into_iter() -// .map(|(k, v)| { -// v.clone() -// }).collect(); -// Ok(ret) -// } -// -// fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { -// let ret = self.simulate.get_balance(script_key, tick)?; -// if let Some(ret) = ret { -// return Ok(Some(ret)); -// } -// self.use_internal_table(BRC20_BALANCES, |table| { -// get_balance(&table, script_key, tick) -// }) -// } -// -// fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { -// let ret = self.simulate.get_token_info(tick)?; -// if let Some(ret) = ret { -// return Ok(Some(ret)); -// } -// self.use_internal_table(BRC20_TOKEN, |table| { -// get_token_info(&table, tick) -// }) -// } -// -// fn get_tokens_info(&self) -> crate::Result, Self::Error> { -// let simulate = self.simulate.get_tokens_info()?; -// let internal = self.use_internal_table(BRC20_TOKEN, |table| { -// get_tokens_info(&table) -// })?; -// // TODO:merge -// todo!() -// } -// -// fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { -// let simulate = self.simulate.get_transaction_receipts(txid)?; -// let internal = self.use_internal_table(BRC20_EVENTS, |table| { -// get_transaction_receipts(&table, txid) -// })?; -// // TODO:merge -// todo!() -// } -// -// fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { -// let simulate = self.simulate.get_transferable(script)?; -// let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// get_transferable(&table, script) -// })?; -// // TODO: merge -// todo!() -// } -// -// -// fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { -// let simulate = self.simulate.get_transferable_by_tick(script, tick)?; -// let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// get_transferable_by_tick(&table, script, tick) -// })?; -// // TODO:merge -// todo!() -// } -// -// fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { -// let simulate = self.simulate.get_transferable_by_id(script, inscription_id)?; -// if let Some(ret) = simulate { -// return Ok(Some(ret)); -// } -// self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// get_transferable_by_id(&table, script, inscription_id) -// }) -// } -// -// fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { -// let simulate = self.simulate.get_inscribe_transfer_inscription(inscription_id)?; -// if let Some(ret) = simulate { -// return Ok(Some(ret)); -// } -// self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { -// get_inscribe_transfer_inscription(&table, inscription_id) +// table.remove(key_bytes); +// Ok(()) // }) // } // } // -// impl Brc20ReaderWriter for SimulateContext { -// fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { -// self.simulate.update_token_balance(script_key, new_balance) -// } -// -// fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { -// self.simulate.insert_token_info(tick, new_info) -// } +// #[test] +// pub fn test_asd() {} // +// #[test] +// fn test_write() { +// let tmpfile = NamedTempFile::new().unwrap(); +// let db = Database::builder() +// .create(tmpfile.path()) +// .unwrap(); +// let table_definition: TableDefinition = TableDefinition::new("x"); // -// fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { -// self.simulate.update_mint_token_info(tick, minted_amt, minted_block_number) +// { +// let mut wtx = db.begin_write().unwrap(); +// let mut table = wtx.open_table(table_definition).unwrap(); +// table.insert(1, 1).unwrap(); +// let vv = table.get(&1).unwrap().unwrap().value(); +// assert_eq!(vv, 1); // } // -// fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { -// self.simulate.save_transaction_receipts(txid, receipt) -// } // -// fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { -// self.simulate.insert_transferable(script, tick, inscription) -// } -// -// fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { -// self.simulate.remove_transferable(script, tick, inscription_id) +// { +// let mut wtx = db.begin_write().unwrap(); +// let mut table = wtx.open_table(table_definition).unwrap(); +// table.insert(2, 2).unwrap(); +// let vv = table.get(&2).unwrap().unwrap().value(); +// assert_eq!(vv, 2); +// let v1 = table.get(&1).unwrap().unwrap().value(); +// assert_eq!(v1, 1); // } // -// fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { -// self.simulate.insert_inscribe_transfer_inscription(inscription_id, transfer_info) -// } -// -// fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { -// self.simulate.remove_inscribe_transfer_inscription(inscription_id) -// } +// // wtx.commit().unwrap(); +// // { +// // let rtx = db.begin_read().unwrap(); +// // let table = rtx.open_table(table_definition).unwrap(); +// // assert_eq!(table.get(&1).unwrap().unwrap().value(), 1); +// // } // } +// + +////////// -impl Brc20Reader for SimulateContext { +use std::cell::RefCell; +use std::collections::HashMap; +use std::marker::PhantomData; +use std::ops::{Deref, DerefMut}; +use std::rc::Rc; +use std::sync::Arc; +use anyhow::anyhow; +use bitcoin::{Network, Txid}; +use redb::{MultimapTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition}; +use crate::{Index, InscriptionId, SatPoint}; +use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; +use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; +use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick, insert_inscribe_transfer_inscription, insert_token_info, insert_transferable, remove_inscribe_transfer_inscription, remove_transferable, save_transaction_receipts, update_token_balance}; +use crate::okx::datastore::cache::CacheWriter; +use crate::okx::datastore::ord::{InscriptionOp, OrdReader, OrdReaderWriter}; +use crate::okx::datastore::ord::collections::CollectionKind; +use crate::okx::datastore::ord::redb::table::{get_collection_inscription_id, get_collections_of_inscription, get_inscription_number_by_sequence_number, get_transaction_operations, get_txout_by_outpoint, save_transaction_operations}; +use crate::okx::datastore::ScriptKey; +use crate::okx::protocol::ContextTrait; + +pub struct SimulateContext<'a, 'db, 'txn> { + internal_index: Arc, + pub(crate) ORD_TX_TO_OPERATIONS: Rc>>, + pub(crate) COLLECTIONS_KEY_TO_INSCRIPTION_ID: + Rc>>, + pub(crate) COLLECTIONS_INSCRIPTION_ID_TO_KINDS: + Rc>>, + pub(crate) SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: + Rc>>, + pub(crate) OUTPOINT_TO_ENTRY: Rc>>, + + // BRC20 tables + pub(crate) BRC20_BALANCES: Rc>>, + pub(crate) BRC20_TOKEN: Rc>>, + pub(crate) BRC20_EVENTS: Rc>>, + pub(crate) BRC20_TRANSFERABLELOG: Rc>>, + pub(crate) BRC20_INSCRIBE_TRANSFER: Rc>>, + pub _marker_a: PhantomData<&'a ()>, +} + +impl<'a, 'db, 'txn> Brc20Reader for SimulateContext<'a, 'db, 'txn> { type Error = anyhow::Error; fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { - // self.simulate.use_cache_mut(CacheTableIndex::BRC20_BALANCES,|table|{ - // - // }) - // let simulate = self.simulate.get_balances(script_key)?; - // let mut simulate_balances: HashMap = simulate.into_iter() - // .map(|v| { - // (v.tick.clone(), v.clone()) - // }).collect(); - // let internal = self.use_internal_table(BRC20_BALANCES, |v| { - // get_balances(&v, script_key) - // })?; - // for node in internal { - // let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); - // v.transferable_balance = v.transferable_balance + node.transferable_balance; - // v.overall_balance = v.overall_balance + node.overall_balance; - // } - // let ret = simulate_balances - // .into_iter() - // .map(|(k, v)| { - // v.clone() - // }).collect(); - // Ok(ret) - todo!() + let balances = self.BRC20_BALANCES.borrow(); + let table = balances.deref(); + let simulate = get_balances(table, script_key)?; + let internal = self.use_internal_table(BRC20_BALANCES, |v| { + get_balances(&v, script_key) + })?; + let mut simulate_balances: HashMap = simulate.into_iter() + .map(|v| { + (v.tick.clone(), v.clone()) + }).collect(); + for node in internal { + let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); + v.transferable_balance = v.transferable_balance + node.transferable_balance; + v.overall_balance = v.overall_balance + node.overall_balance; + } + let ret = simulate_balances + .into_iter() + .map(|(k, v)| { + v.clone() + }).collect(); + Ok(ret) } fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { - let ret = self.simulate.use_cache(CacheTableIndex::BRC20_BALANCES, |table| { - if table.is_none() { - return Ok::, Self::Error>(None); - } - let key = script_tick_key(script_key, tick); - let key = key.as_str(); - let table = table.unwrap(); - let value = table.get(string_to_bytes(key)); - if value.is_none() { - return Ok::, Self::Error>(None); - } - let bal: Balance = rmp_serde::from_slice(&value.unwrap()).unwrap(); - Ok(Some(bal)) - })?; + let table = self.BRC20_BALANCES.borrow(); + let table = table.deref(); + let ret = get_balance(table, script_key, tick)?; if let Some(ret) = ret { return Ok(Some(ret)); } @@ -531,22 +857,9 @@ impl Brc20Reader for SimulateContext { } fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { - let ret = self.simulate - .use_cache(CacheTableIndex::BRC20_TOKEN, |table| { - if table.is_none() { - return Ok::, Self::Error>(None); - } - let table = table.unwrap(); - let binding = tick.to_lowercase().hex(); - let key = binding.as_str(); - let value = table.get(string_to_bytes(key)); - if value.is_none() { - return Ok::, Self::Error>(None); - } - let value = value.unwrap(); - let info: TokenInfo = rmp_serde::from_slice(&value).unwrap(); - return Ok(Some(info)); - })?; + let table = self.BRC20_TOKEN.borrow(); + let table = table.deref(); + let ret = get_token_info(table, tick)?; if let Some(ret) = ret { return Ok(Some(ret)); } @@ -556,88 +869,106 @@ impl Brc20Reader for SimulateContext { } fn get_tokens_info(&self) -> crate::Result, Self::Error> { - // let simulate = self.simulate.get_tokens_info()?; - // let internal = self.use_internal_table(BRC20_TOKEN, |table| { - // get_tokens_info(&table) - // })?; - // TODO:merge - todo!() + let binding = self.BRC20_TOKEN.borrow(); + let table = binding.deref(); + let ret = get_tokens_info(table)?; + let mut token_map = ret.into_iter().map(|v| { + (v.tick.clone(), v) + }).collect::>(); + let internal = self.use_internal_table(BRC20_TOKEN, |table| { + get_tokens_info(&table) + })?; + for node in internal { + if !token_map.contains_key(&node.tick) { + token_map.insert(node.tick.clone(), node.clone()); + } + } + let ret = token_map.into_iter().map(|(_, v)| { + v + }).collect(); + Ok(ret) } fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { - let simulate = self.simulate - .use_cache(CacheTableIndex::BRC20_EVENTS, |table| { - if table.is_none() { - return Ok::>, Self::Error>(None); - } - let table = table.unwrap(); - let key = &txid.store(); - let key: Vec = key.to_vec(); - // let key = TxidValue::as_bytes(&key).as_ref(); - let value = table.get(key); - if value.is_none() { - return Ok::>, Self::Error>(None); - } - let value = value.unwrap(); - let ret = rmp_serde::from_slice::>(&value).unwrap(); - Ok(Some(ret)) - })?; + let binding = self.BRC20_EVENTS.borrow(); + let table = binding.deref(); + let ret = get_transaction_receipts(table, txid)?; + let mut simulate_receipts = ret.into_iter().map(|v| { + (v.inscription_id.clone(), v) + }).collect::>(); let internal = self.use_internal_table(BRC20_EVENTS, |table| { get_transaction_receipts(&table, txid) })?; - // TODO:merge - todo!() + for node in internal { + if !simulate_receipts.contains_key(&node.inscription_id) { + simulate_receipts.insert(node.inscription_id.clone(), node.clone()); + } + } + let ret = simulate_receipts.into_iter().map(|(_, v)| { + v + }).collect(); + Ok(ret) } fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { - // let simulate = self.simulate.get_transferable(script)?; - // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { - // get_transferable(&table, script) - // })?; - // TODO: merge - todo!() + let binding = self.BRC20_TRANSFERABLELOG.borrow(); + let table = binding.deref(); + let ret = get_transferable(table, script)?; + let mut simulate_transferable = ret.into_iter().map(|v| { + (v.inscription_id.clone(), v) + }).collect::>(); + let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable(&table, script) + })?; + for node in internal { + if !simulate_transferable.contains_key(&node.inscription_id) { + simulate_transferable.insert(node.inscription_id.clone(), node.clone()); + } + } + let ret = simulate_transferable.into_iter().map(|(_, v)| { + v + }).collect(); + Ok(ret) } - fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { - // let simulate = self.simulate.get_transferable_by_tick(script, tick)?; - // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { - // get_transferable_by_tick(&table, script, tick) - // })?; - // TODO:merge - todo!() + let binding = self.BRC20_TRANSFERABLELOG.borrow(); + let table = binding.deref(); + let ret = get_transferable_by_tick(table, script, tick)?; + let mut simulate_transferable = ret.into_iter().map(|v| { + (v.inscription_id.clone(), v) + }).collect::>(); + let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable_by_tick(&table, script, tick) + })?; + for node in internal { + if !simulate_transferable.contains_key(&node.inscription_id) { + simulate_transferable.insert(node.inscription_id.clone(), node.clone()); + } + } + let ret = simulate_transferable.into_iter().map(|(_, v)| { + v + }).collect(); + Ok(ret) } fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { - // let simulate = self.simulate.get_transferable_by_id(script, inscription_id)?; - // if let Some(ret) = simulate { - // return Ok(Some(ret)); - // } - // self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { - // get_transferable_by_id(&table, script, inscription_id) - // }) - todo!() + let binding = self.BRC20_TRANSFERABLELOG.borrow(); + let table = binding.deref(); + let ret = get_transferable_by_id(table, script, inscription_id)?; + if let Some(ret) = ret { + return Ok(Some(ret)); + } + self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable_by_id(&table, script, inscription_id) + }) } fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { - let simulate = self.simulate - .use_cache(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { - if table.is_none() { - return Ok::, Self::Error>(None); - } - let table = table.unwrap(); - let key = inscription_id.store(); - let key_bytes = InscriptionIdValue::as_bytes(&key); - let value = table.get(key_bytes); - if value.is_none() { - return Ok::, Self::Error>(None); - } - let value = value.unwrap(); - let ret: TransferInfo = rmp_serde::from_slice::(&value).unwrap(); - return Ok(Some(ret)); - })?; - // let simulate = self.simulate.get_inscribe_transfer_inscription(inscription_id)?; - if let Some(ret) = simulate { + let binding = self.BRC20_INSCRIBE_TRANSFER.borrow(); + let table = binding.deref(); + let ret = get_inscribe_transfer_inscription(table, inscription_id)?; + if let Some(ret) = ret { return Ok(Some(ret)); } self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { @@ -646,131 +977,190 @@ impl Brc20Reader for SimulateContext { } } -impl Brc20ReaderWriter for SimulateContext { +impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { - self.simulate.use_cache_mut(CacheTableIndex::BRC20_BALANCES, |table| { - let key = script_tick_key(script_key, &new_balance.tick); - let key = key.as_str(); - let binding = rmp_serde::to_vec(&new_balance).unwrap(); - let value = binding.as_slice(); - table.insert(string_to_bytes(key), value.to_vec()); - Ok(()) - }) + let mut table = self.BRC20_BALANCES.borrow_mut(); + update_token_balance(&mut table, script_key, new_balance) } fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { - self.simulate.use_cache_mut(CacheTableIndex::BRC20_TOKEN, |table| { - let binding = tick.to_lowercase().hex(); - let key = binding.as_str(); - let binding = rmp_serde::to_vec(new_info).unwrap(); - let value = binding.as_slice(); - table.insert(string_to_bytes(key), value.to_vec()); - Ok(()) - }) + let mut binding = self.BRC20_TOKEN.borrow_mut(); + let mut table = binding.deref_mut(); + insert_token_info(table, tick, new_info) } - fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { - let mut info = self. - get_token_info(tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); + let mut binding = self.BRC20_TOKEN.borrow_mut(); + let mut table = binding.deref_mut(); + let mut info = get_token_info(table, tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); info.minted = minted_amt; info.latest_mint_number = minted_block_number; - self.simulate - .use_cache_mut(CacheTableIndex::BRC20_TOKEN, |table| { - let binding = tick.to_lowercase().hex(); - let key = binding.as_str(); - let value = rmp_serde::to_vec(&info).unwrap(); - table.insert(string_to_bytes(key), value.to_vec()); - Ok(()) - }) + insert_token_info(table, tick, &info) } - fn save_transaction_receipts(&mut self, txid: &Txid, receipts: &[Receipt]) -> crate::Result<(), Self::Error> { - self.simulate.use_cache_mut(CacheTableIndex::BRC20_EVENTS, |table| { - let v = txid.store(); - let key = v.to_vec(); - let value = rmp_serde::to_vec(receipts).unwrap(); - table.insert(key, value); - Ok(()) - }) + fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { + let mut table = self.BRC20_EVENTS.borrow_mut(); + save_transaction_receipts(&mut table, txid, receipt) } fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { - self.simulate - .use_cache_mut(CacheTableIndex::BRC20_TRANSFERABLELOG, |table| { - let binding = script_tick_id_key(script, tick, &inscription.inscription_id); - let key = binding.as_str(); - let binding = rmp_serde::to_vec(inscription).unwrap(); - let value = binding.as_slice(); - table.insert(string_to_bytes(key), value.to_vec()); - Ok(()) - }) + let mut table = self.BRC20_TRANSFERABLELOG.borrow_mut(); + insert_transferable(&mut table, script, tick, inscription) } fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - self.simulate.use_cache_mut(CacheTableIndex::BRC20_TRANSFERABLELOG, |table| { - let binding = script_tick_id_key(script, tick, inscription_id); - let key = binding.as_str(); - table.remove(string_to_bytes(key)); - Ok(()) - }) + let mut table = self.BRC20_TRANSFERABLELOG.borrow_mut(); + remove_transferable(&mut table, script, tick, inscription_id) } fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { - self.simulate.use_cache_mut(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { - let key = inscription_id.store(); - let key_bytes = InscriptionIdValue::as_bytes(&key); - let value = rmp_serde::to_vec(&transfer_info).unwrap(); - table.insert(key_bytes, value); - Ok(()) - }) + let mut table = self.BRC20_INSCRIBE_TRANSFER.borrow_mut(); + insert_inscribe_transfer_inscription(&mut table, inscription_id, transfer_info) } fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - self.simulate.use_cache_mut(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { - let key = inscription_id.store(); - let key_bytes = InscriptionIdValue::as_bytes(&key); - table.remove(key_bytes); - Ok(()) - }) + let mut table = self.BRC20_INSCRIBE_TRANSFER.borrow_mut(); + remove_inscribe_transfer_inscription(&mut table, inscription_id) } } -#[test] -pub fn test_asd() {} - -#[test] -fn test_write() { - let tmpfile = NamedTempFile::new().unwrap(); - let db = Database::builder() - .create(tmpfile.path()) - .unwrap(); - let table_definition: TableDefinition = TableDefinition::new("x"); - - { - let mut wtx = db.begin_write().unwrap(); - let mut table = wtx.open_table(table_definition).unwrap(); - table.insert(1, 1).unwrap(); - let vv = table.get(&1).unwrap().unwrap().value(); - assert_eq!(vv, 1); +impl<'a, 'db, 'txn> OrdReaderWriter for SimulateContext<'a, 'db, 'txn> { + fn save_transaction_operations(&mut self, txid: &Txid, operations: &[InscriptionOp]) -> crate::Result<(), Self::Error> { + let mut table = self.ORD_TX_TO_OPERATIONS.borrow_mut(); + save_transaction_operations(&mut table, txid, operations) } + fn set_inscription_by_collection_key(&mut self, key: &str, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { + todo!() + } - { - let mut wtx = db.begin_write().unwrap(); - let mut table = wtx.open_table(table_definition).unwrap(); - table.insert(2, 2).unwrap(); - let vv = table.get(&2).unwrap().unwrap().value(); - assert_eq!(vv, 2); - let v1 = table.get(&1).unwrap().unwrap().value(); - assert_eq!(v1, 1); + fn set_inscription_attributes(&mut self, inscription_id: &InscriptionId, kind: &[CollectionKind]) -> crate::Result<(), Self::Error> { + todo!() } +} - // wtx.commit().unwrap(); - // { - // let rtx = db.begin_read().unwrap(); - // let table = rtx.open_table(table_definition).unwrap(); - // assert_eq!(table.get(&1).unwrap().unwrap().value(), 1); - // } +impl<'a, 'db, 'txn> OrdReader for SimulateContext<'a, 'db, 'txn> { + type Error = anyhow::Error; + + fn get_inscription_number_by_sequence_number(&self, sequence_number: u32) -> crate::Result { + let binding = self.SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY.borrow(); + let table = binding.deref(); + let ret = get_inscription_number_by_sequence_number( + table, + sequence_number, + ) + .map_err(|e| anyhow!("failed to get inscription number from state! error: {e}"))?; + if let Some(ret) = ret { + return Ok(ret); + } + self.use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| { + get_inscription_number_by_sequence_number( + &table, + sequence_number, + ) + }).map_err(|e| anyhow!("failed to get inscription number from state! error: {e}"))?.ok_or(anyhow!( + "failed to get inscription number! error: sequence number {} not found", + sequence_number + )) + } + + fn get_script_key_on_satpoint(&mut self, satpoint: &SatPoint, network: Network) -> crate::Result { + let binding = self.OUTPOINT_TO_ENTRY.borrow(); + let table = binding.deref(); + if let Some(tx_out) = get_txout_by_outpoint(table, &satpoint.outpoint)? + { + return Ok(ScriptKey::from_script(&tx_out.script_pubkey, network)); + } else { + let ret = self.use_internal_table(OUTPOINT_TO_ENTRY, |table| { + get_txout_by_outpoint(&table, &satpoint.outpoint) + })?; + if let Some(ret) = ret { + return Ok(ScriptKey::from_script(&ret.script_pubkey, network)); + } + } + return Err(anyhow!("failed to get tx out! error: outpoint {} not found", + &satpoint.outpoint)); + } + + fn get_transaction_operations(&self, txid: &Txid) -> crate::Result, Self::Error> { + let binding = self.ORD_TX_TO_OPERATIONS.borrow(); + let table = binding.deref(); + let simulate = get_transaction_operations(table, txid)?; + let mut simulate_operations: HashMap = simulate.into_iter() + .map(|v| { + (v.inscription_id.clone(), v.clone()) + }).collect(); + let internal = self.use_internal_table(BRC20_EVENTS, |table| { + get_transaction_operations(&table, txid) + })?; + for node in internal { + if simulate_operations.contains_key(&node.inscription_id) { + continue; + } + simulate_operations.insert(node.inscription_id.clone(), node.clone()); + } + let ret = simulate_operations.into_iter().map(|(_, v)| { + v + }).collect(); + Ok(ret) + } + + fn get_collections_of_inscription(&self, inscription_id: &InscriptionId) -> crate::Result>, Self::Error> { + let binding = self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS.borrow(); + let table = binding.deref(); + let simulate = get_collections_of_inscription(table, inscription_id)?; + let mut simulate = if let Some(ret) = simulate { + ret + } else { + vec![] + }; + + let internal = self.use_internal_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS, |table| { + get_collections_of_inscription(&table, inscription_id) + })?; + if let Some(internal) = internal { + simulate.extend_from_slice(&internal); + } + if simulate.is_empty() { + return Ok(None); + } + return Ok(Some(simulate)); + } + + fn get_collection_inscription_id(&self, collection_key: &str) -> crate::Result, Self::Error> { + let binding = self.COLLECTIONS_KEY_TO_INSCRIPTION_ID.borrow(); + let table = binding.deref(); + let ret = get_collection_inscription_id(table, collection_key)?; + if let Some(ret) = ret { + return Ok(Some(ret)); + } + self.use_internal_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID, |table| { + get_collection_inscription_id(&table, collection_key) + }) + } } +impl<'a, 'db, 'txn> ContextTrait for SimulateContext<'a, 'db, 'txn> { + fn block_height(&self) -> u32 { + todo!() + } + + fn network(&self) -> Network { + todo!() + } + + fn block_time(&self) -> u32 { + todo!() + } +} + +impl<'a, 'db, 'txn> SimulateContext<'a, 'db, 'txn> { + fn use_internal_table(&self, + table_def: TableDefinition, + f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { + let rtx = self.internal_index.begin_read()?; + let table = rtx.0.open_table(table_def)?; + let ret = f(table); + ret + } +} \ No newline at end of file From aaa721cf31a86a398a9ccfc1d48ea2b3f6770c58 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 08:44:50 +0800 Subject: [PATCH 15/66] save2 --- src/okx/protocol/simulate.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index 01b74a03e5..6613bd2b36 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -793,7 +793,7 @@ use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_i use crate::okx::datastore::cache::CacheWriter; use crate::okx::datastore::ord::{InscriptionOp, OrdReader, OrdReaderWriter}; use crate::okx::datastore::ord::collections::CollectionKind; -use crate::okx::datastore::ord::redb::table::{get_collection_inscription_id, get_collections_of_inscription, get_inscription_number_by_sequence_number, get_transaction_operations, get_txout_by_outpoint, save_transaction_operations}; +use crate::okx::datastore::ord::redb::table::{get_collection_inscription_id, get_collections_of_inscription, get_inscription_number_by_sequence_number, get_transaction_operations, get_txout_by_outpoint, save_transaction_operations, set_inscription_attributes, set_inscription_by_collection_key}; use crate::okx::datastore::ScriptKey; use crate::okx::protocol::ContextTrait; @@ -1031,11 +1031,17 @@ impl<'a, 'db, 'txn> OrdReaderWriter for SimulateContext<'a, 'db, 'txn> { } fn set_inscription_by_collection_key(&mut self, key: &str, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - todo!() + let mut table = self.COLLECTIONS_KEY_TO_INSCRIPTION_ID.borrow_mut(); + set_inscription_by_collection_key(&mut table, key, inscription_id) } fn set_inscription_attributes(&mut self, inscription_id: &InscriptionId, kind: &[CollectionKind]) -> crate::Result<(), Self::Error> { - todo!() + let mut table = self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS.borrow_mut(); + set_inscription_attributes( + &mut table, + inscription_id, + kind, + ) } } From 9bc67fa922cabbbf211c50b5db607968ad7617b2 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 09:21:43 +0800 Subject: [PATCH 16/66] fk --- src/index/processor.rs | 28 ++++++++++-- src/index/simulate.rs | 71 +++++++++++++++++++----------- src/okx/protocol/simulate.rs | 84 +++++++++++++++++++----------------- 3 files changed, 115 insertions(+), 68 deletions(-) diff --git a/src/index/processor.rs b/src/index/processor.rs index 31c90cfb4b..ce072bc8a2 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -214,7 +214,7 @@ use bitcoin::{OutPoint, TxOut}; use redb::{MultimapTable, RedbValue, Table, WriteTransaction}; use crate::{Index, InscriptionId, SatPoint}; use crate::index::entry::SatPointValue; -use crate::index::{InscriptionEntryValue, InscriptionIdValue, OutPointValue, TxidValue}; +use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; use crate::okx::protocol::context::Context; use crate::okx::protocol::simulate::SimulateContext; @@ -223,7 +223,7 @@ use crate::okx::protocol::simulate::SimulateContext; pub struct StorageProcessor<'a, 'db, 'tx> { pub internal: Arc, - // pub wtx: &'a mut WriteTransaction<'db>, + // pub wtx: Rc>>, pub(super) home_inscriptions: Rc>>, pub(super) id_to_sequence_number: Rc>>, @@ -249,8 +249,28 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { pub(crate) fn create_context(&self) -> crate::Result { todo!() } - pub(crate) fn create_simulate_context(&self) -> crate::Result { - todo!() + pub(crate) fn create_simulate_context(&self, wtx: &'tx mut WriteTransaction<'db>) -> crate::Result> { + let h = self.internal.block_height().unwrap().unwrap(); + let ts = self.internal.block_time(h).unwrap().timestamp().timestamp(); + let ctx = SimulateContext { + network: self.internal.get_chain_network().clone(), + current_height: h.0, + current_block_time: ts as u32, + internal_index: self.internal.clone(), + ORD_TX_TO_OPERATIONS: Rc::new(RefCell::new((wtx.open_table(crate::index::ORD_TX_TO_OPERATIONS)?))), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: Rc::new(RefCell::new(wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?)), + COLLECTIONS_INSCRIPTION_ID_TO_KINDS: Rc::new(RefCell::new((wtx + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?))), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: Rc::new(RefCell::new((wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?))), + OUTPOINT_TO_ENTRY: Rc::new(RefCell::new((wtx.open_table(OUTPOINT_TO_ENTRY)?))), + BRC20_BALANCES: Rc::new(RefCell::new((wtx.open_table(BRC20_BALANCES)?))), + BRC20_TOKEN: Rc::new(RefCell::new((wtx.open_table(BRC20_TOKEN)?))), + BRC20_EVENTS: Rc::new(RefCell::new((wtx.open_table(BRC20_EVENTS)?))), + BRC20_TRANSFERABLELOG: Rc::new(RefCell::new((wtx.open_table(BRC20_TRANSFERABLELOG)?))), + BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new((wtx.open_table(BRC20_INSCRIBE_TRANSFER)?))), + _marker_a: Default::default(), + }; + Ok(ctx) } pub(crate) fn next_sequence_number(&self) -> crate::Result { todo!() diff --git a/src/index/simulate.rs b/src/index/simulate.rs index d017e17b39..ccc1e6bb14 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -327,12 +327,12 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { fn index_block( &mut self, height: u32, - index:Index, + index: Index, outpoint_sender: &'a mut Sender, tx_out_receiver: &'a mut Receiver, block: BlockData, tx_out_cache: &'a mut SimpleLru, - processor:StorageProcessor<'a, 'db, 'tx>, + processor: StorageProcessor<'a, 'db, 'tx>, operations: &'db mut HashMap>, ) -> crate::Result<()> { let start = Instant::now(); @@ -563,7 +563,36 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { #[test] pub fn test_simulate() { - let internal = Arc::new(Index::open(&Default::default()).unwrap()); + let opt = crate::options::Options { + log_level: Default::default(), + log_dir: None, + bitcoin_data_dir: None, + bitcoin_rpc_pass: Some("bitcoinrpc".to_string()), + bitcoin_rpc_user: Some("bitcoinrpc".to_string()), + chain_argument: Default::default(), + config: None, + config_dir: None, + cookie_file: None, + data_dir: Default::default(), + db_cache_size: None, + lru_size: 0, + first_inscription_height: None, + height_limit: None, + index: None, + index_runes: false, + index_sats: true, + index_transactions: true, + no_index_inscriptions: false, + regtest: true, + rpc_url: None, + signet: false, + testnet: false, + enable_save_ord_receipts: true, + enable_index_bitmap: true, + enable_index_brc20: true, + first_brc20_height: Some(0), + }; + let internal = Arc::new(Index::open(&opt).unwrap()); let sim = Simulator { options: Default::default(), // simulate_index: IndexTracer {}, @@ -572,31 +601,25 @@ pub fn test_simulate() { _marker_b: Default::default(), _marker_tx: Default::default(), }; - let simulate_index = Index::open(&Options { - index: Some(PathBuf::from("./simulate")), - index_runes: false, - index_sats: true, - index_transactions: true, - regtest: true, - enable_index_brc20: true, - ..Default::default() - }).unwrap(); + let mut opt2 = opt.clone(); + opt2.index = Some(PathBuf::from("./simulate")); + let simulate_index = Index::open(&opt2).unwrap(); let mut wtx = simulate_index.begin_write().unwrap(); - - let mut home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS).unwrap(); + let wtx = Rc::new(RefCell::new(wtx)); + let binding = wtx.borrow(); + let mut home_inscriptions = binding.open_table(HOME_INSCRIPTIONS).unwrap(); let mut inscription_id_to_sequence_number = - wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); + binding.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); let mut inscription_number_to_sequence_number = - wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER).unwrap(); - let mut sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); - let mut satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); - let mut sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); + binding.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER).unwrap(); + let mut sat_to_sequence_number = binding.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); + let mut satpoint_to_sequence_number = binding.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); + let mut sequence_number_to_children = binding.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); let mut sequence_number_to_inscription_entry = - wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(); - let mut sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); - let mut transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); - let mut outpoint_to_entry = wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(); - + binding.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(); + let mut sequence_number_to_satpoint = binding.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); + let mut transaction_id_to_transaction = binding.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); + let mut outpoint_to_entry = binding.open_table(OUTPOINT_TO_ENTRY).unwrap(); let processor = StorageProcessor { internal: internal.clone(), // wtx: &mut wtx, diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index 6613bd2b36..5e985c00c9 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -739,41 +739,41 @@ // #[test] // pub fn test_asd() {} // -// #[test] -// fn test_write() { -// let tmpfile = NamedTempFile::new().unwrap(); -// let db = Database::builder() -// .create(tmpfile.path()) -// .unwrap(); -// let table_definition: TableDefinition = TableDefinition::new("x"); -// -// { -// let mut wtx = db.begin_write().unwrap(); -// let mut table = wtx.open_table(table_definition).unwrap(); -// table.insert(1, 1).unwrap(); -// let vv = table.get(&1).unwrap().unwrap().value(); -// assert_eq!(vv, 1); -// } -// -// -// { -// let mut wtx = db.begin_write().unwrap(); -// let mut table = wtx.open_table(table_definition).unwrap(); -// table.insert(2, 2).unwrap(); -// let vv = table.get(&2).unwrap().unwrap().value(); -// assert_eq!(vv, 2); -// let v1 = table.get(&1).unwrap().unwrap().value(); -// assert_eq!(v1, 1); -// } -// -// // wtx.commit().unwrap(); -// // { -// // let rtx = db.begin_read().unwrap(); -// // let table = rtx.open_table(table_definition).unwrap(); -// // assert_eq!(table.get(&1).unwrap().unwrap().value(), 1); -// // } -// } -// +#[test] +fn test_write() { + let tmpfile = NamedTempFile::new().unwrap(); + let db = Database::builder() + .create(tmpfile.path()) + .unwrap(); + let table_definition: TableDefinition = TableDefinition::new("x"); + + { + let mut wtx = db.begin_write().unwrap(); + let mut table = wtx.open_table(table_definition).unwrap(); + table.insert(1, 1).unwrap(); + let vv = table.get(&1).unwrap().unwrap().value(); + assert_eq!(vv, 1); + } + + + { + let mut wtx = db.begin_write().unwrap(); + let mut table = wtx.open_table(table_definition).unwrap(); + table.insert(2, 2).unwrap(); + let vv = table.get(&2).unwrap().unwrap().value(); + assert_eq!(vv, 2); + let v1 = table.get(&1).unwrap().unwrap().value(); + assert_eq!(v1, 1); + } + + // wtx.commit().unwrap(); + // { + // let rtx = db.begin_read().unwrap(); + // let table = rtx.open_table(table_definition).unwrap(); + // assert_eq!(table.get(&1).unwrap().unwrap().value(), 1); + // } +} + ////////// @@ -785,7 +785,8 @@ use std::rc::Rc; use std::sync::Arc; use anyhow::anyhow; use bitcoin::{Network, Txid}; -use redb::{MultimapTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition}; +use redb::{Database, MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; +use tempfile::NamedTempFile; use crate::{Index, InscriptionId, SatPoint}; use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; @@ -798,7 +799,10 @@ use crate::okx::datastore::ScriptKey; use crate::okx::protocol::ContextTrait; pub struct SimulateContext<'a, 'db, 'txn> { - internal_index: Arc, + pub network: Network, + pub current_height: u32, + pub current_block_time: u32, + pub internal_index: Arc, pub(crate) ORD_TX_TO_OPERATIONS: Rc>>, pub(crate) COLLECTIONS_KEY_TO_INSCRIPTION_ID: Rc>>, @@ -1148,15 +1152,15 @@ impl<'a, 'db, 'txn> OrdReader for SimulateContext<'a, 'db, 'txn> { impl<'a, 'db, 'txn> ContextTrait for SimulateContext<'a, 'db, 'txn> { fn block_height(&self) -> u32 { - todo!() + self.current_height } fn network(&self) -> Network { - todo!() + self.network.clone() } fn block_time(&self) -> u32 { - todo!() + self.current_block_time } } From 536e4e73dec585529389c6de750c9243061f9c70 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 09:56:15 +0800 Subject: [PATCH 17/66] add --- src/index.rs | 2 +- src/index/processor.rs | 154 ++++++++++++++++++++++++++++++----- src/index/simulate.rs | 18 ++-- src/okx/protocol/simulate.rs | 5 +- 4 files changed, 149 insertions(+), 30 deletions(-) diff --git a/src/index.rs b/src/index.rs index 1e77ba2083..d2d5e2a4c5 100644 --- a/src/index.rs +++ b/src/index.rs @@ -53,7 +53,7 @@ pub(crate) mod updater; #[cfg(test)] pub(crate) mod testing; mod simulate; -mod processor; +pub mod processor; mod database_processor; const SCHEMA_VERSION: u64 = 16; diff --git a/src/index/processor.rs b/src/index/processor.rs index ce072bc8a2..c4edcccaf1 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -208,20 +208,41 @@ use std::cell::RefCell; use std::marker::PhantomData; +use std::ops::Deref; use std::rc::Rc; use std::sync::Arc; use bitcoin::{OutPoint, TxOut}; -use redb::{MultimapTable, RedbValue, Table, WriteTransaction}; +use redb::{MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; use crate::{Index, InscriptionId, SatPoint}; -use crate::index::entry::SatPointValue; -use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; +use crate::index::entry::{Entry, SatPointValue}; +use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; +use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::protocol::context::Context; use crate::okx::protocol::simulate::SimulateContext; #[derive(Clone)] -pub struct StorageProcessor<'a, 'db, 'tx> { +pub struct IndexWrapper { pub internal: Arc, +} + +impl IndexWrapper { + pub fn use_internal_table(&self, + table_def: TableDefinition, + f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { + let rtx = self.internal.begin_read()?; + let table = rtx.0.open_table(table_def)?; + let ret = f(table); + ret + } + pub fn new(internal: Arc) -> Self { + Self { internal } + } +} + +#[derive(Clone)] +pub struct StorageProcessor<'a, 'db, 'tx> { + pub internal: IndexWrapper, // pub wtx: Rc>>, @@ -235,8 +256,13 @@ pub struct StorageProcessor<'a, 'db, 'tx> { pub(super) satpoint_to_sequence_number: Rc>>, pub(super) sequence_number_to_children: Rc>>, - pub(super) sequence_number_to_entry: Rc>>, pub(super) sequence_number_to_satpoint: Rc>>, + pub(super) sequence_number_to_inscription_entry: Rc>>, + + pub OUTPOINT_TO_SAT_RANGES: Rc>>, + pub sat_to_satpoint: Rc>>, + + pub statistic_to_count: Rc>>, pub _marker_a: PhantomData<&'a ()>, } @@ -250,10 +276,10 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { todo!() } pub(crate) fn create_simulate_context(&self, wtx: &'tx mut WriteTransaction<'db>) -> crate::Result> { - let h = self.internal.block_height().unwrap().unwrap(); - let ts = self.internal.block_time(h).unwrap().timestamp().timestamp(); + let h = self.internal.internal.block_height().unwrap().unwrap(); + let ts = self.internal.internal.block_time(h).unwrap().timestamp().timestamp(); let ctx = SimulateContext { - network: self.internal.get_chain_network().clone(), + network: self.internal.internal.get_chain_network().clone(), current_height: h.0, current_block_time: ts as u32, internal_index: self.internal.clone(), @@ -273,34 +299,120 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { Ok(ctx) } pub(crate) fn next_sequence_number(&self) -> crate::Result { - todo!() + let table = self.sequence_number_to_inscription_entry.borrow(); + let ret: u32 = table + .iter()? + .next_back() + .and_then(|result| result.ok()) + .map(|(number, _id)| number.value() + 1) + .unwrap_or(0); + let v = self.internal.use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| Ok({ + table + .iter()? + .next_back() + .and_then(|result| result.ok()) + .map(|(number, _id)| number.value() + 1) + .unwrap_or(0) + }))?; + if ret > v { + return Ok(ret); + } + Ok(v) } pub(crate) fn outpoint_to_sat_ranges_insert(&self, value: &OutPointValue, data: &[u8]) -> crate::Result<()> { - todo!() + let mut table = self.OUTPOINT_TO_SAT_RANGES.borrow_mut(); + table.insert(value, data)?; + Ok(()) } - pub(crate) fn outpoint_to_sat_ranges_remove(&self, p0: &OutPointValue) -> crate::Result>> { - todo!() + pub(crate) fn outpoint_to_sat_ranges_remove(&self, k: &OutPointValue) -> crate::Result>> { + let mut table = self.OUTPOINT_TO_SAT_RANGES.borrow_mut(); + let ret: Vec = table.remove(k)?.map(|ranges| ranges.value().to_vec()).unwrap_or_default(); + return Ok(Some(ret)); } + pub fn get_lost_sats(&self) -> crate::Result { - todo!() + let table = self.statistic_to_count.borrow(); + let ret = table + .get(&Statistic::LostSats.key())? + .map(|lost_sats| lost_sats.value()) + .unwrap_or(0); + if ret == 0 { + let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ + table + .get(&Statistic::LostSats.key())? + .map(|lost_sats| lost_sats.value()) + .unwrap_or(0) + }))?; + return Ok(ret); + } + return Ok(ret); } pub fn get_cursed_inscription_count(&self) -> crate::Result { - todo!() + let table = self.statistic_to_count.borrow(); + let ret = table + .get(&Statistic::CursedInscriptions.key())? + .map(|count| count.value()) + .unwrap_or(0); + if ret != 0 { + return Ok(ret); + } + let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ + table + .get(&Statistic::CursedInscriptions.key())? + .map(|count| count.value()) + .unwrap_or(0) + }))?; + return Ok(ret); } pub fn get_blessed_inscription_count(&self) -> crate::Result { - todo!() + let table = self.statistic_to_count.borrow(); + let ret = table + .get(&Statistic::BlessedInscriptions.key())? + .map(|count| count.value()) + .unwrap_or(0); + if ret != 0 { + return Ok(ret); + } + let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ + table + .get(&Statistic::BlessedInscriptions.key())? + .map(|count| count.value()) + .unwrap_or(0) + }))?; + Ok(ret) } pub fn get_unbound_inscriptions(&self) -> crate::Result { - todo!() - } - pub fn get_next_sequence_number(&self) -> crate::Result { - todo!() + let table = self.statistic_to_count.borrow(); + let ret = table + .get(&Statistic::UnboundInscriptions.key())? + .map(|unbound_inscriptions| unbound_inscriptions.value()) + .unwrap_or(0); + if ret > 0 { + return Ok(ret); + } + let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ + table + .get(&Statistic::UnboundInscriptions.key())? + .map(|count| count.value()) + .unwrap_or(0) + }))?; + Ok(ret) } pub fn sat_to_satpoint_insert(&self, key: &u64, value: &SatPointValue) -> crate::Result<()> { - todo!() + let mut table = self.sat_to_satpoint.borrow_mut(); + table.insert(key, value)?; + Ok(()) } pub fn get_txout_by_outpoint(&self, x: &OutPoint) -> crate::Result> { - todo!() + let bindind = self.outpoint_to_entry.borrow(); + let ret = get_txout_by_outpoint(bindind.deref(), x)?; + if let Some(ret) = ret { + return Ok(Some(ret)); + } + let ret = self.internal.use_internal_table(OUTPOINT_TO_ENTRY, |table| { + get_txout_by_outpoint(&table, x) + })?; + Ok(ret) } pub(crate) fn satpoint_to_sequence_number_remove_all(&self, v: &SatPointValue) -> crate::Result<()> { // self diff --git a/src/index/simulate.rs b/src/index/simulate.rs index ccc1e6bb14..73674a212e 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -15,7 +15,7 @@ use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; use crate::height::Height; use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; use crate::index::entry::{Entry, SatPointValue, SatRange}; -use crate::index::processor::StorageProcessor; +use crate::index::processor::{IndexWrapper, StorageProcessor}; use crate::index::updater::pending_updater::PendingUpdater; use crate::okx::datastore::cache::CacheWriter; use crate::okx::datastore::ord::InscriptionOp; @@ -28,7 +28,7 @@ use crate::okx::protocol::trace::IndexTracer; pub struct Simulator<'a, 'db, 'tx> { pub options: Options, // pub simulate_index: IndexTracer, - pub internal_index: Arc, + pub internal_index: IndexWrapper, _marker_a: PhantomData<&'a ()>, _marker_b: PhantomData<&'db ()>, _marker_tx: PhantomData<&'tx ()>, @@ -406,10 +406,10 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { let mut inscription_updater = PendingUpdater::new( operations, blessed_inscription_count, - self.internal_index.options.chain(), + self.internal_index.internal.options.chain(), cursed_inscription_count, height, - self.internal_index.index_transactions, + self.internal_index.internal.index_transactions, next_sequence_number, lost_sats, block.header.time, @@ -592,7 +592,7 @@ pub fn test_simulate() { enable_index_brc20: true, first_brc20_height: Some(0), }; - let internal = Arc::new(Index::open(&opt).unwrap()); + let internal = IndexWrapper::new(Arc::new(Index::open(&opt).unwrap())); let sim = Simulator { options: Default::default(), // simulate_index: IndexTracer {}, @@ -620,6 +620,9 @@ pub fn test_simulate() { let mut sequence_number_to_satpoint = binding.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); let mut transaction_id_to_transaction = binding.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); let mut outpoint_to_entry = binding.open_table(OUTPOINT_TO_ENTRY).unwrap(); + let mut OUTPOINT_TO_SAT_RANGES_table = binding.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); + let sat_to_point = binding.open_table(SAT_TO_SATPOINT).unwrap(); + let statis_to_count = binding.open_table(STATISTIC_TO_COUNT).unwrap(); let processor = StorageProcessor { internal: internal.clone(), // wtx: &mut wtx, @@ -631,8 +634,11 @@ pub fn test_simulate() { sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), - sequence_number_to_entry: Rc::new(RefCell::new(sequence_number_to_inscription_entry)), sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), + sequence_number_to_inscription_entry: Rc::new(RefCell::new((sequence_number_to_inscription_entry))), + OUTPOINT_TO_SAT_RANGES: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), + sat_to_satpoint: Rc::new(RefCell::new((sat_to_point))), + statistic_to_count: Rc::new(RefCell::new((statis_to_count))), _marker_a: Default::default(), }; } \ No newline at end of file diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index 5e985c00c9..f76417dc17 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -789,6 +789,7 @@ use redb::{Database, MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbV use tempfile::NamedTempFile; use crate::{Index, InscriptionId, SatPoint}; use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; +use crate::index::processor::IndexWrapper; use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick, insert_inscribe_transfer_inscription, insert_token_info, insert_transferable, remove_inscribe_transfer_inscription, remove_transferable, save_transaction_receipts, update_token_balance}; use crate::okx::datastore::cache::CacheWriter; @@ -802,7 +803,7 @@ pub struct SimulateContext<'a, 'db, 'txn> { pub network: Network, pub current_height: u32, pub current_block_time: u32, - pub internal_index: Arc, + pub internal_index: IndexWrapper, pub(crate) ORD_TX_TO_OPERATIONS: Rc>>, pub(crate) COLLECTIONS_KEY_TO_INSCRIPTION_ID: Rc>>, @@ -1168,7 +1169,7 @@ impl<'a, 'db, 'txn> SimulateContext<'a, 'db, 'txn> { fn use_internal_table(&self, table_def: TableDefinition, f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { - let rtx = self.internal_index.begin_read()?; + let rtx = self.internal_index.internal.begin_read()?; let table = rtx.0.open_table(table_def)?; let ret = f(table); ret From 47b6fd7061697d54781cd3b3f73e92ada943dca4 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:03:33 +0800 Subject: [PATCH 18/66] add --- src/index/processor.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/index/processor.rs b/src/index/processor.rs index c4edcccaf1..ec97e9d24a 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -215,7 +215,7 @@ use bitcoin::{OutPoint, TxOut}; use redb::{MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; use crate::{Index, InscriptionId, SatPoint}; use crate::index::entry::{Entry, SatPointValue}; -use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; +use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::protocol::context::Context; @@ -415,14 +415,19 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { Ok(ret) } pub(crate) fn satpoint_to_sequence_number_remove_all(&self, v: &SatPointValue) -> crate::Result<()> { - // self - // .satpoint_to_sequence_number - // .remove_all(v)?; - // Ok(()) - todo!() + let mut table = self.satpoint_to_sequence_number.borrow_mut(); + table + .remove_all(v)?; + Ok(()) } pub(crate) fn home_inscriptions_len(&self) -> u64 { - todo!() + let table = self.home_inscriptions.borrow(); + let sim = table.len().unwrap(); + let ret = self.internal.use_internal_table(HOME_INSCRIPTIONS, |table| { + // TODO + Ok(table.len().unwrap()) + }).unwrap(); + return sim + ret; } pub(crate) fn sequence_number_to_satpoint_insert(&self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { let mut table = self.sequence_number_to_satpoint.borrow_mut(); From e65f7d3ac2306ca470bca50e9d12586e20a3e3f4 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:31:31 +0800 Subject: [PATCH 19/66] pro --- src/index/processor.rs | 60 +++++++++++++++++++++++++++++------------- src/sat_point.rs | 2 +- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/index/processor.rs b/src/index/processor.rs index ec97e9d24a..bd32d026f3 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -207,6 +207,7 @@ use std::cell::RefCell; +use std::collections::HashSet; use std::marker::PhantomData; use std::ops::Deref; use std::rc::Rc; @@ -215,7 +216,7 @@ use bitcoin::{OutPoint, TxOut}; use redb::{MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; use crate::{Index, InscriptionId, SatPoint}; use crate::index::entry::{Entry, SatPointValue}; -use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; +use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::protocol::context::Context; @@ -480,9 +481,9 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // v.insert(key.to_vec(), value.to_vec()); // }); // Ok(()) - // self - // .id_to_sequence_number - // .insert(value, sequence_number)?; + let mut table = self.id_to_sequence_number.borrow_mut(); + table + .insert(value, sequence_number)?; Ok(()) } pub(crate) fn sequence_number_to_children_insert(&self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { @@ -492,9 +493,8 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // v.insert(key.to_vec(), value.to_vec()); // }); // Ok(()) - // self - // .sequence_number_to_children - // .insert(parent_sequence_number, sequence_number)?; + let mut table = self.sequence_number_to_children.borrow_mut(); + table.insert(parent_sequence_number, sequence_number)?; Ok(()) } pub(crate) fn sequence_number_to_entry_insert(&self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { @@ -504,7 +504,8 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // v.insert(key.to_vec(), value.to_vec()); // }); // Ok(()) - // self.sequence_number_to_entry.insert(sequence, value)?; + let mut table = self.sequence_number_to_inscription_entry.borrow_mut(); + table.insert(sequence, value)?; Ok(()) } pub(crate) fn sat_to_sequence_number_insert(&self, n: &u64, sequence_number: &u32) -> crate::Result<()> { @@ -514,7 +515,8 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // v.insert(key.to_vec(), value.to_vec()); // }); // Ok(()) - // self.sat_to_sequence_number.insert(n, sequence_number)?; + let mut table = self.sat_to_sequence_number.borrow_mut(); + table.insert(n, sequence_number)?; Ok(()) } pub(crate) fn inscription_number_to_sequence_number_insert(&self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { @@ -524,9 +526,8 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // v.insert(key.to_vec(), value.to_vec()); // }); // Ok(()) - // self - // .inscription_number_to_sequence_number - // .insert(inscription_number, sequence_number)?; + let mut table = self.inscription_number_to_sequence_number.borrow_mut(); + table.insert(inscription_number, sequence_number)?; Ok(()) } pub(crate) fn outpoint_to_entry_insert(&self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { @@ -541,12 +542,35 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // Ok(()) } pub fn inscriptions_on_output(&self, prev_output: &OutPoint) -> crate::Result> { - // let ret = Index::inscriptions_on_output( - // self.satpoint_to_sequence_number, - // self.sequence_number_to_entry, - // prev_output.clone())?; - // TODO: twice - todo!() + let table = self.satpoint_to_sequence_number.borrow(); + let satpoint_to_sequence_number = table.deref(); + + let table = self.sequence_number_to_inscription_entry.borrow(); + let sequence_number_to_entry = table.deref(); + let ret = Index::inscriptions_on_output( + satpoint_to_sequence_number, + sequence_number_to_entry, + prev_output.clone())?; + + let mut set: HashSet<(SatPoint, InscriptionId)> = ret.into_iter() + .map(|(k, v)| { + (k, v) + }).collect(); + + let rtx = self.internal.internal.begin_read()?; + let satpoint_to_sequence_number = rtx.0.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; + let sequence_number_to_entry = rtx.0.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; + let ret = Index::inscriptions_on_output( + &satpoint_to_sequence_number, + &sequence_number_to_entry, + prev_output.clone())?; + for node in ret { + if set.contains(&node) { + continue; + } + set.insert(node); + } + Ok(set.into_iter().collect()) } pub(crate) fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { diff --git a/src/sat_point.rs b/src/sat_point.rs index 75c034cf82..2065dd31db 100644 --- a/src/sat_point.rs +++ b/src/sat_point.rs @@ -1,6 +1,6 @@ use super::*; -#[derive(Debug, PartialEq, Copy, Clone, Eq, PartialOrd, Ord, Default)] +#[derive(Debug, PartialEq, Copy, Clone, Eq, PartialOrd, Ord, Default,Hash)] pub struct SatPoint { pub outpoint: OutPoint, pub offset: u64, From 3223dc43d18930e94023a9c1b2e895ba9e24b4a5 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:53:59 +0800 Subject: [PATCH 20/66] add --- src/index/processor.rs | 59 +++++++++++++++++++--------- src/index/updater/pending_updater.rs | 6 +-- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/index/processor.rs b/src/index/processor.rs index bd32d026f3..601967ee43 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -212,11 +212,12 @@ use std::marker::PhantomData; use std::ops::Deref; use std::rc::Rc; use std::sync::Arc; +use anyhow::anyhow; use bitcoin::{OutPoint, TxOut}; use redb::{MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; use crate::{Index, InscriptionId, SatPoint}; use crate::index::entry::{Entry, SatPointValue}; -use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; +use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::protocol::context::Context; @@ -574,27 +575,49 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { } pub(crate) fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { - // self - // .transaction_id_to_transaction - // .insert(tx_id, value)?; - + let mut table = self.transaction_id_to_transaction.borrow_mut(); + table.insert(tx_id, value)?; Ok(()) } - pub(crate) fn id_to_sequence_number_get(&self, x: InscriptionIdValue) -> crate::Result> { - // TODO,twice - // let ret = self.id_to_sequence_number.get(x)?.unwrap().value(); - // Ok(Some(ret)) - todo!() + pub(crate) fn id_to_sequence_number_get(&self, x: &InscriptionIdValue) -> crate::Result> { + let table = self.id_to_sequence_number.borrow(); + let v = table.get(x)?; + if let Some(v) = v { + return Ok(Some(v.value())); + } + let ret = self.internal.use_internal_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |table| { + let value=table.get(x).map_err(|e|{ + anyhow!("id_to_sequence_number_get error:{}",e) + })?; + if let Some(value) = value { + return Ok(Some(value.value())); + } + return Ok(None); + })?; + if let Some(ret) = ret { + return Ok(Some(ret)); + } + Ok(None) } pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { - // TODO: twice - // let ret = self - // .sequence_number_to_entry - // .get(initial_inscription_sequence_number)? - // .unwrap() - // .value(); - // Ok(Some(ret)) - todo!() + let table = self.sequence_number_to_inscription_entry.borrow(); + let value = table.get(initial_inscription_sequence_number)?; + if let Some(v) = value { + return Ok(Some(v.value())); + } + let ret = self.internal.use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| { + let ret=table.get(initial_inscription_sequence_number).map_err(move |e| { + anyhow!("sequence_number_to_entry_get error:{}",e) + })?; + if let Some(ret)=ret{ + return Ok(Some(ret.value())) + } + return Ok(None) + })?; + if let Some(ret) = ret { + return Ok(Some(ret)); + } + Ok(None) } } \ No newline at end of file diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index a51b93fafa..04d42daba5 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -163,7 +163,7 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { Some(crate::index::updater::inscription_updater::Curse::Reinscription) } else { let initial_inscription_sequence_number = - self.processor.id_to_sequence_number_get(id.store())?.unwrap(); + self.processor.id_to_sequence_number_get(&id.store())?.unwrap(); let entry = InscriptionEntry::load(self.processor.sequence_number_to_entry_get(initial_inscription_sequence_number)?.unwrap()); @@ -414,7 +414,7 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { false, self .processor.id_to_sequence_number_get( - inscription_id.store())? + &inscription_id.store())? .unwrap() ) } @@ -503,7 +503,7 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { Some(parent_id) => { let parent_sequence_number = self .processor.id_to_sequence_number_get( - parent_id.store())? + &parent_id.store())? .unwrap(); self .processor.sequence_number_to_children_insert( From 30bf5751e4c380c928308a483c173ee798547c85 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 11:18:33 +0800 Subject: [PATCH 21/66] add --- src/index/simulate.rs | 159 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 158 insertions(+), 1 deletion(-) diff --git a/src/index/simulate.rs b/src/index/simulate.rs index 73674a212e..170fc57a8d 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -324,6 +324,161 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { // Ok(()) // } + // fn execute_tx(&mut self,processor: StorageProcessor<'a, 'db, 'tx>,tx:&Transaction)-> crate::Result<()> { + // let start = Instant::now(); + // let mut sat_ranges_written = 0; + // let mut outputs_in_block = 0; + // + // // If value_receiver still has values something went wrong with the last block + // // Could be an assert, shouldn't recover from this and commit the last block + // + // let index_inscriptions = true; + // + // let fetching_outputs_count = AtomicUsize::new(0); + // let total_outputs_count = AtomicUsize::new(0); + // let cache_outputs_count = AtomicUsize::new(0); + // let miss_outputs_count = AtomicUsize::new(0); + // let meet_outputs_count = AtomicUsize::new(0); + // if index_inscriptions { + // // Send all missing input outpoints to be fetched right away + // let txids =tx.txid(); + // use rayon::prelude::*; + // let tx_outs = block + // .txdata + // .par_iter() + // .flat_map(|(tx, _)| tx.input.par_iter()) + // .filter_map(|input| { + // total_outputs_count.fetch_add(1, Ordering::Relaxed); + // let prev_output = input.previous_output; + // // We don't need coinbase input value + // if prev_output.is_null() { + // None + // } else if txids.contains(&prev_output.txid) { + // meet_outputs_count.fetch_add(1, Ordering::Relaxed); + // None + // } else if tx_out_cache.contains(&prev_output) { + // cache_outputs_count.fetch_add(1, Ordering::Relaxed); + // None + // } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output).unwrap() + // { + // miss_outputs_count.fetch_add(1, Ordering::Relaxed); + // Some((prev_output, Some(txout))) + // } else { + // fetching_outputs_count.fetch_add(1, Ordering::Relaxed); + // Some((prev_output, None)) + // } + // }) + // .collect::>(); + // for (out_point, value) in tx_outs.into_iter() { + // if let Some(tx_out) = value { + // tx_out_cache.insert(out_point, tx_out); + // } else { + // outpoint_sender.blocking_send(out_point).unwrap(); + // } + // } + // } + // + // let mut lost_sats = processor.get_lost_sats()?; + // let cursed_inscription_count = processor.get_cursed_inscription_count()?; + // let blessed_inscription_count = processor.get_blessed_inscription_count()?; + // let unbound_inscriptions = processor.get_unbound_inscriptions()?; + // let next_sequence_number = processor.next_sequence_number()?; + // + // // let processor = &mut self.processor; + // let mut inscription_updater = PendingUpdater::new( + // operations, + // blessed_inscription_count, + // self.internal_index.internal.options.chain(), + // cursed_inscription_count, + // height, + // self.internal_index.internal.index_transactions, + // next_sequence_number, + // lost_sats, + // block.header.time, + // unbound_inscriptions, + // tx_out_receiver, + // tx_out_cache, + // processor.clone(), + // )?; + // + // let index_sats = true; + // if index_sats { + // let mut coinbase_inputs = VecDeque::new(); + // + // let h = Height(height); + // if h.subsidy() > 0 { + // let start = h.starting_sat(); + // coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); + // } + // + // for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { + // log::trace!("Indexing transaction {tx_offset}…"); + // + // let mut input_sat_ranges = VecDeque::new(); + // + // self.index_transaction_sats( + // tx, + // *txid, + // &mut input_sat_ranges, + // &mut sat_ranges_written, + // &mut outputs_in_block, + // &mut inscription_updater, + // index_inscriptions, + // )?; + // + // coinbase_inputs.extend(input_sat_ranges); + // } + // + // if let Some((tx, txid)) = block.txdata.first() { + // self.index_transaction_sats( + // tx, + // *txid, + // &mut coinbase_inputs, + // &mut sat_ranges_written, + // &mut outputs_in_block, + // &mut inscription_updater, + // index_inscriptions, + // )?; + // } + // + // if !coinbase_inputs.is_empty() { + // let mut lost_sat_ranges = processor.outpoint_to_sat_ranges_remove(&OutPoint::null().store())?.map(|ranges| ranges.to_vec()) + // .unwrap_or_default(); + // + // for (start, end) in coinbase_inputs { + // if !Sat(start).common() { + // processor.sat_to_satpoint_insert( + // &start, + // &SatPoint { + // outpoint: OutPoint::null(), + // offset: lost_sats, + // } + // .store(), + // )?; + // } + // + // lost_sat_ranges.extend_from_slice(&(start, end).store()); + // + // lost_sats += end - start; + // } + // processor.outpoint_to_sat_ranges_insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; + // } + // } else if index_inscriptions { + // for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { + // inscription_updater.index_envelopes(tx, *txid, None)?; + // } + // } + // inscription_updater.flush_cache()?; + // + // // // TODO: + // let mut context = processor.create_context()?; + // // // // Create a protocol manager to index the block of bitmap data. + // let config = ProtocolConfig::new_with_options(&index.options); + // ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; + // + // Ok(()) + // } + fn index_block( &mut self, height: u32, @@ -593,7 +748,7 @@ pub fn test_simulate() { first_brc20_height: Some(0), }; let internal = IndexWrapper::new(Arc::new(Index::open(&opt).unwrap())); - let sim = Simulator { + let mut sim = Simulator { options: Default::default(), // simulate_index: IndexTracer {}, internal_index: internal.clone(), @@ -641,4 +796,6 @@ pub fn test_simulate() { statistic_to_count: Rc::new(RefCell::new((statis_to_count))), _marker_a: Default::default(), }; + + sim.index_block() } \ No newline at end of file From a3a79273c92bb3edc56c2643e1bcd0e1700c5882 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 11:21:16 +0800 Subject: [PATCH 22/66] add dep --- Cargo.lock | 478 ++++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 2 +- 2 files changed, 473 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 05754ec1d4..30ac97a489 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -164,6 +164,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + [[package]] name = "async-channel" version = "2.1.1" @@ -317,6 +328,19 @@ dependencies = [ "utf-8", ] +[[package]] +name = "asynchronous-codec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a860072022177f903e59730004fb5dc13db9275b79bb2aef7ba8ce831956c233" +dependencies = [ + "bytes", + "futures-sink", + "futures-util", + "memchr", + "pin-project-lite", +] + [[package]] name = "atom_syndication" version = "0.12.2" @@ -344,6 +368,18 @@ dependencies = [ "reqwest", ] +[[package]] +name = "auto_impl" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -453,6 +489,18 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +[[package]] +name = "bigdecimal" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", + "serde", +] + [[package]] name = "bigdecimal" version = "0.4.2" @@ -513,6 +561,32 @@ dependencies = [ "serde", ] +[[package]] +name = "bitcoincore-rpc" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6c0ee9354e3dac217db4cb1dd31941073a87fe53c86bcf3eb2b8bc97f00a08" +dependencies = [ + "bitcoin-private", + "bitcoincore-rpc-json", + "jsonrpc", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "bitcoincore-rpc-json" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d30ce6f40fb0a2e8d98522796219282504b7a4b14e2b4c26139a7bea6aec6586" +dependencies = [ + "bitcoin", + "bitcoin-private", + "serde", + "serde_json", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -540,7 +614,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel", + "async-channel 2.1.1", "async-lock 3.2.0", "async-task", "fastrand 2.0.1", @@ -595,6 +669,12 @@ dependencies = [ "serde", ] +[[package]] +name = "build_const" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" + [[package]] name = "bumpalo" version = "3.14.0" @@ -809,6 +889,17 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "core_affinity" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622892f5635ce1fc38c8f16dfc938553ed64af482edb5e150bf4caedbfcb2304" +dependencies = [ + "libc", + "num_cpus", + "winapi", +] + [[package]] name = "cpufeatures" version = "0.2.11" @@ -818,6 +909,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +dependencies = [ + "build_const", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -863,6 +963,28 @@ dependencies = [ "itertools", ] +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.4" @@ -885,6 +1007,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.18" @@ -894,6 +1025,12 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -910,7 +1047,7 @@ version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" dependencies = [ - "nix", + "nix 0.27.1", "windows-sys 0.52.0", ] @@ -984,6 +1121,19 @@ dependencies = [ "syn 2.0.46", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if 1.0.0", + "hashbrown 0.14.3", + "lock_api", + "once_cell", + "parking_lot_core 0.9.9", +] + [[package]] name = "data-encoding" version = "2.5.0" @@ -1131,6 +1281,12 @@ dependencies = [ "syn 2.0.46", ] +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + [[package]] name = "either" version = "1.9.0" @@ -1171,6 +1327,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + [[package]] name = "errno" version = "0.3.8" @@ -1181,6 +1348,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -1229,6 +1406,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "static_assertions", +] + [[package]] name = "flate2" version = "1.0.28" @@ -1269,6 +1455,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "futures" version = "0.3.30" @@ -1394,6 +1590,19 @@ dependencies = [ "slab", ] +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows 0.48.0", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1714,6 +1923,47 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "impl-num-traits" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "951641f13f873bff03d4bf19ae8bec531935ac0ac2cc775f84d7edfdcfed3f17" +dependencies = [ + "integer-sqrt", + "num-traits", + "uint", +] + +[[package]] +name = "indexer-sdk" +version = "0.1.0" +source = "git+https://github.com/ItsFunny/indexer-sdk.git#1e6751f0ac9e077dca558c0344c541237f61a26f" +dependencies = [ + "async-channel 1.9.0", + "async-trait", + "auto_impl", + "bigdecimal 0.3.1", + "bitcoincore-rpc", + "chrono", + "crossbeam", + "downcast-rs", + "env_logger", + "hex", + "log", + "log4rs", + "may", + "once_cell", + "primitive-types", + "rustc-serialize", + "rusty-leveldb", + "serde", + "serde_json", + "thiserror", + "tokio", + "wg", + "zeromq", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -1757,6 +2007,21 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "integer-encoding" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + [[package]] name = "io-lifetimes" version = "1.0.11" @@ -2034,12 +2299,55 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "may" +version = "0.3.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f1b6d76280e56d1c65b8d0a9a7f05d0b730ff0463110ea82bc999838d6f7369" +dependencies = [ + "core_affinity", + "crossbeam", + "generator", + "lazy_static", + "libc", + "log", + "may_queue", + "miow", + "nix 0.26.4", + "num_cpus", + "parking_lot 0.12.1", + "rustversion", + "smallvec", + "socket2 0.5.5", + "windows-sys 0.42.0", +] + +[[package]] +name = "may_queue" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f6fa598a71c1f6d55b09fdb508d256c301e458ea544457c7f0fa8ee64b0676c" +dependencies = [ + "crossbeam-utils", + "rustversion", + "smallvec", +] + [[package]] name = "memchr" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -2092,6 +2400,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "miow" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ffbca2f655e33c08be35d87278e5b18b89550a37dbd598c20db92f6a471123" +dependencies = [ + "windows-sys 0.42.0", +] + [[package]] name = "mp4" version = "0.14.0" @@ -2151,6 +2468,19 @@ dependencies = [ "unicase", ] +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if 1.0.0", + "libc", + "memoffset", + "pin-utils", +] + [[package]] name = "nix" version = "0.27.1" @@ -2339,7 +2669,7 @@ dependencies = [ "axum-server", "base64 0.21.5", "bech32", - "bigdecimal", + "bigdecimal 0.4.2", "bip39", "bitcoin", "boilerplate", @@ -2359,6 +2689,7 @@ dependencies = [ "http 0.2.11", "humantime", "hyper", + "indexer-sdk", "indicatif", "lazy_static", "log", @@ -2628,6 +2959,17 @@ dependencies = [ "yansi", ] +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-num-traits", + "uint", +] + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -2973,6 +3315,12 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-serialize" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe834bc780604f4674073badbad26d7219cadfb4a2275802db12cbae17498401" + [[package]] name = "rustc_version" version = "0.4.0" @@ -2998,7 +3346,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", - "errno", + "errno 0.3.8", "io-lifetimes", "libc", "linux-raw-sys 0.3.8", @@ -3012,7 +3360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ "bitflags 2.4.1", - "errno", + "errno 0.3.8", "libc", "linux-raw-sys 0.4.12", "windows-sys 0.52.0", @@ -3115,6 +3463,20 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +[[package]] +name = "rusty-leveldb" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3453f8c92d48f99810f59095444eda0622ae8485ac899ad97a574fd7cb9aa9c4" +dependencies = [ + "crc", + "errno 0.2.8", + "fs2", + "integer-encoding", + "rand", + "snap", +] + [[package]] name = "ryu" version = "1.0.16" @@ -3339,6 +3701,15 @@ dependencies = [ "tzdb", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.9" @@ -3354,6 +3725,12 @@ version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +[[package]] +name = "snap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" + [[package]] name = "socket2" version = "0.4.10" @@ -3386,6 +3763,12 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.10.0" @@ -3472,7 +3855,7 @@ dependencies = [ "ntapi", "once_cell", "rayon", - "windows", + "windows 0.52.0", ] [[package]] @@ -3631,7 +4014,9 @@ dependencies = [ "libc", "mio", "num_cpus", + "parking_lot 0.12.1", "pin-project-lite", + "signal-hook-registry", "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", @@ -3826,6 +4211,18 @@ dependencies = [ "tz-rs", ] +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unicase" version = "2.7.0" @@ -3948,6 +4345,15 @@ dependencies = [ "syn 2.0.46", ] +[[package]] +name = "uuid" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +dependencies = [ + "getrandom", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -4073,6 +4479,15 @@ version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +[[package]] +name = "wg" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "232b936590098c53587078a25ed087d5cd3aa18ec65c85bb42c6ae335263e15b" +dependencies = [ + "atomic-waker", +] + [[package]] name = "winapi" version = "0.3.9" @@ -4104,6 +4519,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows" version = "0.52.0" @@ -4123,6 +4547,21 @@ dependencies = [ "windows-targets 0.52.0", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -4378,3 +4817,30 @@ name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" + +[[package]] +name = "zeromq" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2db35fbc7d9082d39a85c9831ec5dc7b7b135038d2f00bb5ff2a4c0275893da1" +dependencies = [ + "async-trait", + "asynchronous-codec", + "bytes", + "crossbeam-queue", + "dashmap", + "futures-channel", + "futures-io", + "futures-task", + "futures-util", + "log", + "num-traits", + "once_cell", + "parking_lot 0.12.1", + "rand", + "regex", + "thiserror", + "tokio", + "tokio-util 0.7.10", + "uuid", +] diff --git a/Cargo.toml b/Cargo.toml index 634ae8db32..c563977cef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,7 +74,7 @@ log4rs = { version = "1.2.0", features = ["gzip"] } once_cell = "1.19.0" rmp-serde = "1.1.2" rayon = "1.8.0" - +indexer-sdk={git="https://github.com/ItsFunny/indexer-sdk.git"} [dev-dependencies] criterion = "0.5.1" executable-path = "1.0.0" From 0d256f76fa807fcc8e20666d584febd7e74d9edd Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 12:20:53 +0800 Subject: [PATCH 23/66] add --- Cargo.lock | 29 +---- Cargo.toml | 3 +- src/index/processor.rs | 18 ++- src/index/simulate.rs | 181 ++------------------------- src/index/updater/pending_updater.rs | 19 +-- 5 files changed, 31 insertions(+), 219 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 30ac97a489..5a6e7d1a6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -561,32 +561,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitcoincore-rpc" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6c0ee9354e3dac217db4cb1dd31941073a87fe53c86bcf3eb2b8bc97f00a08" -dependencies = [ - "bitcoin-private", - "bitcoincore-rpc-json", - "jsonrpc", - "log", - "serde", - "serde_json", -] - -[[package]] -name = "bitcoincore-rpc-json" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d30ce6f40fb0a2e8d98522796219282504b7a4b14e2b4c26139a7bea6aec6586" -dependencies = [ - "bitcoin", - "bitcoin-private", - "serde", - "serde_json", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -1937,13 +1911,11 @@ dependencies = [ [[package]] name = "indexer-sdk" version = "0.1.0" -source = "git+https://github.com/ItsFunny/indexer-sdk.git#1e6751f0ac9e077dca558c0344c541237f61a26f" dependencies = [ "async-channel 1.9.0", "async-trait", "auto_impl", "bigdecimal 0.3.1", - "bitcoincore-rpc", "chrono", "crossbeam", "downcast-rs", @@ -1953,6 +1925,7 @@ dependencies = [ "log4rs", "may", "once_cell", + "ord-bitcoincore-rpc", "primitive-types", "rustc-serialize", "rusty-leveldb", diff --git a/Cargo.toml b/Cargo.toml index c563977cef..176a736ba4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,7 +74,8 @@ log4rs = { version = "1.2.0", features = ["gzip"] } once_cell = "1.19.0" rmp-serde = "1.1.2" rayon = "1.8.0" -indexer-sdk={git="https://github.com/ItsFunny/indexer-sdk.git"} +#indexer-sdk={git="https://github.com/ItsFunny/indexer-sdk.git"} +indexer-sdk={path="/Users/lvcong/RustroverProjects/indexer-sdk"} [dev-dependencies] criterion = "0.5.1" executable-path = "1.0.0" diff --git a/src/index/processor.rs b/src/index/processor.rs index 601967ee43..77c79cd789 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -213,7 +213,12 @@ use std::ops::Deref; use std::rc::Rc; use std::sync::Arc; use anyhow::anyhow; -use bitcoin::{OutPoint, TxOut}; +use bitcoin::{OutPoint, Transaction, Txid, TxOut}; +use indexer_sdk::client::drect::DirectClient; +use indexer_sdk::client::SyncClient; +use indexer_sdk::storage::db::memory::MemoryDB; +use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; +use indexer_sdk::storage::kv::KVStorageProcessor; use redb::{MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; use crate::{Index, InscriptionId, SatPoint}; use crate::index::entry::{Entry, SatPointValue}; @@ -222,7 +227,7 @@ use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::protocol::context::Context; use crate::okx::protocol::simulate::SimulateContext; - +use crate::RpcApi; #[derive(Clone)] pub struct IndexWrapper { pub internal: Arc, @@ -266,6 +271,8 @@ pub struct StorageProcessor<'a, 'db, 'tx> { pub statistic_to_count: Rc>>, pub _marker_a: PhantomData<&'a ()>, + + pub client:Option>>>, } unsafe impl<'a, 'db, 'tx> Send for StorageProcessor<'a, 'db, 'tx> {} @@ -277,6 +284,13 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { pub(crate) fn create_context(&self) -> crate::Result { todo!() } + + pub fn get_transaction(&self,tx_id:&Txid)->crate::Result{ + let client=self.client.as_ref().unwrap(); + let client=client.get_btc_client(); + let tx=client.get_raw_transaction(tx_id,None)?; + Ok(tx) + } pub(crate) fn create_simulate_context(&self, wtx: &'tx mut WriteTransaction<'db>) -> crate::Result> { let h = self.internal.internal.block_height().unwrap().unwrap(); let ts = self.internal.internal.block_time(h).unwrap().timestamp().timestamp(); diff --git a/src/index/simulate.rs b/src/index/simulate.rs index 170fc57a8d..0690510487 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -5,12 +5,10 @@ use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::time::Instant; use anyhow::anyhow; use bitcoin::{OutPoint, Transaction, Txid, TxOut}; +use indexer_sdk::client::SyncClient; use redb::{ReadableTable}; -use tokio::sync::mpsc::{Receiver, Sender}; -use tokio::sync::mpsc::error::TryRecvError; use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; use crate::height::Height; use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; @@ -324,182 +322,19 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { // Ok(()) // } - // fn execute_tx(&mut self,processor: StorageProcessor<'a, 'db, 'tx>,tx:&Transaction)-> crate::Result<()> { - // let start = Instant::now(); - // let mut sat_ranges_written = 0; - // let mut outputs_in_block = 0; - // - // // If value_receiver still has values something went wrong with the last block - // // Could be an assert, shouldn't recover from this and commit the last block - // - // let index_inscriptions = true; - // - // let fetching_outputs_count = AtomicUsize::new(0); - // let total_outputs_count = AtomicUsize::new(0); - // let cache_outputs_count = AtomicUsize::new(0); - // let miss_outputs_count = AtomicUsize::new(0); - // let meet_outputs_count = AtomicUsize::new(0); - // if index_inscriptions { - // // Send all missing input outpoints to be fetched right away - // let txids =tx.txid(); - // use rayon::prelude::*; - // let tx_outs = block - // .txdata - // .par_iter() - // .flat_map(|(tx, _)| tx.input.par_iter()) - // .filter_map(|input| { - // total_outputs_count.fetch_add(1, Ordering::Relaxed); - // let prev_output = input.previous_output; - // // We don't need coinbase input value - // if prev_output.is_null() { - // None - // } else if txids.contains(&prev_output.txid) { - // meet_outputs_count.fetch_add(1, Ordering::Relaxed); - // None - // } else if tx_out_cache.contains(&prev_output) { - // cache_outputs_count.fetch_add(1, Ordering::Relaxed); - // None - // } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output).unwrap() - // { - // miss_outputs_count.fetch_add(1, Ordering::Relaxed); - // Some((prev_output, Some(txout))) - // } else { - // fetching_outputs_count.fetch_add(1, Ordering::Relaxed); - // Some((prev_output, None)) - // } - // }) - // .collect::>(); - // for (out_point, value) in tx_outs.into_iter() { - // if let Some(tx_out) = value { - // tx_out_cache.insert(out_point, tx_out); - // } else { - // outpoint_sender.blocking_send(out_point).unwrap(); - // } - // } - // } - // - // let mut lost_sats = processor.get_lost_sats()?; - // let cursed_inscription_count = processor.get_cursed_inscription_count()?; - // let blessed_inscription_count = processor.get_blessed_inscription_count()?; - // let unbound_inscriptions = processor.get_unbound_inscriptions()?; - // let next_sequence_number = processor.next_sequence_number()?; - // - // // let processor = &mut self.processor; - // let mut inscription_updater = PendingUpdater::new( - // operations, - // blessed_inscription_count, - // self.internal_index.internal.options.chain(), - // cursed_inscription_count, - // height, - // self.internal_index.internal.index_transactions, - // next_sequence_number, - // lost_sats, - // block.header.time, - // unbound_inscriptions, - // tx_out_receiver, - // tx_out_cache, - // processor.clone(), - // )?; - // - // let index_sats = true; - // if index_sats { - // let mut coinbase_inputs = VecDeque::new(); - // - // let h = Height(height); - // if h.subsidy() > 0 { - // let start = h.starting_sat(); - // coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); - // } - // - // for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { - // log::trace!("Indexing transaction {tx_offset}…"); - // - // let mut input_sat_ranges = VecDeque::new(); - // - // self.index_transaction_sats( - // tx, - // *txid, - // &mut input_sat_ranges, - // &mut sat_ranges_written, - // &mut outputs_in_block, - // &mut inscription_updater, - // index_inscriptions, - // )?; - // - // coinbase_inputs.extend(input_sat_ranges); - // } - // - // if let Some((tx, txid)) = block.txdata.first() { - // self.index_transaction_sats( - // tx, - // *txid, - // &mut coinbase_inputs, - // &mut sat_ranges_written, - // &mut outputs_in_block, - // &mut inscription_updater, - // index_inscriptions, - // )?; - // } - // - // if !coinbase_inputs.is_empty() { - // let mut lost_sat_ranges = processor.outpoint_to_sat_ranges_remove(&OutPoint::null().store())?.map(|ranges| ranges.to_vec()) - // .unwrap_or_default(); - // - // for (start, end) in coinbase_inputs { - // if !Sat(start).common() { - // processor.sat_to_satpoint_insert( - // &start, - // &SatPoint { - // outpoint: OutPoint::null(), - // offset: lost_sats, - // } - // .store(), - // )?; - // } - // - // lost_sat_ranges.extend_from_slice(&(start, end).store()); - // - // lost_sats += end - start; - // } - // processor.outpoint_to_sat_ranges_insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; - // } - // } else if index_inscriptions { - // for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { - // inscription_updater.index_envelopes(tx, *txid, None)?; - // } - // } - // inscription_updater.flush_cache()?; - // - // // // TODO: - // let mut context = processor.create_context()?; - // // // // Create a protocol manager to index the block of bitmap data. - // let config = ProtocolConfig::new_with_options(&index.options); - // ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; - // - // Ok(()) - // } fn index_block( &mut self, height: u32, index: Index, - outpoint_sender: &'a mut Sender, - tx_out_receiver: &'a mut Receiver, block: BlockData, tx_out_cache: &'a mut SimpleLru, processor: StorageProcessor<'a, 'db, 'tx>, operations: &'db mut HashMap>, ) -> crate::Result<()> { - let start = Instant::now(); let mut sat_ranges_written = 0; let mut outputs_in_block = 0; - // If value_receiver still has values something went wrong with the last block - // Could be an assert, shouldn't recover from this and commit the last block - let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { - return Err(anyhow!("Previous block did not consume all input values")); - }; - let index_inscriptions = true; @@ -546,7 +381,13 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { if let Some(tx_out) = value { tx_out_cache.insert(out_point, tx_out); } else { - outpoint_sender.blocking_send(out_point).unwrap(); + let tx=processor.get_transaction(&out_point.txid)?; + let out=tx.output[out_point.vout as usize].clone(); + let tx_out=TxOut{ + value: out.value, + script_pubkey: out.script_pubkey.clone(), + }; + tx_out_cache.insert(out_point, tx_out); } } } @@ -569,7 +410,6 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { lost_sats, block.header.time, unbound_inscriptions, - tx_out_receiver, tx_out_cache, processor.clone(), )?; @@ -748,7 +588,7 @@ pub fn test_simulate() { first_brc20_height: Some(0), }; let internal = IndexWrapper::new(Arc::new(Index::open(&opt).unwrap())); - let mut sim = Simulator { + let mut sim = Simulator { options: Default::default(), // simulate_index: IndexTracer {}, internal_index: internal.clone(), @@ -795,7 +635,6 @@ pub fn test_simulate() { sat_to_satpoint: Rc::new(RefCell::new((sat_to_point))), statistic_to_count: Rc::new(RefCell::new((statis_to_count))), _marker_a: Default::default(), + client: None, }; - - sim.index_block() } \ No newline at end of file diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index 04d42daba5..b571be6f8c 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -22,7 +22,6 @@ pub struct PendingUpdater<'a, 'db, 'tx> { pub(super) transaction_buffer: Vec, pub(super) timestamp: u32, pub(super) unbound_inscriptions: u64, - pub(super) tx_out_receiver: &'a mut Receiver, pub(super) tx_out_cache: &'a mut SimpleLru, pub(super) new_outpoints: Vec, } @@ -39,9 +38,8 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { lost_sats: u64, timestamp: u32, unbound_inscriptions: u64, - tx_out_receiver: &'a mut Receiver, tx_out_cache: &'a mut SimpleLru, - processor: StorageProcessor<'a, 'db, 'tx>, + processor: StorageProcessor<'a, 'db, 'tx>, ) -> Result { let home_inscriptions_len = processor.home_inscriptions_len(); Ok(Self { @@ -60,7 +58,6 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { transaction_buffer: vec![], timestamp, unbound_inscriptions, - tx_out_receiver, tx_out_cache, new_outpoints: vec![], }) @@ -114,19 +111,7 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { { tx_out.value } else { - let tx_out = self.tx_out_receiver.blocking_recv().ok_or_else(|| { - anyhow!( - "failed to get transaction for {}", - tx_in.previous_output.txid - ) - })?; - // received new tx out from chain node, add it to new_outpoints first and persist it in db later. - #[cfg(not(feature = "cache"))] - self.new_outpoints.push(tx_in.previous_output); - self - .tx_out_cache - .insert(tx_in.previous_output, tx_out.clone()); - tx_out.value + panic!("tx_out_cache should have tx_out for input"); }; total_input_value += current_input_value; From 72f82f490383a2e25dd2fc8697ea8a62ae210ab8 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 14:03:42 +0800 Subject: [PATCH 24/66] add --- src/index/simulate.rs | 380 +++++++++--------------------------------- src/okx/lru.rs | 1 - 2 files changed, 82 insertions(+), 299 deletions(-) diff --git a/src/index/simulate.rs b/src/index/simulate.rs index 0690510487..de60ec6f9d 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -1,13 +1,18 @@ use std::cell::RefCell; use std::collections::{HashMap, HashSet, VecDeque}; use std::marker::PhantomData; +use std::ops::{Deref, DerefMut}; use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use anyhow::anyhow; use bitcoin::{OutPoint, Transaction, Txid, TxOut}; +use indexer_sdk::client::drect::DirectClient; use indexer_sdk::client::SyncClient; +use indexer_sdk::storage::db::memory::MemoryDB; +use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; +use indexer_sdk::storage::kv::KVStorageProcessor; use redb::{ReadableTable}; use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; use crate::height::Height; @@ -24,313 +29,92 @@ use crate::okx::protocol::context::Context; use crate::okx::protocol::trace::IndexTracer; pub struct Simulator<'a, 'db, 'tx> { - pub options: Options, // pub simulate_index: IndexTracer, pub internal_index: IndexWrapper, + pub client: Option>>>, _marker_a: PhantomData<&'a ()>, _marker_b: PhantomData<&'db ()>, _marker_tx: PhantomData<&'tx ()>, } -impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { - pub fn simulate_tx(&self) {} - - // fn index_block( - // &mut self, - // index: &Index, - // height: u32, - // outpoint_sender: &mut Sender, - // tx_out_receiver: &mut Receiver, - // block: BlockData, - // tx_out_cache: &mut SimpleLru, - // wtx: &mut WriteTransaction, - // ) -> crate::Result<()> { - // let start = Instant::now(); - // let mut sat_ranges_written = 0; - // let mut outputs_in_block = 0; - // - // // If value_receiver still has values something went wrong with the last block - // // Could be an assert, shouldn't recover from this and commit the last block - // let Err(TryRecvError::Empty) = tx_out_receiver.try_recv() else { - // return Err(anyhow!("Previous block did not consume all input values")); - // }; - // - // let mut outpoint_to_entry = wtx.open_table(OUTPOINT_TO_ENTRY)?; - // - // let index_inscriptions = true; - // - // let fetching_outputs_count = AtomicUsize::new(0); - // let total_outputs_count = AtomicUsize::new(0); - // let cache_outputs_count = AtomicUsize::new(0); - // let miss_outputs_count = AtomicUsize::new(0); - // let meet_outputs_count = AtomicUsize::new(0); - // if index_inscriptions { - // // Send all missing input outpoints to be fetched right away - // let txids = block - // .txdata - // .iter() - // .map(|(_, txid)| txid) - // .collect::>(); - // use rayon::prelude::*; - // let tx_outs = block - // .txdata - // .par_iter() - // .flat_map(|(tx, _)| tx.input.par_iter()) - // .filter_map(|input| { - // total_outputs_count.fetch_add(1, Ordering::Relaxed); - // let prev_output = input.previous_output; - // // We don't need coinbase input value - // if prev_output.is_null() { - // None - // } else if txids.contains(&prev_output.txid) { - // meet_outputs_count.fetch_add(1, Ordering::Relaxed); - // None - // } else if tx_out_cache.contains(&prev_output) { - // cache_outputs_count.fetch_add(1, Ordering::Relaxed); - // None - // } else if let Some(txout) = - // get_txout_by_outpoint(&outpoint_to_entry, &prev_output).unwrap() - // { - // miss_outputs_count.fetch_add(1, Ordering::Relaxed); - // Some((prev_output, Some(txout))) - // } else { - // fetching_outputs_count.fetch_add(1, Ordering::Relaxed); - // Some((prev_output, None)) - // } - // }) - // .collect::>(); - // for (out_point, value) in tx_outs.into_iter() { - // if let Some(tx_out) = value { - // tx_out_cache.insert(out_point, tx_out); - // } else { - // outpoint_sender.blocking_send(out_point).unwrap(); - // } - // } - // } - // - // let time = timestamp(block.header.time); - // - // log::info!( - // "Block {} at {} with {} transactions, fetching previous outputs {}/{}…, {},{},{}, cost:{}ms", - // height, - // time, - // block.txdata.len(), - // fetching_outputs_count.load(Ordering::Relaxed), - // total_outputs_count.load(Ordering::Relaxed), - // miss_outputs_count.load(Ordering::Relaxed), - // meet_outputs_count.load(Ordering::Relaxed), - // cache_outputs_count.load(Ordering::Relaxed), - // start.elapsed().as_millis(), - // ); - // - // let mut height_to_block_header = wtx.open_table(HEIGHT_TO_BLOCK_HEADER)?; - // let mut height_to_last_sequence_number = wtx.open_table(HEIGHT_TO_LAST_SEQUENCE_NUMBER)?; - // let mut home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS)?; - // let mut inscription_id_to_sequence_number = - // wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; - // let mut inscription_number_to_sequence_number = - // wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER)?; - // let mut sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER)?; - // let mut satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; - // let mut sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN)?; - // let mut sequence_number_to_inscription_entry = - // wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; - // let mut sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT)?; - // let mut statistic_to_count = wtx.open_table(STATISTIC_TO_COUNT)?; - // let mut transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION)?; - // - // let mut lost_sats = statistic_to_count - // .get(&Statistic::LostSats.key())? - // .map(|lost_sats| lost_sats.value()) - // .unwrap_or(0); - // - // let cursed_inscription_count = statistic_to_count - // .get(&Statistic::CursedInscriptions.key())? - // .map(|count| count.value()) - // .unwrap_or(0); - // - // let blessed_inscription_count = statistic_to_count - // .get(&Statistic::BlessedInscriptions.key())? - // .map(|count| count.value()) - // .unwrap_or(0); - // - // let unbound_inscriptions = statistic_to_count - // .get(&Statistic::UnboundInscriptions.key())? - // .map(|unbound_inscriptions| unbound_inscriptions.value()) - // .unwrap_or(0); - // - // let next_sequence_number = sequence_number_to_inscription_entry - // .iter()? - // .next_back() - // .and_then(|result| result.ok()) - // .map(|(number, _id)| number.value() + 1) - // .unwrap_or(0); - // - // let mut operations = HashMap::new(); - // let mut processor = StorageProcessor::new(self.cache.clone(),self.internal_index.clone()); - // // let mut processor = crate::index::updater::pending_updater::PendingStorageProcessor::new( - // // &mut home_inscriptions, - // // &mut inscription_id_to_sequence_number, - // // &mut inscription_number_to_sequence_number, - // // &mut outpoint_to_entry, - // // &mut transaction_id_to_transaction, - // // &mut sat_to_sequence_number, - // // &mut satpoint_to_sequence_number, - // // &mut sequence_number_to_children, - // // &mut sequence_number_to_inscription_entry, - // // &mut sequence_number_to_satpoint, - // // ); - // let mut inscription_updater = PendingUpdater::new( - // &mut operations, - // blessed_inscription_count, - // self.internal_index.options.chain(), - // cursed_inscription_count, - // height, - // self.internal_index.index_transactions, - // next_sequence_number, - // lost_sats, - // block.header.time, - // unbound_inscriptions, - // tx_out_receiver, - // tx_out_cache, - // &mut processor, - // )?; - // - // let index_sats = true; - // if index_sats { - // let mut sat_to_satpoint = wtx.open_table(SAT_TO_SATPOINT)?; - // let mut outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES)?; - // - // let mut coinbase_inputs = VecDeque::new(); - // - // let h = Height(height); - // if h.subsidy() > 0 { - // let start = h.starting_sat(); - // coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); - // } - // - // for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { - // log::trace!("Indexing transaction {tx_offset}…"); - // - // let mut input_sat_ranges = VecDeque::new(); - // - // // TODO: make sure this is correct - // // for input in &tx.input { - // // let key = input.previous_output.store(); - // // let sat_ranges = match self.range_cache.remove(&key) { - // // Some(sat_ranges) => { - // // self.outputs_cached += 1; - // // sat_ranges - // // } - // // None => outpoint_to_sat_ranges - // // .remove(&key)? - // // .ok_or_else(|| anyhow!("Could not find outpoint {} in index", input.previous_output))? - // // .value() - // // .to_vec(), - // // }; - // // - // // for chunk in sat_ranges.chunks_exact(11) { - // // input_sat_ranges.push_back(SatRange::load(chunk.try_into().unwrap())); - // // } - // // } - // - // self.index_transaction_sats( - // tx, - // *txid, - // &mut sat_to_satpoint, - // &mut input_sat_ranges, - // &mut sat_ranges_written, - // &mut outputs_in_block, - // &mut inscription_updater, - // index_inscriptions, - // )?; - // - // coinbase_inputs.extend(input_sat_ranges); - // } - // - // if let Some((tx, txid)) = block.txdata.first() { - // self.index_transaction_sats( - // tx, - // *txid, - // &mut sat_to_satpoint, - // &mut coinbase_inputs, - // &mut sat_ranges_written, - // &mut outputs_in_block, - // &mut inscription_updater, - // index_inscriptions, - // )?; - // } - // - // if !coinbase_inputs.is_empty() { - // let mut lost_sat_ranges = outpoint_to_sat_ranges - // .remove(&OutPoint::null().store())? - // .map(|ranges| ranges.value().to_vec()) - // .unwrap_or_default(); - // - // for (start, end) in coinbase_inputs { - // if !Sat(start).common() { - // sat_to_satpoint.insert( - // &start, - // &SatPoint { - // outpoint: OutPoint::null(), - // offset: lost_sats, - // } - // .store(), - // )?; - // } - // - // lost_sat_ranges.extend_from_slice(&(start, end).store()); - // - // lost_sats += end - start; - // } - // - // outpoint_to_sat_ranges.insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; - // } - // } else if index_inscriptions { - // for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { - // inscription_updater.index_envelopes(tx, *txid, None)?; - // } - // } - // inscription_updater.flush_cache()?; - // - // let mut context = Context { - // chain: BlockContext { - // network: index.get_chain_network(), - // blockheight: height, - // blocktime: block.header.time, - // }, - // tx_out_cache, - // hit: 0, - // miss: 0, - // ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS)?, - // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, - // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx - // .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, - // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut sequence_number_to_inscription_entry, - // OUTPOINT_TO_ENTRY: &mut outpoint_to_entry, - // BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES)?, - // BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN)?, - // BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS)?, - // BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG)?, - // BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER)?, - // }; - // - // // Create a protocol manager to index the block of bitmap data. - // let config = ProtocolConfig::new_with_options(&index.options); - // ProtocolManager::new(config).index_block(&mut context, &block, operations)?; - // - // Ok(()) - // } +pub struct SimulatorServer { + tx_out_cache: Rc>>, + pub internal_index: IndexWrapper, + pub simulate_index: Arc, + pub client: DirectClient>>, +} +impl SimulatorServer { + pub fn simulate_tx(&self, tx: &Transaction) -> crate::Result<()> { + let mut sim = Simulator { + internal_index: self.internal_index.clone(), + client: None, + _marker_a: Default::default(), + _marker_b: Default::default(), + _marker_tx: Default::default(), + }; + let height = self.internal_index.internal.block_count()?; + let block = self.internal_index.internal.get_block_by_height(height)?.unwrap(); + let mut cache = self.tx_out_cache.borrow_mut(); + let cache = cache.deref_mut(); + + let mut wtx = self.simulate_index.begin_write()?; + let wtx = Rc::new(RefCell::new(wtx)); + let binding = wtx.borrow(); + let mut home_inscriptions = binding.open_table(HOME_INSCRIPTIONS).unwrap(); + let mut inscription_id_to_sequence_number = + binding.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); + let mut inscription_number_to_sequence_number = + binding.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER).unwrap(); + let mut sat_to_sequence_number = binding.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); + let mut satpoint_to_sequence_number = binding.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); + let mut sequence_number_to_children = binding.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); + let mut sequence_number_to_inscription_entry = + binding.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(); + let mut sequence_number_to_satpoint = binding.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); + let mut transaction_id_to_transaction = binding.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); + let mut outpoint_to_entry = binding.open_table(OUTPOINT_TO_ENTRY).unwrap(); + let mut OUTPOINT_TO_SAT_RANGES_table = binding.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); + let sat_to_point = binding.open_table(SAT_TO_SATPOINT).unwrap(); + let statis_to_count = binding.open_table(STATISTIC_TO_COUNT).unwrap(); + + let processor = StorageProcessor { + internal: self.internal_index.clone(), + // wtx: &mut wtx, + home_inscriptions: Rc::new(RefCell::new(home_inscriptions)), + id_to_sequence_number: Rc::new(RefCell::new(inscription_id_to_sequence_number)), + inscription_number_to_sequence_number: Rc::new(RefCell::new(inscription_number_to_sequence_number)), + outpoint_to_entry: Rc::new(RefCell::new(outpoint_to_entry)), + transaction_id_to_transaction: Rc::new(RefCell::new(transaction_id_to_transaction)), + sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), + satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), + sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), + sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), + sequence_number_to_inscription_entry: Rc::new(RefCell::new((sequence_number_to_inscription_entry))), + OUTPOINT_TO_SAT_RANGES: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), + sat_to_satpoint: Rc::new(RefCell::new((sat_to_point))), + statistic_to_count: Rc::new(RefCell::new((statis_to_count))), + _marker_a: Default::default(), + client: Some(self.client.clone()), + }; + let mut operations: HashMap> = HashMap::new(); + sim.index_block(BlockData { + header: block.header, + txdata: vec![(tx.clone(), tx.txid())], + }, height, cache, processor, &mut operations)?; + Ok(()) + } +} + +impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { fn index_block( &mut self, - height: u32, - index: Index, block: BlockData, + height: u32, tx_out_cache: &'a mut SimpleLru, processor: StorageProcessor<'a, 'db, 'tx>, - operations: &'db mut HashMap>, + operations: &'a mut HashMap>, ) -> crate::Result<()> { let mut sat_ranges_written = 0; let mut outputs_in_block = 0; @@ -381,9 +165,9 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { if let Some(tx_out) = value { tx_out_cache.insert(out_point, tx_out); } else { - let tx=processor.get_transaction(&out_point.txid)?; - let out=tx.output[out_point.vout as usize].clone(); - let tx_out=TxOut{ + let tx = processor.get_transaction(&out_point.txid)?; + let out = tx.output[out_point.vout as usize].clone(); + let tx_out = TxOut { value: out.value, script_pubkey: out.script_pubkey.clone(), }; @@ -486,7 +270,7 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { // // TODO: let mut context = processor.create_context()?; // // // Create a protocol manager to index the block of bitmap data. - let config = ProtocolConfig::new_with_options(&index.options); + let config = ProtocolConfig::new_with_options(&self.internal_index.internal.options); ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; Ok(()) @@ -589,9 +373,9 @@ pub fn test_simulate() { }; let internal = IndexWrapper::new(Arc::new(Index::open(&opt).unwrap())); let mut sim = Simulator { - options: Default::default(), // simulate_index: IndexTracer {}, internal_index: internal.clone(), + client: None, _marker_a: Default::default(), _marker_b: Default::default(), _marker_tx: Default::default(), diff --git a/src/okx/lru.rs b/src/okx/lru.rs index f2ebac3c89..2c443b289c 100644 --- a/src/okx/lru.rs +++ b/src/okx/lru.rs @@ -8,7 +8,6 @@ pub struct SimpleLru { new_cache: HashMap, old_cache: HashMap, } - impl SimpleLru where K: Eq + Hash, From 81010c0ee8327a3f46f0943129459e41751ec910 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 14:05:49 +0800 Subject: [PATCH 25/66] add --- src/index/simulate.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/index/simulate.rs b/src/index/simulate.rs index de60ec6f9d..450bbf4085 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -59,22 +59,22 @@ impl SimulatorServer { let cache = cache.deref_mut(); let mut wtx = self.simulate_index.begin_write()?; - let wtx = Rc::new(RefCell::new(wtx)); - let binding = wtx.borrow(); - let mut home_inscriptions = binding.open_table(HOME_INSCRIPTIONS).unwrap(); - let mut inscription_id_to_sequence_number = + // let wtx = Rc::new(RefCell::new(wtx)); + let binding = wtx; + let home_inscriptions = binding.open_table(HOME_INSCRIPTIONS).unwrap(); + let inscription_id_to_sequence_number = binding.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); - let mut inscription_number_to_sequence_number = + let inscription_number_to_sequence_number = binding.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER).unwrap(); - let mut sat_to_sequence_number = binding.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); - let mut satpoint_to_sequence_number = binding.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); - let mut sequence_number_to_children = binding.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); + let sat_to_sequence_number = binding.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); + let satpoint_to_sequence_number = binding.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); + let sequence_number_to_children = binding.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); let mut sequence_number_to_inscription_entry = binding.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(); - let mut sequence_number_to_satpoint = binding.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); - let mut transaction_id_to_transaction = binding.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); - let mut outpoint_to_entry = binding.open_table(OUTPOINT_TO_ENTRY).unwrap(); - let mut OUTPOINT_TO_SAT_RANGES_table = binding.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); + let sequence_number_to_satpoint = binding.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); + let transaction_id_to_transaction = binding.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); + let outpoint_to_entry = binding.open_table(OUTPOINT_TO_ENTRY).unwrap(); + let OUTPOINT_TO_SAT_RANGES_table = binding.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); let sat_to_point = binding.open_table(SAT_TO_SATPOINT).unwrap(); let statis_to_count = binding.open_table(STATISTIC_TO_COUNT).unwrap(); @@ -103,6 +103,8 @@ impl SimulatorServer { txdata: vec![(tx.clone(), tx.txid())], }, height, cache, processor, &mut operations)?; + binding.commit()?; + Ok(()) } } From c870bf2f2b2255b6f7b32243c970eaed68186711 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 14:40:40 +0800 Subject: [PATCH 26/66] add --- src/index/processor.rs | 49 ++++++-------------- src/index/simulate.rs | 88 ++++++++++++++++++++++-------------- src/index/updater.rs | 1 + src/okx/protocol/simulate.rs | 1 + 4 files changed, 71 insertions(+), 68 deletions(-) diff --git a/src/index/processor.rs b/src/index/processor.rs index 77c79cd789..c6e2c75a7f 100644 --- a/src/index/processor.rs +++ b/src/index/processor.rs @@ -228,6 +228,7 @@ use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::protocol::context::Context; use crate::okx::protocol::simulate::SimulateContext; use crate::RpcApi; + #[derive(Clone)] pub struct IndexWrapper { pub internal: Arc, @@ -251,8 +252,6 @@ impl IndexWrapper { pub struct StorageProcessor<'a, 'db, 'tx> { pub internal: IndexWrapper, - // pub wtx: Rc>>, - pub(super) home_inscriptions: Rc>>, pub(super) id_to_sequence_number: Rc>>, pub(super) inscription_number_to_sequence_number: Rc>>, @@ -272,7 +271,9 @@ pub struct StorageProcessor<'a, 'db, 'tx> { pub statistic_to_count: Rc>>, pub _marker_a: PhantomData<&'a ()>, - pub client:Option>>>, + pub client: Option>>>, + + pub context: SimulateContext<'a, 'db, 'tx>, } unsafe impl<'a, 'db, 'tx> Send for StorageProcessor<'a, 'db, 'tx> {} @@ -285,34 +286,14 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { todo!() } - pub fn get_transaction(&self,tx_id:&Txid)->crate::Result{ - let client=self.client.as_ref().unwrap(); - let client=client.get_btc_client(); - let tx=client.get_raw_transaction(tx_id,None)?; + pub fn get_transaction(&self, tx_id: &Txid) -> crate::Result { + let client = self.client.as_ref().unwrap(); + let client = client.get_btc_client(); + let tx = client.get_raw_transaction(tx_id, None)?; Ok(tx) } - pub(crate) fn create_simulate_context(&self, wtx: &'tx mut WriteTransaction<'db>) -> crate::Result> { - let h = self.internal.internal.block_height().unwrap().unwrap(); - let ts = self.internal.internal.block_time(h).unwrap().timestamp().timestamp(); - let ctx = SimulateContext { - network: self.internal.internal.get_chain_network().clone(), - current_height: h.0, - current_block_time: ts as u32, - internal_index: self.internal.clone(), - ORD_TX_TO_OPERATIONS: Rc::new(RefCell::new((wtx.open_table(crate::index::ORD_TX_TO_OPERATIONS)?))), - COLLECTIONS_KEY_TO_INSCRIPTION_ID: Rc::new(RefCell::new(wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?)), - COLLECTIONS_INSCRIPTION_ID_TO_KINDS: Rc::new(RefCell::new((wtx - .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?))), - SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: Rc::new(RefCell::new((wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?))), - OUTPOINT_TO_ENTRY: Rc::new(RefCell::new((wtx.open_table(OUTPOINT_TO_ENTRY)?))), - BRC20_BALANCES: Rc::new(RefCell::new((wtx.open_table(BRC20_BALANCES)?))), - BRC20_TOKEN: Rc::new(RefCell::new((wtx.open_table(BRC20_TOKEN)?))), - BRC20_EVENTS: Rc::new(RefCell::new((wtx.open_table(BRC20_EVENTS)?))), - BRC20_TRANSFERABLELOG: Rc::new(RefCell::new((wtx.open_table(BRC20_TRANSFERABLELOG)?))), - BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new((wtx.open_table(BRC20_INSCRIBE_TRANSFER)?))), - _marker_a: Default::default(), - }; - Ok(ctx) + pub(crate) fn create_simulate_context(&self) -> crate::Result> { + Ok(self.context.clone()) } pub(crate) fn next_sequence_number(&self) -> crate::Result { let table = self.sequence_number_to_inscription_entry.borrow(); @@ -601,7 +582,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { return Ok(Some(v.value())); } let ret = self.internal.use_internal_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |table| { - let value=table.get(x).map_err(|e|{ + let value = table.get(x).map_err(|e| { anyhow!("id_to_sequence_number_get error:{}",e) })?; if let Some(value) = value { @@ -621,13 +602,13 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { return Ok(Some(v.value())); } let ret = self.internal.use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| { - let ret=table.get(initial_inscription_sequence_number).map_err(move |e| { + let ret = table.get(initial_inscription_sequence_number).map_err(move |e| { anyhow!("sequence_number_to_entry_get error:{}",e) })?; - if let Some(ret)=ret{ - return Ok(Some(ret.value())) + if let Some(ret) = ret { + return Ok(Some(ret.value())); } - return Ok(None) + return Ok(None); })?; if let Some(ret) = ret { return Ok(Some(ret)); diff --git a/src/index/simulate.rs b/src/index/simulate.rs index 450bbf4085..7033a00ca6 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -16,17 +16,14 @@ use indexer_sdk::storage::kv::KVStorageProcessor; use redb::{ReadableTable}; use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; use crate::height::Height; -use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; +use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; use crate::index::entry::{Entry, SatPointValue, SatRange}; use crate::index::processor::{IndexWrapper, StorageProcessor}; use crate::index::updater::pending_updater::PendingUpdater; -use crate::okx::datastore::cache::CacheWriter; use crate::okx::datastore::ord::InscriptionOp; -use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::lru::SimpleLru; use crate::okx::protocol::{BlockContext, ProtocolConfig, ProtocolManager}; -use crate::okx::protocol::context::Context; -use crate::okx::protocol::trace::IndexTracer; +use crate::okx::protocol::simulate::SimulateContext; pub struct Simulator<'a, 'db, 'tx> { // pub simulate_index: IndexTracer, @@ -60,7 +57,7 @@ impl SimulatorServer { let mut wtx = self.simulate_index.begin_write()?; // let wtx = Rc::new(RefCell::new(wtx)); - let binding = wtx; + let mut binding = wtx; let home_inscriptions = binding.open_table(HOME_INSCRIPTIONS).unwrap(); let inscription_id_to_sequence_number = binding.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); @@ -70,38 +67,62 @@ impl SimulatorServer { let satpoint_to_sequence_number = binding.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); let sequence_number_to_children = binding.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); let mut sequence_number_to_inscription_entry = - binding.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(); + Rc::new(RefCell::new(binding.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap())); let sequence_number_to_satpoint = binding.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); let transaction_id_to_transaction = binding.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); - let outpoint_to_entry = binding.open_table(OUTPOINT_TO_ENTRY).unwrap(); + let outpoint_to_entry = Rc::new((RefCell::new(binding.open_table(OUTPOINT_TO_ENTRY).unwrap()))); let OUTPOINT_TO_SAT_RANGES_table = binding.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); let sat_to_point = binding.open_table(SAT_TO_SATPOINT).unwrap(); let statis_to_count = binding.open_table(STATISTIC_TO_COUNT).unwrap(); + let h = height; + let ts = block.header.time; + let ctx = SimulateContext { + network: self.internal_index.internal.get_chain_network().clone(), + current_height: h, + current_block_time: ts as u32, + internal_index: self.internal_index.clone(), + ORD_TX_TO_OPERATIONS: Rc::new(RefCell::new((binding.open_table(crate::index::ORD_TX_TO_OPERATIONS)?))), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: Rc::new(RefCell::new(binding.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?)), + COLLECTIONS_INSCRIPTION_ID_TO_KINDS: Rc::new(RefCell::new((binding + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?))), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: sequence_number_to_inscription_entry.clone(), + OUTPOINT_TO_ENTRY: outpoint_to_entry.clone(), + BRC20_BALANCES: Rc::new(RefCell::new((binding.open_table(BRC20_BALANCES)?))), + BRC20_TOKEN: Rc::new(RefCell::new((binding.open_table(BRC20_TOKEN)?))), + BRC20_EVENTS: Rc::new(RefCell::new((binding.open_table(BRC20_EVENTS)?))), + BRC20_TRANSFERABLELOG: Rc::new(RefCell::new((binding.open_table(BRC20_TRANSFERABLELOG)?))), + BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new((binding.open_table(BRC20_INSCRIBE_TRANSFER)?))), + _marker_a: Default::default(), + }; + let processor = StorageProcessor { internal: self.internal_index.clone(), // wtx: &mut wtx, home_inscriptions: Rc::new(RefCell::new(home_inscriptions)), id_to_sequence_number: Rc::new(RefCell::new(inscription_id_to_sequence_number)), inscription_number_to_sequence_number: Rc::new(RefCell::new(inscription_number_to_sequence_number)), - outpoint_to_entry: Rc::new(RefCell::new(outpoint_to_entry)), + outpoint_to_entry: outpoint_to_entry, transaction_id_to_transaction: Rc::new(RefCell::new(transaction_id_to_transaction)), sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), - sequence_number_to_inscription_entry: Rc::new(RefCell::new((sequence_number_to_inscription_entry))), + sequence_number_to_inscription_entry: sequence_number_to_inscription_entry, OUTPOINT_TO_SAT_RANGES: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), sat_to_satpoint: Rc::new(RefCell::new((sat_to_point))), statistic_to_count: Rc::new(RefCell::new((statis_to_count))), _marker_a: Default::default(), client: Some(self.client.clone()), + context: ctx, }; let mut operations: HashMap> = HashMap::new(); - sim.index_block(BlockData { + let block = BlockData { header: block.header, txdata: vec![(tx.clone(), tx.txid())], - }, height, cache, processor, &mut operations)?; + }; + sim.index_block(block.clone(), height, cache, processor, &mut operations)?; + binding.commit()?; @@ -269,9 +290,7 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { } inscription_updater.flush_cache()?; - // // TODO: - let mut context = processor.create_context()?; - // // // Create a protocol manager to index the block of bitmap data. + let mut context = processor.create_simulate_context()?; let config = ProtocolConfig::new_with_options(&self.internal_index.internal.options); ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; @@ -404,23 +423,24 @@ pub fn test_simulate() { let mut OUTPOINT_TO_SAT_RANGES_table = binding.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); let sat_to_point = binding.open_table(SAT_TO_SATPOINT).unwrap(); let statis_to_count = binding.open_table(STATISTIC_TO_COUNT).unwrap(); - let processor = StorageProcessor { - internal: internal.clone(), - // wtx: &mut wtx, - home_inscriptions: Rc::new(RefCell::new(home_inscriptions)), - id_to_sequence_number: Rc::new(RefCell::new(inscription_id_to_sequence_number)), - inscription_number_to_sequence_number: Rc::new(RefCell::new(inscription_number_to_sequence_number)), - outpoint_to_entry: Rc::new(RefCell::new(outpoint_to_entry)), - transaction_id_to_transaction: Rc::new(RefCell::new(transaction_id_to_transaction)), - sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), - satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), - sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), - sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), - sequence_number_to_inscription_entry: Rc::new(RefCell::new((sequence_number_to_inscription_entry))), - OUTPOINT_TO_SAT_RANGES: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), - sat_to_satpoint: Rc::new(RefCell::new((sat_to_point))), - statistic_to_count: Rc::new(RefCell::new((statis_to_count))), - _marker_a: Default::default(), - client: None, - }; + // let processor = StorageProcessor { + // internal: internal.clone(), + // // wtx: &mut wtx, + // home_inscriptions: Rc::new(RefCell::new(home_inscriptions)), + // id_to_sequence_number: Rc::new(RefCell::new(inscription_id_to_sequence_number)), + // inscription_number_to_sequence_number: Rc::new(RefCell::new(inscription_number_to_sequence_number)), + // outpoint_to_entry: Rc::new(RefCell::new(outpoint_to_entry)), + // transaction_id_to_transaction: Rc::new(RefCell::new(transaction_id_to_transaction)), + // sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), + // satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), + // sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), + // sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), + // sequence_number_to_inscription_entry: Rc::new(RefCell::new((sequence_number_to_inscription_entry))), + // OUTPOINT_TO_SAT_RANGES: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), + // sat_to_satpoint: Rc::new(RefCell::new((sat_to_point))), + // statistic_to_count: Rc::new(RefCell::new((statis_to_count))), + // _marker_a: Default::default(), + // client: None, + // context: SimulateContext {}, + // }; } \ No newline at end of file diff --git a/src/index/updater.rs b/src/index/updater.rs index b1d4cd72f2..8213177572 100644 --- a/src/index/updater.rs +++ b/src/index/updater.rs @@ -15,6 +15,7 @@ mod rune_updater; pub mod pending_updater; mod pending2; +#[derive(Clone)] pub(crate) struct BlockData { pub(crate) header: Header, pub(crate) txdata: Vec<(Transaction, Txid)>, diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index f76417dc17..400af1fb10 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -799,6 +799,7 @@ use crate::okx::datastore::ord::redb::table::{get_collection_inscription_id, get use crate::okx::datastore::ScriptKey; use crate::okx::protocol::ContextTrait; +#[derive(Clone)] pub struct SimulateContext<'a, 'db, 'txn> { pub network: Network, pub current_height: u32, From 0615cf2425f725d0076c39b2d3dca06169f88506 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 16:34:20 +0800 Subject: [PATCH 27/66] cargo --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 176a736ba4..52fea8ba28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,8 +74,8 @@ log4rs = { version = "1.2.0", features = ["gzip"] } once_cell = "1.19.0" rmp-serde = "1.1.2" rayon = "1.8.0" -#indexer-sdk={git="https://github.com/ItsFunny/indexer-sdk.git"} -indexer-sdk={path="/Users/lvcong/RustroverProjects/indexer-sdk"} +indexer-sdk={git="https://github.com/ItsFunny/indexer-sdk.git"} +#indexer-sdk={path="/Users/lvcong/RustroverProjects/indexer-sdk"} [dev-dependencies] criterion = "0.5.1" executable-path = "1.0.0" From 5cf8baeb6c937ea2557f04f4c31a9e8799e20b47 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 12 Jan 2024 16:40:13 +0800 Subject: [PATCH 28/66] add --- Cargo.toml | 4 +- src/index/simulate.rs | 191 ++++++++++++++++++++++++------------------ 2 files changed, 110 insertions(+), 85 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 52fea8ba28..176a736ba4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,8 +74,8 @@ log4rs = { version = "1.2.0", features = ["gzip"] } once_cell = "1.19.0" rmp-serde = "1.1.2" rayon = "1.8.0" -indexer-sdk={git="https://github.com/ItsFunny/indexer-sdk.git"} -#indexer-sdk={path="/Users/lvcong/RustroverProjects/indexer-sdk"} +#indexer-sdk={git="https://github.com/ItsFunny/indexer-sdk.git"} +indexer-sdk={path="/Users/lvcong/RustroverProjects/indexer-sdk"} [dev-dependencies] criterion = "0.5.1" executable-path = "1.0.0" diff --git a/src/index/simulate.rs b/src/index/simulate.rs index 7033a00ca6..dc58a4304b 100644 --- a/src/index/simulate.rs +++ b/src/index/simulate.rs @@ -128,6 +128,9 @@ impl SimulatorServer { Ok(()) } + pub fn new(internal_index: Arc, simulate_index: Arc, client: DirectClient>>) -> Self { + Self { tx_out_cache: Default::default(), internal_index: IndexWrapper::new(internal_index), simulate_index, client } + } } impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { @@ -361,86 +364,108 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { } } -#[test] -pub fn test_simulate() { - let opt = crate::options::Options { - log_level: Default::default(), - log_dir: None, - bitcoin_data_dir: None, - bitcoin_rpc_pass: Some("bitcoinrpc".to_string()), - bitcoin_rpc_user: Some("bitcoinrpc".to_string()), - chain_argument: Default::default(), - config: None, - config_dir: None, - cookie_file: None, - data_dir: Default::default(), - db_cache_size: None, - lru_size: 0, - first_inscription_height: None, - height_limit: None, - index: None, - index_runes: false, - index_sats: true, - index_transactions: true, - no_index_inscriptions: false, - regtest: true, - rpc_url: None, - signet: false, - testnet: false, - enable_save_ord_receipts: true, - enable_index_bitmap: true, - enable_index_brc20: true, - first_brc20_height: Some(0), - }; - let internal = IndexWrapper::new(Arc::new(Index::open(&opt).unwrap())); - let mut sim = Simulator { - // simulate_index: IndexTracer {}, - internal_index: internal.clone(), - client: None, - _marker_a: Default::default(), - _marker_b: Default::default(), - _marker_tx: Default::default(), - }; - let mut opt2 = opt.clone(); - opt2.index = Some(PathBuf::from("./simulate")); - let simulate_index = Index::open(&opt2).unwrap(); - let mut wtx = simulate_index.begin_write().unwrap(); - let wtx = Rc::new(RefCell::new(wtx)); - let binding = wtx.borrow(); - let mut home_inscriptions = binding.open_table(HOME_INSCRIPTIONS).unwrap(); - let mut inscription_id_to_sequence_number = - binding.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); - let mut inscription_number_to_sequence_number = - binding.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER).unwrap(); - let mut sat_to_sequence_number = binding.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); - let mut satpoint_to_sequence_number = binding.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); - let mut sequence_number_to_children = binding.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); - let mut sequence_number_to_inscription_entry = - binding.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(); - let mut sequence_number_to_satpoint = binding.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); - let mut transaction_id_to_transaction = binding.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); - let mut outpoint_to_entry = binding.open_table(OUTPOINT_TO_ENTRY).unwrap(); - let mut OUTPOINT_TO_SAT_RANGES_table = binding.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); - let sat_to_point = binding.open_table(SAT_TO_SATPOINT).unwrap(); - let statis_to_count = binding.open_table(STATISTIC_TO_COUNT).unwrap(); - // let processor = StorageProcessor { - // internal: internal.clone(), - // // wtx: &mut wtx, - // home_inscriptions: Rc::new(RefCell::new(home_inscriptions)), - // id_to_sequence_number: Rc::new(RefCell::new(inscription_id_to_sequence_number)), - // inscription_number_to_sequence_number: Rc::new(RefCell::new(inscription_number_to_sequence_number)), - // outpoint_to_entry: Rc::new(RefCell::new(outpoint_to_entry)), - // transaction_id_to_transaction: Rc::new(RefCell::new(transaction_id_to_transaction)), - // sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), - // satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), - // sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), - // sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), - // sequence_number_to_inscription_entry: Rc::new(RefCell::new((sequence_number_to_inscription_entry))), - // OUTPOINT_TO_SAT_RANGES: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), - // sat_to_satpoint: Rc::new(RefCell::new((sat_to_point))), - // statistic_to_count: Rc::new(RefCell::new((statis_to_count))), - // _marker_a: Default::default(), - // client: None, - // context: SimulateContext {}, - // }; -} \ No newline at end of file +#[cfg(test)] +mod tests { + use indexer_sdk::factory::common::new_client_for_test; + use super::*; + + #[test] + pub fn test_simulate_tx() { + let opt = create_options(); + let internal = Arc::new(Index::open(&opt).unwrap()); + let mut opt2 = opt.clone(); + opt2.index = Some(PathBuf::from("./simulate")); + let simulate_index = Index::open(&opt2).unwrap(); + let client = new_client_for_test("http://localhost:18443".to_string(), "bitcoinrpc".to_string(), "bitcoinrpc".to_string()); + let simulate_server = SimulatorServer::new(internal.clone(), simulate_index.clone(), client); + } + + fn create_options() -> Options { + let opt = crate::options::Options { + log_level: Default::default(), + log_dir: None, + bitcoin_data_dir: None, + bitcoin_rpc_pass: Some("bitcoinrpc".to_string()), + bitcoin_rpc_user: Some("bitcoinrpc".to_string()), + chain_argument: Default::default(), + config: None, + config_dir: None, + cookie_file: None, + data_dir: Default::default(), + db_cache_size: None, + lru_size: 0, + first_inscription_height: None, + height_limit: None, + index: Some(PathBuf::from("./internal")), + index_runes: false, + index_sats: true, + index_transactions: true, + no_index_inscriptions: false, + regtest: true, + rpc_url: None, + signet: false, + testnet: false, + enable_save_ord_receipts: true, + enable_index_bitmap: true, + enable_index_brc20: true, + first_brc20_height: Some(0), + }; + opt + } + + #[test] + pub fn test_simulate() { + let opt = create_options(); + let internal = IndexWrapper::new(Arc::new(Index::open(&opt).unwrap())); + let mut sim = Simulator { + // simulate_index: IndexTracer {}, + internal_index: internal.clone(), + client: None, + _marker_a: Default::default(), + _marker_b: Default::default(), + _marker_tx: Default::default(), + }; + let mut opt2 = opt.clone(); + opt2.index = Some(PathBuf::from("./simulate")); + let simulate_index = Index::open(&opt2).unwrap(); + let mut wtx = simulate_index.begin_write().unwrap(); + let wtx = Rc::new(RefCell::new(wtx)); + let binding = wtx.borrow(); + let mut home_inscriptions = binding.open_table(HOME_INSCRIPTIONS).unwrap(); + let mut inscription_id_to_sequence_number = + binding.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); + let mut inscription_number_to_sequence_number = + binding.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER).unwrap(); + let mut sat_to_sequence_number = binding.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); + let mut satpoint_to_sequence_number = binding.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); + let mut sequence_number_to_children = binding.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); + let mut sequence_number_to_inscription_entry = + binding.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(); + let mut sequence_number_to_satpoint = binding.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); + let mut transaction_id_to_transaction = binding.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); + let mut outpoint_to_entry = binding.open_table(OUTPOINT_TO_ENTRY).unwrap(); + let mut OUTPOINT_TO_SAT_RANGES_table = binding.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); + let sat_to_point = binding.open_table(SAT_TO_SATPOINT).unwrap(); + let statis_to_count = binding.open_table(STATISTIC_TO_COUNT).unwrap(); + // let processor = StorageProcessor { + // internal: internal.clone(), + // // wtx: &mut wtx, + // home_inscriptions: Rc::new(RefCell::new(home_inscriptions)), + // id_to_sequence_number: Rc::new(RefCell::new(inscription_id_to_sequence_number)), + // inscription_number_to_sequence_number: Rc::new(RefCell::new(inscription_number_to_sequence_number)), + // outpoint_to_entry: Rc::new(RefCell::new(outpoint_to_entry)), + // transaction_id_to_transaction: Rc::new(RefCell::new(transaction_id_to_transaction)), + // sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), + // satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), + // sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), + // sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), + // sequence_number_to_inscription_entry: Rc::new(RefCell::new((sequence_number_to_inscription_entry))), + // OUTPOINT_TO_SAT_RANGES: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), + // sat_to_satpoint: Rc::new(RefCell::new((sat_to_point))), + // statistic_to_count: Rc::new(RefCell::new((statis_to_count))), + // _marker_a: Default::default(), + // client: None, + // context: SimulateContext {}, + // }; + } +} From a8ad4725d5f3c8a53edd2c7a094bfd65f4d7a111 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sat, 13 Jan 2024 23:11:24 +0800 Subject: [PATCH 29/66] save add ok --- src/index.rs | 3 +- src/index/simulator/error.rs | 17 ++ src/index/simulator/mod.rs | 3 + src/index/{ => simulator}/processor.rs | 9 +- src/index/{ => simulator}/simulate.rs | 208 ++++++++++++------------- src/index/updater.rs | 1 + src/index/updater/pending_updater.rs | 2 +- src/okx/protocol/simulate.rs | 3 +- 8 files changed, 133 insertions(+), 113 deletions(-) create mode 100644 src/index/simulator/error.rs create mode 100644 src/index/simulator/mod.rs rename src/index/{ => simulator}/processor.rs (99%) rename src/index/{ => simulator}/simulate.rs (72%) diff --git a/src/index.rs b/src/index.rs index d2d5e2a4c5..f5eeef2d6e 100644 --- a/src/index.rs +++ b/src/index.rs @@ -52,8 +52,7 @@ pub(crate) mod updater; #[cfg(test)] pub(crate) mod testing; -mod simulate; -pub mod processor; +pub mod simulator; mod database_processor; const SCHEMA_VERSION: u64 = 16; diff --git a/src/index/simulator/error.rs b/src/index/simulator/error.rs new file mode 100644 index 0000000000..a472df24a6 --- /dev/null +++ b/src/index/simulator/error.rs @@ -0,0 +1,17 @@ +use bitcoin::Txid; +use redb::{CommitError, TableError}; + +#[derive(Debug, thiserror::Error)] +pub enum SimulateError { + #[error("tx not found: {0}")] + TxNotFound(Txid), + + #[error("error: {0}")] + Anyhow(#[from] anyhow::Error), + + #[error("commit failed: {0}")] + CommitError(#[from]CommitError), + + #[error("table failed: {0}")] + TableError(#[from]TableError) +} \ No newline at end of file diff --git a/src/index/simulator/mod.rs b/src/index/simulator/mod.rs new file mode 100644 index 0000000000..d2e4494444 --- /dev/null +++ b/src/index/simulator/mod.rs @@ -0,0 +1,3 @@ +pub mod simulate; +pub mod processor; +pub mod error; \ No newline at end of file diff --git a/src/index/processor.rs b/src/index/simulator/processor.rs similarity index 99% rename from src/index/processor.rs rename to src/index/simulator/processor.rs index c6e2c75a7f..62e359c8a7 100644 --- a/src/index/processor.rs +++ b/src/index/simulator/processor.rs @@ -219,6 +219,7 @@ use indexer_sdk::client::SyncClient; use indexer_sdk::storage::db::memory::MemoryDB; use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; +use log::info; use redb::{MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; use crate::{Index, InscriptionId, SatPoint}; use crate::index::entry::{Entry, SatPointValue}; @@ -286,11 +287,11 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { todo!() } - pub fn get_transaction(&self, tx_id: &Txid) -> crate::Result { + pub fn get_transaction(&self, tx_id: &Txid) -> crate::Result> { + info!("get_transaction: {:?}", tx_id); let client = self.client.as_ref().unwrap(); - let client = client.get_btc_client(); - let tx = client.get_raw_transaction(tx_id, None)?; - Ok(tx) + let ret=client.get_transaction_by_tx_id(tx_id.clone())?; + Ok(ret) } pub(crate) fn create_simulate_context(&self) -> crate::Result> { Ok(self.context.clone()) diff --git a/src/index/simulate.rs b/src/index/simulator/simulate.rs similarity index 72% rename from src/index/simulate.rs rename to src/index/simulator/simulate.rs index dc58a4304b..b1b77d9e1c 100644 --- a/src/index/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -13,12 +13,14 @@ use indexer_sdk::client::SyncClient; use indexer_sdk::storage::db::memory::MemoryDB; use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; -use redb::{ReadableTable}; +use log::{error, info}; +use redb::{ReadableTable, WriteTransaction}; use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; use crate::height::Height; use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; use crate::index::entry::{Entry, SatPointValue, SatRange}; -use crate::index::processor::{IndexWrapper, StorageProcessor}; +use crate::index::simulator::error::SimulateError; +use crate::index::simulator::processor::{IndexWrapper, StorageProcessor}; use crate::index::updater::pending_updater::PendingUpdater; use crate::okx::datastore::ord::InscriptionOp; use crate::okx::lru::SimpleLru; @@ -42,38 +44,35 @@ pub struct SimulatorServer { } impl SimulatorServer { - pub fn simulate_tx(&self, tx: &Transaction) -> crate::Result<()> { - let mut sim = Simulator { - internal_index: self.internal_index.clone(), - client: None, - _marker_a: Default::default(), - _marker_b: Default::default(), - _marker_tx: Default::default(), - }; + pub fn execute_tx(&self, tx: &Transaction, commit: bool) -> crate::Result<(),SimulateError> { + let mut wtx = self.simulate_index.begin_write()?; + self.simulate_tx(tx, &wtx)?; + if commit { + wtx.commit()?; + } + + Ok(()) + } + + fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction) -> crate::Result<(),SimulateError> { let height = self.internal_index.internal.block_count()?; let block = self.internal_index.internal.get_block_by_height(height)?.unwrap(); - let mut cache = self.tx_out_cache.borrow_mut(); - let cache = cache.deref_mut(); - - let mut wtx = self.simulate_index.begin_write()?; - // let wtx = Rc::new(RefCell::new(wtx)); - let mut binding = wtx; - let home_inscriptions = binding.open_table(HOME_INSCRIPTIONS).unwrap(); + let home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS).unwrap(); let inscription_id_to_sequence_number = - binding.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); + wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); let inscription_number_to_sequence_number = - binding.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER).unwrap(); - let sat_to_sequence_number = binding.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); - let satpoint_to_sequence_number = binding.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); - let sequence_number_to_children = binding.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); + wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER).unwrap(); + let sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); + let satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); + let sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); let mut sequence_number_to_inscription_entry = - Rc::new(RefCell::new(binding.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap())); - let sequence_number_to_satpoint = binding.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); - let transaction_id_to_transaction = binding.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); - let outpoint_to_entry = Rc::new((RefCell::new(binding.open_table(OUTPOINT_TO_ENTRY).unwrap()))); - let OUTPOINT_TO_SAT_RANGES_table = binding.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); - let sat_to_point = binding.open_table(SAT_TO_SATPOINT).unwrap(); - let statis_to_count = binding.open_table(STATISTIC_TO_COUNT).unwrap(); + Rc::new(RefCell::new(wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap())); + let sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); + let transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); + let outpoint_to_entry = Rc::new((RefCell::new(wtx.open_table(OUTPOINT_TO_ENTRY).unwrap()))); + let OUTPOINT_TO_SAT_RANGES_table = wtx.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); + let sat_to_point = wtx.open_table(SAT_TO_SATPOINT).unwrap(); + let statis_to_count = wtx.open_table(STATISTIC_TO_COUNT).unwrap(); let h = height; let ts = block.header.time; @@ -82,17 +81,17 @@ impl SimulatorServer { current_height: h, current_block_time: ts as u32, internal_index: self.internal_index.clone(), - ORD_TX_TO_OPERATIONS: Rc::new(RefCell::new((binding.open_table(crate::index::ORD_TX_TO_OPERATIONS)?))), - COLLECTIONS_KEY_TO_INSCRIPTION_ID: Rc::new(RefCell::new(binding.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?)), - COLLECTIONS_INSCRIPTION_ID_TO_KINDS: Rc::new(RefCell::new((binding + ORD_TX_TO_OPERATIONS: Rc::new(RefCell::new((wtx.open_table(crate::index::ORD_TX_TO_OPERATIONS)?))), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: Rc::new(RefCell::new(wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?)), + COLLECTIONS_INSCRIPTION_ID_TO_KINDS: Rc::new(RefCell::new((wtx .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?))), SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: sequence_number_to_inscription_entry.clone(), OUTPOINT_TO_ENTRY: outpoint_to_entry.clone(), - BRC20_BALANCES: Rc::new(RefCell::new((binding.open_table(BRC20_BALANCES)?))), - BRC20_TOKEN: Rc::new(RefCell::new((binding.open_table(BRC20_TOKEN)?))), - BRC20_EVENTS: Rc::new(RefCell::new((binding.open_table(BRC20_EVENTS)?))), - BRC20_TRANSFERABLELOG: Rc::new(RefCell::new((binding.open_table(BRC20_TRANSFERABLELOG)?))), - BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new((binding.open_table(BRC20_INSCRIBE_TRANSFER)?))), + BRC20_BALANCES: Rc::new(RefCell::new((wtx.open_table(BRC20_BALANCES)?))), + BRC20_TOKEN: Rc::new(RefCell::new((wtx.open_table(BRC20_TOKEN)?))), + BRC20_EVENTS: Rc::new(RefCell::new((wtx.open_table(BRC20_EVENTS)?))), + BRC20_TRANSFERABLELOG: Rc::new(RefCell::new((wtx.open_table(BRC20_TRANSFERABLELOG)?))), + BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new((wtx.open_table(BRC20_INSCRIBE_TRANSFER)?))), _marker_a: Default::default(), }; @@ -116,20 +115,67 @@ impl SimulatorServer { client: Some(self.client.clone()), context: ctx, }; + + self.loop_simulate_tx(&processor, &tx)?; + Ok(()) + } + pub fn loop_simulate_tx(&self, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(),SimulateError> { + let tx_id = tx.txid(); + let mut need_handle_first = vec![]; + for input in &tx.input { + if input.previous_output.is_null() { + continue; + } + let prev_tx_id = &input.previous_output.txid; + let prev_out = processor.get_txout_by_outpoint(&input.previous_output)?; + if prev_out.is_none() { + need_handle_first.push(prev_tx_id); + } + } + if need_handle_first.is_empty() { + info!("parent suits is ready,start to simulate tx:{:?}",&tx_id); + } + for parent in need_handle_first { + let parent_tx = processor.get_transaction(&parent)?; + if parent_tx.is_none() { + error!("parent tx not exist,tx_hash:{:?},child_hash:{:?}",&parent,&tx_id); + return Err(SimulateError::TxNotFound(parent.clone())) + } + let parent_tx = parent_tx.unwrap(); + info!("parent tx :{:?},exist,but not in utxo data,child_hash:{:?},need to simulate parent tx",&parent,&tx_id); + self.loop_simulate_tx(processor, &parent_tx)?; + info!("parent tx {:?} simulate done,start to simulate child_hash:{:?}",&parent,&tx_id); + } + self.do_simulate_tx(processor, &tx)?; + + Ok(()) + } + + pub fn do_simulate_tx(&self, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(),SimulateError> { + let mut sim = Simulator { + internal_index: self.internal_index.clone(), + client: None, + _marker_a: Default::default(), + _marker_b: Default::default(), + _marker_tx: Default::default(), + }; + let height = self.internal_index.internal.block_count()?; + let block = self.internal_index.internal.get_block_by_height(height)?.unwrap(); + let mut cache = self.tx_out_cache.borrow_mut(); + let cache = cache.deref_mut(); + let mut operations: HashMap> = HashMap::new(); let block = BlockData { header: block.header, txdata: vec![(tx.clone(), tx.txid())], }; - sim.index_block(block.clone(), height, cache, processor, &mut operations)?; - - - binding.commit()?; + sim.index_block(block.clone(), height, cache, &processor, &mut operations)?; Ok(()) } + pub fn new(internal_index: Arc, simulate_index: Arc, client: DirectClient>>) -> Self { - Self { tx_out_cache: Default::default(), internal_index: IndexWrapper::new(internal_index), simulate_index, client } + Self { tx_out_cache: Rc::new(RefCell::new(SimpleLru::new(500))), internal_index: IndexWrapper::new(internal_index), simulate_index, client } } } @@ -139,7 +185,7 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { block: BlockData, height: u32, tx_out_cache: &'a mut SimpleLru, - processor: StorageProcessor<'a, 'db, 'tx>, + processor: &StorageProcessor<'a, 'db, 'tx>, operations: &'a mut HashMap>, ) -> crate::Result<()> { let mut sat_ranges_written = 0; @@ -191,7 +237,7 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { if let Some(tx_out) = value { tx_out_cache.insert(out_point, tx_out); } else { - let tx = processor.get_transaction(&out_point.txid)?; + let tx = processor.get_transaction(&out_point.txid)?.unwrap(); let out = tx.output[out_point.vout as usize].clone(); let tx_out = TxOut { value: out.value, @@ -300,8 +346,6 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { Ok(()) } - - fn index_and_execute(&self) {} fn index_transaction_sats( &mut self, tx: &Transaction, @@ -366,18 +410,30 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { #[cfg(test)] mod tests { + use std::str::FromStr; + use bitcoincore_rpc::RpcApi; use indexer_sdk::factory::common::new_client_for_test; + use log::LevelFilter; use super::*; #[test] pub fn test_simulate_tx() { + env_logger::builder() + .filter_level(LevelFilter::Debug) + .format_target(false) + .init(); let opt = create_options(); let internal = Arc::new(Index::open(&opt).unwrap()); let mut opt2 = opt.clone(); opt2.index = Some(PathBuf::from("./simulate")); - let simulate_index = Index::open(&opt2).unwrap(); + let simulate_index = Arc::new(Index::open(&opt2).unwrap()); let client = new_client_for_test("http://localhost:18443".to_string(), "bitcoinrpc".to_string(), "bitcoinrpc".to_string()); - let simulate_server = SimulatorServer::new(internal.clone(), simulate_index.clone(), client); + let simulate_server = SimulatorServer::new(internal.clone(), simulate_index.clone(), client.clone()); + + let client = client.clone().get_btc_client(); + let tx = client.get_raw_transaction(&Txid::from_str("f2ecd8708afbb0056709333a60882536c7d070633e1ee7cf80d83ad35e1f8403").unwrap(), None).unwrap(); + println!("{:?}", tx); + simulate_server.execute_tx(&tx, true).unwrap(); } fn create_options() -> Options { @@ -412,60 +468,4 @@ mod tests { }; opt } - - #[test] - pub fn test_simulate() { - let opt = create_options(); - let internal = IndexWrapper::new(Arc::new(Index::open(&opt).unwrap())); - let mut sim = Simulator { - // simulate_index: IndexTracer {}, - internal_index: internal.clone(), - client: None, - _marker_a: Default::default(), - _marker_b: Default::default(), - _marker_tx: Default::default(), - }; - let mut opt2 = opt.clone(); - opt2.index = Some(PathBuf::from("./simulate")); - let simulate_index = Index::open(&opt2).unwrap(); - let mut wtx = simulate_index.begin_write().unwrap(); - let wtx = Rc::new(RefCell::new(wtx)); - let binding = wtx.borrow(); - let mut home_inscriptions = binding.open_table(HOME_INSCRIPTIONS).unwrap(); - let mut inscription_id_to_sequence_number = - binding.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); - let mut inscription_number_to_sequence_number = - binding.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER).unwrap(); - let mut sat_to_sequence_number = binding.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); - let mut satpoint_to_sequence_number = binding.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); - let mut sequence_number_to_children = binding.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); - let mut sequence_number_to_inscription_entry = - binding.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(); - let mut sequence_number_to_satpoint = binding.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); - let mut transaction_id_to_transaction = binding.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); - let mut outpoint_to_entry = binding.open_table(OUTPOINT_TO_ENTRY).unwrap(); - let mut OUTPOINT_TO_SAT_RANGES_table = binding.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); - let sat_to_point = binding.open_table(SAT_TO_SATPOINT).unwrap(); - let statis_to_count = binding.open_table(STATISTIC_TO_COUNT).unwrap(); - // let processor = StorageProcessor { - // internal: internal.clone(), - // // wtx: &mut wtx, - // home_inscriptions: Rc::new(RefCell::new(home_inscriptions)), - // id_to_sequence_number: Rc::new(RefCell::new(inscription_id_to_sequence_number)), - // inscription_number_to_sequence_number: Rc::new(RefCell::new(inscription_number_to_sequence_number)), - // outpoint_to_entry: Rc::new(RefCell::new(outpoint_to_entry)), - // transaction_id_to_transaction: Rc::new(RefCell::new(transaction_id_to_transaction)), - // sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), - // satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), - // sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), - // sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), - // sequence_number_to_inscription_entry: Rc::new(RefCell::new((sequence_number_to_inscription_entry))), - // OUTPOINT_TO_SAT_RANGES: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), - // sat_to_satpoint: Rc::new(RefCell::new((sat_to_point))), - // statistic_to_count: Rc::new(RefCell::new((statis_to_count))), - // _marker_a: Default::default(), - // client: None, - // context: SimulateContext {}, - // }; - } } diff --git a/src/index/updater.rs b/src/index/updater.rs index 8213177572..22bb58a87e 100644 --- a/src/index/updater.rs +++ b/src/index/updater.rs @@ -15,6 +15,7 @@ mod rune_updater; pub mod pending_updater; mod pending2; + #[derive(Clone)] pub(crate) struct BlockData { pub(crate) header: Header, diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index b571be6f8c..f00a264ae7 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -2,7 +2,7 @@ use { super::*, crate::okx::datastore::ord::operation::{Action, InscriptionOp}, }; -use crate::index::processor::StorageProcessor; +use crate::index::simulator::processor::StorageProcessor; use crate::index::updater::inscription_updater::{Flotsam, Origin}; diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index 400af1fb10..2554c03d9e 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -789,10 +789,9 @@ use redb::{Database, MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbV use tempfile::NamedTempFile; use crate::{Index, InscriptionId, SatPoint}; use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; -use crate::index::processor::IndexWrapper; +use crate::index::simulator::processor::IndexWrapper; use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick, insert_inscribe_transfer_inscription, insert_token_info, insert_transferable, remove_inscribe_transfer_inscription, remove_transferable, save_transaction_receipts, update_token_balance}; -use crate::okx::datastore::cache::CacheWriter; use crate::okx::datastore::ord::{InscriptionOp, OrdReader, OrdReaderWriter}; use crate::okx::datastore::ord::collections::CollectionKind; use crate::okx::datastore::ord::redb::table::{get_collection_inscription_id, get_collections_of_inscription, get_inscription_number_by_sequence_number, get_transaction_operations, get_txout_by_outpoint, save_transaction_operations, set_inscription_attributes, set_inscription_by_collection_key}; From e48414ff825de2806638e128592b48098c196339 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sat, 13 Jan 2024 23:26:25 +0800 Subject: [PATCH 30/66] rm uselss codes --- src/index/database_processor.rs | 51 ---- src/index/simulator/processor.rs | 220 +------------- src/index/simulator/simulate.rs | 20 +- src/index/updater/pending2.rs | 496 ------------------------------- 4 files changed, 13 insertions(+), 774 deletions(-) delete mode 100644 src/index/database_processor.rs delete mode 100644 src/index/updater/pending2.rs diff --git a/src/index/database_processor.rs b/src/index/database_processor.rs deleted file mode 100644 index 145a15d236..0000000000 --- a/src/index/database_processor.rs +++ /dev/null @@ -1,51 +0,0 @@ -use std::sync::Arc; -use bitcoin::{OutPoint, TxOut}; -use redb::{ReadTransaction, WriteTransaction}; -use crate::{Index, InscriptionId, SatPoint}; -use crate::index::{InscriptionEntryValue, InscriptionIdValue, TxidValue}; - -pub struct DataBaseProcessor<'a, 'db> { - rtx:&'a ReadTransaction<'db>, - wtx: &'a WriteTransaction<'db>, -} - -impl<'a, 'db> DataBaseProcessor<'a, 'db> { - pub(crate) fn tx_out_cache_insert(&self, p0: &OutPoint, p1: TxOut) -> crate::Result<()> { - todo!() - } -} - -impl<'a, 'db> DataBaseProcessor<'a, 'db> { - pub(crate) fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { - todo!() - } -} - -impl<'a, 'db> DataBaseProcessor<'a, 'db> { - pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { - todo!() - } -} - -impl<'a, 'db> DataBaseProcessor<'a, 'db> { - pub(crate) fn id_to_sequence_number_get(&self, x: InscriptionIdValue) -> crate::Result> { - todo!() - } -} - -impl<'a, 'db> DataBaseProcessor<'a, 'db> { - pub(crate) fn get_txout_by_outpoint(&self, p0: &OutPoint) -> crate::Result { - todo!() - } -} - -impl<'a, 'db> DataBaseProcessor<'a, 'db> { - pub fn inscriptions_on_output(&self, prev_output: &OutPoint) -> crate::Result> { - // let ret = Index::inscriptions_on_output( - // self.satpoint_to_sequence_number, - // self.sequence_number_to_entry, - // prev_output.clone())?; - // TODO: twice - todo!() - } -} diff --git a/src/index/simulator/processor.rs b/src/index/simulator/processor.rs index 62e359c8a7..8c094e3f2d 100644 --- a/src/index/simulator/processor.rs +++ b/src/index/simulator/processor.rs @@ -1,211 +1,3 @@ -// use std::sync::Arc; -// use bitcoin::{OutPoint, TxOut}; -// use redb::{RedbValue, WriteTransaction}; -// use crate::{Index, InscriptionId, SatPoint}; -// use crate::index::entry::SatPointValue; -// use crate::index::{InscriptionEntryValue, InscriptionIdValue, OutPointValue, TxidValue}; -// use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; -// use crate::okx::protocol::context::Context; -// -// pub struct StorageProcessor<'a, 'db,'tx> { -// pub cache_writer: CacheWriter, -// pub internal: Arc, -// -// pub wtx: &'a mut WriteTransaction<'db>, -// } -// -// unsafe impl<'a, 'db,'tx> Send for StorageProcessor<'a, 'db,'tx> {} -// -// unsafe impl<'a, 'db,'tx> Sync for StorageProcessor<'a, 'db,'tx> {} -// -// -// impl<'a, 'db,'tx> StorageProcessor<'a, 'db,'tx> { -// pub(crate) fn create_context(&self) -> crate::Result { -// todo!() -// } -// pub(crate) fn next_sequence_number(&self) -> crate::Result { -// todo!() -// } -// pub(crate) fn outpoint_to_sat_ranges_insert(&self, value: &OutPointValue, data: &[u8]) -> crate::Result<()> { -// todo!() -// } -// pub(crate) fn outpoint_to_sat_ranges_remove(&self, p0: &OutPointValue) -> crate::Result>> { -// todo!() -// } -// pub fn get_lost_sats(&self) -> crate::Result { -// todo!() -// } -// pub fn get_cursed_inscription_count(&self) -> crate::Result { -// todo!() -// } -// pub fn get_blessed_inscription_count(&self) -> crate::Result { -// todo!() -// } -// pub fn get_unbound_inscriptions(&self) -> crate::Result { -// todo!() -// } -// pub fn get_next_sequence_number(&self) -> crate::Result { -// todo!() -// } -// pub fn sat_to_satpoint_insert(&self, key: &u64, value: &SatPointValue) -> crate::Result<()> { -// todo!() -// } -// pub fn get_txout_by_outpoint(&self, x: &OutPoint) -> crate::Result> { -// todo!() -// } -// pub(crate) fn satpoint_to_sequence_number_remove_all(&self, v: &SatPointValue) -> crate::Result<()> { -// // self -// // .satpoint_to_sequence_number -// // .remove_all(v)?; -// // Ok(()) -// todo!() -// } -// pub(crate) fn home_inscriptions_len(&self) -> u64 { -// todo!() -// } -// pub(crate) fn sequence_number_to_satpoint_insert(&self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { -// // self.sequence_number_to_satpoint.insert(sequence_number, sat_point)?; -// -// let key = u32::as_bytes(&sequence_number).to_vec(); -// let value = sat_point.to_vec(); -// self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_SATPOINT, |v| { -// v.insert(key.to_vec(), value.to_vec()); -// }); -// Ok(()) -// } -// pub(crate) fn satpoint_to_sequence_number_insert(&self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { -// // self.sequence_number_to_satpoint.insert(sequence, sat_point)?; -// -// let key = sat_point.to_vec(); -// let value = u32::as_bytes(&sequence).to_vec(); -// self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { -// v.insert(key.to_vec(), value.to_vec()); -// }); -// Ok(()) -// } -// pub(crate) fn home_inscriptions_pop_first(&self) -> crate::Result<()> { -// // self.home_inscriptions.pop_first()?; -// -// self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { -// v.pop_first() -// }); -// Ok(()) -// } -// pub(crate) fn home_inscriptions_insert(&self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { -// let key = u32::as_bytes(sequence_number).to_vec(); -// let value = InscriptionIdValue::as_bytes(&value).to_vec(); -// self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { -// v.insert(key.to_vec(), value.to_vec()); -// }); -// Ok(()) -// // self -// // .home_inscriptions -// // .insert(sequence_number, value)?; -// // Ok(()) -// } -// pub(crate) fn id_to_sequence_number_insert(&self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { -// // let key = rmp_serde::to_vec(value).unwrap(); -// // let value = sequence.to_le_bytes().as_slice(); -// // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |v| { -// // v.insert(key.to_vec(), value.to_vec()); -// // }); -// // Ok(()) -// // self -// // .id_to_sequence_number -// // .insert(value, sequence_number)?; -// Ok(()) -// } -// pub(crate) fn sequence_number_to_children_insert(&self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { -// // let key = sequence.to_le_bytes().as_slice(); -// // let value = rmp_serde::to_vec(value).unwrap(); -// // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_CHILDREN, |v| { -// // v.insert(key.to_vec(), value.to_vec()); -// // }); -// // Ok(()) -// // self -// // .sequence_number_to_children -// // .insert(parent_sequence_number, sequence_number)?; -// Ok(()) -// } -// pub(crate) fn sequence_number_to_entry_insert(&self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { -// // let key = sequence.to_le_bytes().as_slice(); -// // let value = rmp_serde::to_vec(value).unwrap(); -// // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |v| { -// // v.insert(key.to_vec(), value.to_vec()); -// // }); -// // Ok(()) -// // self.sequence_number_to_entry.insert(sequence, value)?; -// Ok(()) -// } -// pub(crate) fn sat_to_sequence_number_insert(&self, n: &u64, sequence_number: &u32) -> crate::Result<()> { -// // let key = n.to_le_bytes().as_slice(); -// // let value = sequence.to_le_bytes().as_slice(); -// // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { -// // v.insert(key.to_vec(), value.to_vec()); -// // }); -// // Ok(()) -// // self.sat_to_sequence_number.insert(n, sequence_number)?; -// Ok(()) -// } -// pub(crate) fn inscription_number_to_sequence_number_insert(&self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { -// // let key = inscription_number.to_le_bytes().as_slice(); -// // let value = sequence_number.to_le_bytes().as_slice(); -// // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, |v| { -// // v.insert(key.to_vec(), value.to_vec()); -// // }); -// // Ok(()) -// // self -// // .inscription_number_to_sequence_number -// // .insert(inscription_number, sequence_number)?; -// Ok(()) -// } -// pub(crate) fn outpoint_to_entry_insert(&self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { -// // self.outpoint_to_entry.insert(value, entry)?; -// Ok(()) -// // let key = rmp_serde::to_vec(value).unwrap(); -// // let value = entry.to_vec(); -// // self.cache_writer.use_cache_mut(CacheTableIndex::OUTPOINT_TO_ENTRY, |v| { -// // v.insert(key.to_vec(), value.to_vec()); -// // }); -// // Ok(()) -// } -// pub fn inscriptions_on_output(&self, prev_output: &OutPoint) -> crate::Result> { -// // let ret = Index::inscriptions_on_output( -// // self.satpoint_to_sequence_number, -// // self.sequence_number_to_entry, -// // prev_output.clone())?; -// // TODO: twice -// todo!() -// } -// -// pub(crate) fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { -// // self -// // .transaction_id_to_transaction -// // .insert(tx_id, value)?; -// -// Ok(()) -// } -// -// pub(crate) fn id_to_sequence_number_get(&self, x: InscriptionIdValue) -> crate::Result> { -// // TODO,twice -// // let ret = self.id_to_sequence_number.get(x)?.unwrap().value(); -// // Ok(Some(ret)) -// todo!() -// } -// pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { -// // TODO: twice -// // let ret = self -// // .sequence_number_to_entry -// // .get(initial_inscription_sequence_number)? -// // .unwrap() -// // .value(); -// // Ok(Some(ret)) -// todo!() -// } -// } -////////////////// - - use std::cell::RefCell; use std::collections::HashSet; use std::marker::PhantomData; @@ -219,16 +11,13 @@ use indexer_sdk::client::SyncClient; use indexer_sdk::storage::db::memory::MemoryDB; use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; -use log::info; -use redb::{MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; +use redb::{MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition}; use crate::{Index, InscriptionId, SatPoint}; -use crate::index::entry::{Entry, SatPointValue}; -use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; -use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; +use crate::index::entry::{SatPointValue}; +use crate::index::{HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::protocol::context::Context; use crate::okx::protocol::simulate::SimulateContext; -use crate::RpcApi; #[derive(Clone)] pub struct IndexWrapper { @@ -288,9 +77,8 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { } pub fn get_transaction(&self, tx_id: &Txid) -> crate::Result> { - info!("get_transaction: {:?}", tx_id); let client = self.client.as_ref().unwrap(); - let ret=client.get_transaction_by_tx_id(tx_id.clone())?; + let ret = client.get_transaction_by_tx_id(tx_id.clone())?; Ok(ret) } pub(crate) fn create_simulate_context(&self) -> crate::Result> { diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index b1b77d9e1c..7f6350c756 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -15,20 +15,19 @@ use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; use log::{error, info}; use redb::{ReadableTable, WriteTransaction}; -use crate::{Index, Options, Rune, RuneEntry, Sat, SatPoint, timestamp}; +use crate::{Index, Options, Sat, SatPoint}; use crate::height::Height; -use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HEIGHT_TO_BLOCK_HEADER, HEIGHT_TO_LAST_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, OUTPOINT_TO_RUNE_BALANCES, OUTPOINT_TO_SAT_RANGES, RUNE_ID_TO_RUNE_ENTRY, RUNE_TO_RUNE_ID, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_RUNE_ID, SEQUENCE_NUMBER_TO_SATPOINT, Statistic, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_RUNE, TRANSACTION_ID_TO_TRANSACTION}; -use crate::index::entry::{Entry, SatPointValue, SatRange}; +use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION}; +use crate::index::entry::Entry; use crate::index::simulator::error::SimulateError; use crate::index::simulator::processor::{IndexWrapper, StorageProcessor}; use crate::index::updater::pending_updater::PendingUpdater; use crate::okx::datastore::ord::InscriptionOp; use crate::okx::lru::SimpleLru; -use crate::okx::protocol::{BlockContext, ProtocolConfig, ProtocolManager}; +use crate::okx::protocol::{ProtocolConfig, ProtocolManager}; use crate::okx::protocol::simulate::SimulateContext; pub struct Simulator<'a, 'db, 'tx> { - // pub simulate_index: IndexTracer, pub internal_index: IndexWrapper, pub client: Option>>>, _marker_a: PhantomData<&'a ()>, @@ -44,7 +43,7 @@ pub struct SimulatorServer { } impl SimulatorServer { - pub fn execute_tx(&self, tx: &Transaction, commit: bool) -> crate::Result<(),SimulateError> { + pub fn execute_tx(&self, tx: &Transaction, commit: bool) -> crate::Result<(), SimulateError> { let mut wtx = self.simulate_index.begin_write()?; self.simulate_tx(tx, &wtx)?; if commit { @@ -54,7 +53,7 @@ impl SimulatorServer { Ok(()) } - fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction) -> crate::Result<(),SimulateError> { + fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction) -> crate::Result<(), SimulateError> { let height = self.internal_index.internal.block_count()?; let block = self.internal_index.internal.get_block_by_height(height)?.unwrap(); let home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS).unwrap(); @@ -119,7 +118,7 @@ impl SimulatorServer { self.loop_simulate_tx(&processor, &tx)?; Ok(()) } - pub fn loop_simulate_tx(&self, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(),SimulateError> { + pub fn loop_simulate_tx(&self, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(), SimulateError> { let tx_id = tx.txid(); let mut need_handle_first = vec![]; for input in &tx.input { @@ -139,7 +138,7 @@ impl SimulatorServer { let parent_tx = processor.get_transaction(&parent)?; if parent_tx.is_none() { error!("parent tx not exist,tx_hash:{:?},child_hash:{:?}",&parent,&tx_id); - return Err(SimulateError::TxNotFound(parent.clone())) + return Err(SimulateError::TxNotFound(parent.clone())); } let parent_tx = parent_tx.unwrap(); info!("parent tx :{:?},exist,but not in utxo data,child_hash:{:?},need to simulate parent tx",&parent,&tx_id); @@ -151,7 +150,7 @@ impl SimulatorServer { Ok(()) } - pub fn do_simulate_tx(&self, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(),SimulateError> { + pub fn do_simulate_tx(&self, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(), SimulateError> { let mut sim = Simulator { internal_index: self.internal_index.clone(), client: None, @@ -254,7 +253,6 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { let unbound_inscriptions = processor.get_unbound_inscriptions()?; let next_sequence_number = processor.next_sequence_number()?; - // let processor = &mut self.processor; let mut inscription_updater = PendingUpdater::new( operations, blessed_inscription_count, diff --git a/src/index/updater/pending2.rs b/src/index/updater/pending2.rs deleted file mode 100644 index b111d1067c..0000000000 --- a/src/index/updater/pending2.rs +++ /dev/null @@ -1,496 +0,0 @@ -// use std::collections::{BTreeMap, HashSet, VecDeque}; -// use anyhow::anyhow; -// use bitcoin::{OutPoint, Transaction, Txid}; -// use bitcoin::consensus::Encodable; -// use crate::height::Height; -// use crate::{Index, InscriptionId, Rarity, Sat, SatPoint, unbound_outpoint}; -// use crate::index::database_processor::DataBaseProcessor; -// use crate::index::entry::Entry; -// use crate::index::InscriptionEntry; -// use crate::index::processor::StorageProcessor; -// use crate::index::updater::inscription_updater::{Curse, Flotsam, Origin}; -// use crate::inscriptions::{Charm, ParsedEnvelope}; -// use crate::okx::datastore::ord::{Action, InscriptionOp}; -// -// pub struct PendingUpdater2<'a, 'db> { -// pub processor: &'a DataBaseProcessor<'a, 'db>, -// pub(super) flotsam: Vec, -// pub(super) lost_sats: u64, -// pub(super) reward: u64, -// } -// -// impl<'a,'db> PendingUpdater2<'a,'db> { -// pub(super) fn index_envelopes( -// &mut self, -// tx: &Transaction, -// txid: Txid, -// input_sat_ranges: Option<&VecDeque<(u64, u64)>>, -// ) -> crate::Result { -// let mut floating_inscriptions = Vec::new(); -// let mut id_counter = 0; -// let mut inscribed_offsets = BTreeMap::new(); -// let jubilant = true; -// let mut total_input_value = 0; -// let total_output_value = tx.output.iter().map(|txout| txout.value).sum::(); -// -// let envelopes = ParsedEnvelope::from_transaction(tx); -// let inscriptions = !envelopes.is_empty(); -// let mut envelopes = envelopes.into_iter().peekable(); -// -// for (input_index, tx_in) in tx.input.iter().enumerate() { -// // skip subsidy since no inscriptions possible -// if tx_in.previous_output.is_null() { -// continue; -// } -// -// // find existing inscriptions on input (transfers of inscriptions) -// -// for (old_satpoint, inscription_id) in self.processor.inscriptions_on_output(&tx_in.previous_output)? { -// let offset = total_input_value + old_satpoint.offset; -// floating_inscriptions.push(Flotsam { -// txid, -// offset, -// inscription_id, -// old_satpoint, -// origin: Origin::Old, -// }); -// -// inscribed_offsets -// .entry(offset) -// .or_insert((inscription_id, 0)) -// .1 += 1; -// } -// -// let offset = total_input_value; -// -// // multi-level cache for UTXO set to get to the input amount -// let current_input_value = self.processor.get_txout_by_outpoint(&tx_in.previous_output)?; -// -// total_input_value += current_input_value; -// -// // go through all inscriptions in this input -// while let Some(inscription) = envelopes.peek() { -// if inscription.input != u32::try_from(input_index).unwrap() { -// break; -// } -// -// let inscription_id = InscriptionId { -// txid, -// index: id_counter, -// }; -// -// let curse = if inscription.payload.unrecognized_even_field { -// Some(Curse::UnrecognizedEvenField) -// } else if inscription.payload.duplicate_field { -// Some(Curse::DuplicateField) -// } else if inscription.payload.incomplete_field { -// Some(Curse::IncompleteField) -// } else if inscription.input != 0 { -// Some(Curse::NotInFirstInput) -// } else if inscription.offset != 0 { -// Some(Curse::NotAtOffsetZero) -// } else if inscription.payload.pointer.is_some() { -// Some(Curse::Pointer) -// } else if inscription.pushnum { -// Some(Curse::Pushnum) -// } else if inscription.stutter { -// Some(Curse::Stutter) -// } else if let Some((id, count)) = inscribed_offsets.get(&offset) { -// if *count > 1 { -// Some(Curse::Reinscription) -// } else { -// let initial_inscription_sequence_number = -// self.processor.id_to_sequence_number_get(id.store())?.unwrap(); -// -// let entry = InscriptionEntry::load(self.processor.sequence_number_to_entry_get(initial_inscription_sequence_number)?.unwrap()); -// -// let initial_inscription_was_cursed_or_vindicated = -// entry.inscription_number < 0 || Charm::Vindicated.is_set(entry.charms); -// -// if initial_inscription_was_cursed_or_vindicated { -// None -// } else { -// Some(Curse::Reinscription) -// } -// } -// } else { -// None -// }; -// -// let unbound = current_input_value == 0 -// || curse == Some(Curse::UnrecognizedEvenField) -// || inscription.payload.unrecognized_even_field; -// -// let offset = inscription -// .payload -// .pointer() -// .filter(|&pointer| pointer < total_output_value) -// .unwrap_or(offset); -// -// floating_inscriptions.push(Flotsam { -// txid, -// inscription_id, -// offset, -// old_satpoint: SatPoint { -// outpoint: tx_in.previous_output, -// offset: 0, -// }, -// origin: Origin::New { -// cursed: curse.is_some() && !jubilant, -// fee: 0, -// hidden: inscription.payload.hidden(), -// parent: inscription.payload.parent(), -// pointer: inscription.payload.pointer(), -// reinscription: inscribed_offsets.get(&offset).is_some(), -// unbound, -// inscription: inscription.payload.clone(), -// vindicated: curse.is_some() && jubilant, -// }, -// }); -// -// inscribed_offsets -// .entry(offset) -// .or_insert((inscription_id, 0)) -// .1 += 1; -// -// envelopes.next(); -// id_counter += 1; -// } -// } -// -// if inscriptions { -// let mut transaction_buffer = vec![]; -// tx.consensus_encode(&mut transaction_buffer) -// .expect("in-memory writers don't error"); -// -// self.processor.transaction_id_to_transaction_insert(&txid.store(), transaction_buffer.as_slice())?; -// } -// -// let potential_parents = floating_inscriptions -// .iter() -// .map(|flotsam| flotsam.inscription_id) -// .collect::>(); -// -// for flotsam in &mut floating_inscriptions { -// if let Flotsam { -// origin: Origin::New { parent, .. }, -// .. -// } = flotsam -// { -// if let Some(purported_parent) = parent { -// if !potential_parents.contains(purported_parent) { -// *parent = None; -// } -// } -// } -// } -// -// // still have to normalize over inscription size -// for flotsam in &mut floating_inscriptions { -// if let Flotsam { -// origin: Origin::New { ref mut fee, .. }, -// .. -// } = flotsam -// { -// *fee = (total_input_value - total_output_value) / u64::from(id_counter); -// } -// } -// -// let is_coinbase = tx -// .input -// .first() -// .map(|tx_in| tx_in.previous_output.is_null()) -// .unwrap_or_default(); -// -// if is_coinbase { -// floating_inscriptions.append(&mut self.flotsam); -// } -// -// floating_inscriptions.sort_by_key(|flotsam| flotsam.offset); -// let mut inscriptions = floating_inscriptions.into_iter().peekable(); -// -// let mut range_to_vout = BTreeMap::new(); -// let mut new_locations = Vec::new(); -// let mut output_value = 0; -// for (vout, tx_out) in tx.output.iter().enumerate() { -// let end = output_value + tx_out.value; -// -// while let Some(flotsam) = inscriptions.peek() { -// if flotsam.offset >= end { -// break; -// } -// -// let new_satpoint = SatPoint { -// outpoint: OutPoint { -// txid, -// vout: vout.try_into().unwrap(), -// }, -// offset: flotsam.offset - output_value, -// }; -// -// new_locations.push((new_satpoint, inscriptions.next().unwrap())); -// } -// -// range_to_vout.insert((output_value, end), vout.try_into().unwrap()); -// -// output_value = end; -// -// self.processor.tx_out_cache_insert(&OutPoint { -// vout: vout.try_into().unwrap(), -// txid, -// }, tx_out.clone())?; -// } -// -// for (new_satpoint, mut flotsam) in new_locations.into_iter() { -// let new_satpoint = match flotsam.origin { -// Origin::New { -// pointer: Some(pointer), -// .. -// } if pointer < output_value => { -// match range_to_vout.iter().find_map(|((start, end), vout)| { -// (pointer >= *start && pointer < *end).then(|| (vout, pointer - start)) -// }) { -// Some((vout, offset)) => { -// flotsam.offset = pointer; -// SatPoint { -// outpoint: OutPoint { txid, vout: *vout }, -// offset, -// } -// } -// _ => new_satpoint, -// } -// } -// _ => new_satpoint, -// }; -// -// self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; -// } -// -// if is_coinbase { -// for flotsam in inscriptions { -// let new_satpoint = SatPoint { -// outpoint: OutPoint::null(), -// offset: self.lost_sats + flotsam.offset - output_value, -// }; -// self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; -// } -// self.lost_sats += self.reward - output_value; -// Ok(()) -// } else { -// self.flotsam.extend(inscriptions.map(|flotsam| Flotsam { -// offset: self.reward + flotsam.offset - output_value, -// ..flotsam -// })); -// self.reward += total_input_value - output_value; -// Ok(()) -// } -// } -// -// fn update_inscription_location( -// &mut self, -// input_sat_ranges: Option<&VecDeque<(u64, u64)>>, -// flotsam: Flotsam, -// new_satpoint: SatPoint, -// ) -> crate::Result { -// let inscription_id = flotsam.inscription_id; -// let (unbound, sequence_number) = match flotsam.origin { -// Origin::Old => { -// self -// .processor.satpoint_to_sequence_number_remove_all(&flotsam.old_satpoint.store())?; -// -// ( -// false, -// self -// .processor.id_to_sequence_number_get( -// inscription_id.store())? -// .unwrap() -// ) -// } -// Origin::New { -// cursed, -// fee, -// hidden, -// parent, -// pointer: _, -// reinscription, -// unbound, -// inscription: _, -// vindicated, -// } => { -// let inscription_number = if cursed { -// let number: i32 = self.cursed_inscription_count.try_into().unwrap(); -// self.cursed_inscription_count += 1; -// -// // because cursed numbers start at -1 -// -(number + 1) -// } else { -// let number: i32 = self.blessed_inscription_count.try_into().unwrap(); -// self.blessed_inscription_count += 1; -// -// number -// }; -// -// let sequence_number = self.next_sequence_number; -// self.next_sequence_number += 1; -// -// self -// .processor.inscription_number_to_sequence_number_insert( -// inscription_number, sequence_number)?; -// -// let sat = if unbound { -// None -// } else { -// Self::calculate_sat(input_sat_ranges, flotsam.offset) -// }; -// -// let mut charms = 0; -// -// if cursed { -// Charm::Cursed.set(&mut charms); -// } -// -// if reinscription { -// Charm::Reinscription.set(&mut charms); -// } -// -// if let Some(sat) = sat { -// if sat.nineball() { -// Charm::Nineball.set(&mut charms); -// } -// -// if sat.coin() { -// Charm::Coin.set(&mut charms); -// } -// -// match sat.rarity() { -// Rarity::Common | Rarity::Mythic => {} -// Rarity::Uncommon => Charm::Uncommon.set(&mut charms), -// Rarity::Rare => Charm::Rare.set(&mut charms), -// Rarity::Epic => Charm::Epic.set(&mut charms), -// Rarity::Legendary => Charm::Legendary.set(&mut charms), -// } -// } -// -// if new_satpoint.outpoint == OutPoint::null() { -// Charm::Lost.set(&mut charms); -// } -// -// if unbound { -// Charm::Unbound.set(&mut charms); -// } -// -// if vindicated { -// Charm::Vindicated.set(&mut charms); -// } -// -// if let Some(Sat(n)) = sat { -// self.processor.sat_to_sequence_number_insert(&n, &sequence_number)?; -// } -// -// let parent = match parent { -// Some(parent_id) => { -// let parent_sequence_number = self -// .processor.id_to_sequence_number_get( -// parent_id.store())? -// .unwrap(); -// self -// .processor.sequence_number_to_children_insert( -// parent_sequence_number, sequence_number)?; -// -// Some(parent_sequence_number) -// } -// None => None, -// }; -// -// self.processor.sequence_number_to_entry_insert( -// sequence_number, -// &InscriptionEntry { -// charms, -// fee, -// height: self.height, -// id: inscription_id, -// inscription_number, -// parent, -// sat, -// sequence_number, -// timestamp: self.timestamp, -// } -// .store(), -// )?; -// -// self -// .processor.id_to_sequence_number_insert( -// &inscription_id.store(), sequence_number)?; -// -// if !hidden { -// self -// .processor.home_inscriptions_insert( -// &sequence_number, inscription_id.store())?; -// -// if self.home_inscription_count == 100 { -// self.processor.home_inscriptions_pop_first()?; -// } else { -// self.home_inscription_count += 1; -// } -// } -// -// (unbound, sequence_number) -// } -// }; -// -// let satpoint = if unbound { -// let new_unbound_satpoint = SatPoint { -// outpoint: unbound_outpoint(), -// offset: self.unbound_inscriptions, -// }; -// self.unbound_inscriptions += 1; -// new_unbound_satpoint.store() -// } else { -// new_satpoint.store() -// }; -// -// self -// .operations -// .entry(flotsam.txid) -// .or_default() -// .push(InscriptionOp { -// txid: flotsam.txid, -// sequence_number, -// inscription_number: self -// .processor.sequence_number_to_entry_get( -// sequence_number)? -// .map(|entry| InscriptionEntry::load(entry).inscription_number), -// inscription_id: flotsam.inscription_id, -// action: match flotsam.origin { -// Origin::Old => Action::Transfer, -// Origin::New { -// cursed, -// fee: _, -// hidden: _, -// parent: _, -// pointer: _, -// reinscription: _, -// unbound, -// inscription, -// vindicated, -// } => Action::New { -// cursed, -// unbound, -// vindicated, -// inscription, -// }, -// }, -// old_satpoint: flotsam.old_satpoint, -// new_satpoint: Some(Entry::load(satpoint)), -// }); -// -// self -// .processor.satpoint_to_sequence_number_insert( -// &satpoint, sequence_number)?; -// self -// .processor.sequence_number_to_satpoint_insert( -// sequence_number, &satpoint)?; -// -// Ok(()) -// } -// } \ No newline at end of file From 664a72b5211e644238ea79642da728506ad48550 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sat, 13 Jan 2024 23:29:59 +0800 Subject: [PATCH 31/66] add --- src/index.rs | 1 - src/index/simulator/simulate.rs | 24 ++++++++++++------------ src/index/updater.rs | 1 - src/okx/protocol/brc20/msg_executor.rs | 1 - 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/index.rs b/src/index.rs index f5eeef2d6e..39260981a3 100644 --- a/src/index.rs +++ b/src/index.rs @@ -53,7 +53,6 @@ pub(crate) mod updater; #[cfg(test)] pub(crate) mod testing; pub mod simulator; -mod database_processor; const SCHEMA_VERSION: u64 = 16; diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 7f6350c756..8015914a1b 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -14,7 +14,7 @@ use indexer_sdk::storage::db::memory::MemoryDB; use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; use log::{error, info}; -use redb::{ReadableTable, WriteTransaction}; +use redb::{ WriteTransaction}; use crate::{Index, Options, Sat, SatPoint}; use crate::height::Height; use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION}; @@ -68,7 +68,7 @@ impl SimulatorServer { Rc::new(RefCell::new(wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap())); let sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); let transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); - let outpoint_to_entry = Rc::new((RefCell::new(wtx.open_table(OUTPOINT_TO_ENTRY).unwrap()))); + let outpoint_to_entry = Rc::new(RefCell::new(wtx.open_table(OUTPOINT_TO_ENTRY).unwrap())); let OUTPOINT_TO_SAT_RANGES_table = wtx.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); let sat_to_point = wtx.open_table(SAT_TO_SATPOINT).unwrap(); let statis_to_count = wtx.open_table(STATISTIC_TO_COUNT).unwrap(); @@ -80,17 +80,17 @@ impl SimulatorServer { current_height: h, current_block_time: ts as u32, internal_index: self.internal_index.clone(), - ORD_TX_TO_OPERATIONS: Rc::new(RefCell::new((wtx.open_table(crate::index::ORD_TX_TO_OPERATIONS)?))), + ORD_TX_TO_OPERATIONS: Rc::new(RefCell::new(wtx.open_table(crate::index::ORD_TX_TO_OPERATIONS)?)), COLLECTIONS_KEY_TO_INSCRIPTION_ID: Rc::new(RefCell::new(wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?)), - COLLECTIONS_INSCRIPTION_ID_TO_KINDS: Rc::new(RefCell::new((wtx - .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?))), + COLLECTIONS_INSCRIPTION_ID_TO_KINDS: Rc::new(RefCell::new(wtx + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?)), SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: sequence_number_to_inscription_entry.clone(), OUTPOINT_TO_ENTRY: outpoint_to_entry.clone(), - BRC20_BALANCES: Rc::new(RefCell::new((wtx.open_table(BRC20_BALANCES)?))), - BRC20_TOKEN: Rc::new(RefCell::new((wtx.open_table(BRC20_TOKEN)?))), - BRC20_EVENTS: Rc::new(RefCell::new((wtx.open_table(BRC20_EVENTS)?))), - BRC20_TRANSFERABLELOG: Rc::new(RefCell::new((wtx.open_table(BRC20_TRANSFERABLELOG)?))), - BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new((wtx.open_table(BRC20_INSCRIBE_TRANSFER)?))), + BRC20_BALANCES: Rc::new(RefCell::new(wtx.open_table(BRC20_BALANCES)?)), + BRC20_TOKEN: Rc::new(RefCell::new(wtx.open_table(BRC20_TOKEN)?)), + BRC20_EVENTS: Rc::new(RefCell::new(wtx.open_table(BRC20_EVENTS)?)), + BRC20_TRANSFERABLELOG: Rc::new(RefCell::new(wtx.open_table(BRC20_TRANSFERABLELOG)?)), + BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new(wtx.open_table(BRC20_INSCRIBE_TRANSFER)?)), _marker_a: Default::default(), }; @@ -108,8 +108,8 @@ impl SimulatorServer { sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), sequence_number_to_inscription_entry: sequence_number_to_inscription_entry, OUTPOINT_TO_SAT_RANGES: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), - sat_to_satpoint: Rc::new(RefCell::new((sat_to_point))), - statistic_to_count: Rc::new(RefCell::new((statis_to_count))), + sat_to_satpoint: Rc::new(RefCell::new(sat_to_point)), + statistic_to_count: Rc::new(RefCell::new(statis_to_count)), _marker_a: Default::default(), client: Some(self.client.clone()), context: ctx, diff --git a/src/index/updater.rs b/src/index/updater.rs index 22bb58a87e..f9fe147e74 100644 --- a/src/index/updater.rs +++ b/src/index/updater.rs @@ -13,7 +13,6 @@ use crate::okx::lru::SimpleLru; mod rune_updater; pub mod pending_updater; -mod pending2; #[derive(Clone)] diff --git a/src/okx/protocol/brc20/msg_executor.rs b/src/okx/protocol/brc20/msg_executor.rs index dfaa5be6bd..3575341aaf 100644 --- a/src/okx/protocol/brc20/msg_executor.rs +++ b/src/okx/protocol/brc20/msg_executor.rs @@ -5,7 +5,6 @@ use super::{ use crate::okx::datastore::brc20::{Brc20Reader, Brc20ReaderWriter}; use crate::okx::datastore::ord::OrdReader; -use crate::okx::protocol::context::Context; use crate::{ okx::{ datastore::brc20::{ From f826194d5c833f69b8cfa7f3dab512b74cceea8c Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sun, 14 Jan 2024 10:12:21 +0800 Subject: [PATCH 32/66] add --- src/index/simulator/processor.rs | 182 +++++++++++++++---------------- src/index/simulator/simulate.rs | 16 ++- src/okx/protocol/simulate.rs | 4 +- 3 files changed, 103 insertions(+), 99 deletions(-) diff --git a/src/index/simulator/processor.rs b/src/index/simulator/processor.rs index 8c094e3f2d..e9d165d664 100644 --- a/src/index/simulator/processor.rs +++ b/src/index/simulator/processor.rs @@ -18,6 +18,7 @@ use crate::index::{HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, Inscrip use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::protocol::context::Context; use crate::okx::protocol::simulate::SimulateContext; +use crate::okx::protocol::trace::TraceNode; #[derive(Clone)] pub struct IndexWrapper { @@ -55,7 +56,7 @@ pub struct StorageProcessor<'a, 'db, 'tx> { pub(super) sequence_number_to_satpoint: Rc>>, pub(super) sequence_number_to_inscription_entry: Rc>>, - pub OUTPOINT_TO_SAT_RANGES: Rc>>, + pub outpoint_to_sat_ranges: Rc>>, pub sat_to_satpoint: Rc>>, pub statistic_to_count: Rc>>, @@ -63,6 +64,7 @@ pub struct StorageProcessor<'a, 'db, 'tx> { pub client: Option>>>, + pub traces: Rc>>, pub context: SimulateContext<'a, 'db, 'tx>, } @@ -75,7 +77,6 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { pub(crate) fn create_context(&self) -> crate::Result { todo!() } - pub fn get_transaction(&self, tx_id: &Txid) -> crate::Result> { let client = self.client.as_ref().unwrap(); let ret = client.get_transaction_by_tx_id(tx_id.clone())?; @@ -105,17 +106,46 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { } Ok(v) } - pub(crate) fn outpoint_to_sat_ranges_insert(&self, value: &OutPointValue, data: &[u8]) -> crate::Result<()> { - let mut table = self.OUTPOINT_TO_SAT_RANGES.borrow_mut(); - table.insert(value, data)?; - Ok(()) + pub(crate) fn id_to_sequence_number_get(&self, x: &InscriptionIdValue) -> crate::Result> { + let table = self.id_to_sequence_number.borrow(); + let v = table.get(x)?; + if let Some(v) = v { + return Ok(Some(v.value())); + } + let ret = self.internal.use_internal_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |table| { + let value = table.get(x).map_err(|e| { + anyhow!("id_to_sequence_number_get error:{}",e) + })?; + if let Some(value) = value { + return Ok(Some(value.value())); + } + return Ok(None); + })?; + if let Some(ret) = ret { + return Ok(Some(ret)); + } + Ok(None) } - pub(crate) fn outpoint_to_sat_ranges_remove(&self, k: &OutPointValue) -> crate::Result>> { - let mut table = self.OUTPOINT_TO_SAT_RANGES.borrow_mut(); - let ret: Vec = table.remove(k)?.map(|ranges| ranges.value().to_vec()).unwrap_or_default(); - return Ok(Some(ret)); + pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { + let table = self.sequence_number_to_inscription_entry.borrow(); + let value = table.get(initial_inscription_sequence_number)?; + if let Some(v) = value { + return Ok(Some(v.value())); + } + let ret = self.internal.use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| { + let ret = table.get(initial_inscription_sequence_number).map_err(move |e| { + anyhow!("sequence_number_to_entry_get error:{}",e) + })?; + if let Some(ret) = ret { + return Ok(Some(ret.value())); + } + return Ok(None); + })?; + if let Some(ret) = ret { + return Ok(Some(ret)); + } + Ok(None) } - pub fn get_lost_sats(&self) -> crate::Result { let table = self.statistic_to_count.borrow(); let ret = table @@ -184,11 +214,6 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { }))?; Ok(ret) } - pub fn sat_to_satpoint_insert(&self, key: &u64, value: &SatPointValue) -> crate::Result<()> { - let mut table = self.sat_to_satpoint.borrow_mut(); - table.insert(key, value)?; - Ok(()) - } pub fn get_txout_by_outpoint(&self, x: &OutPoint) -> crate::Result> { let bindind = self.outpoint_to_entry.borrow(); let ret = get_txout_by_outpoint(bindind.deref(), x)?; @@ -200,11 +225,36 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { })?; Ok(ret) } - pub(crate) fn satpoint_to_sequence_number_remove_all(&self, v: &SatPointValue) -> crate::Result<()> { - let mut table = self.satpoint_to_sequence_number.borrow_mut(); - table - .remove_all(v)?; - Ok(()) + pub fn inscriptions_on_output(&self, prev_output: &OutPoint) -> crate::Result> { + let table = self.satpoint_to_sequence_number.borrow(); + let satpoint_to_sequence_number = table.deref(); + + let table = self.sequence_number_to_inscription_entry.borrow(); + let sequence_number_to_entry = table.deref(); + let ret = Index::inscriptions_on_output( + satpoint_to_sequence_number, + sequence_number_to_entry, + prev_output.clone())?; + + let mut set: HashSet<(SatPoint, InscriptionId)> = ret.into_iter() + .map(|(k, v)| { + (k, v) + }).collect(); + + let rtx = self.internal.internal.begin_read()?; + let satpoint_to_sequence_number = rtx.0.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; + let sequence_number_to_entry = rtx.0.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; + let ret = Index::inscriptions_on_output( + &satpoint_to_sequence_number, + &sequence_number_to_entry, + prev_output.clone())?; + for node in ret { + if set.contains(&node) { + continue; + } + set.insert(node); + } + Ok(set.into_iter().collect()) } pub(crate) fn home_inscriptions_len(&self) -> u64 { let table = self.home_inscriptions.borrow(); @@ -326,82 +376,30 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // }); // Ok(()) } - pub fn inscriptions_on_output(&self, prev_output: &OutPoint) -> crate::Result> { - let table = self.satpoint_to_sequence_number.borrow(); - let satpoint_to_sequence_number = table.deref(); - - let table = self.sequence_number_to_inscription_entry.borrow(); - let sequence_number_to_entry = table.deref(); - let ret = Index::inscriptions_on_output( - satpoint_to_sequence_number, - sequence_number_to_entry, - prev_output.clone())?; - - let mut set: HashSet<(SatPoint, InscriptionId)> = ret.into_iter() - .map(|(k, v)| { - (k, v) - }).collect(); - - let rtx = self.internal.internal.begin_read()?; - let satpoint_to_sequence_number = rtx.0.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; - let sequence_number_to_entry = rtx.0.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; - let ret = Index::inscriptions_on_output( - &satpoint_to_sequence_number, - &sequence_number_to_entry, - prev_output.clone())?; - for node in ret { - if set.contains(&node) { - continue; - } - set.insert(node); - } - Ok(set.into_iter().collect()) - } - pub(crate) fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { let mut table = self.transaction_id_to_transaction.borrow_mut(); table.insert(tx_id, value)?; Ok(()) } - - pub(crate) fn id_to_sequence_number_get(&self, x: &InscriptionIdValue) -> crate::Result> { - let table = self.id_to_sequence_number.borrow(); - let v = table.get(x)?; - if let Some(v) = v { - return Ok(Some(v.value())); - } - let ret = self.internal.use_internal_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |table| { - let value = table.get(x).map_err(|e| { - anyhow!("id_to_sequence_number_get error:{}",e) - })?; - if let Some(value) = value { - return Ok(Some(value.value())); - } - return Ok(None); - })?; - if let Some(ret) = ret { - return Ok(Some(ret)); - } - Ok(None) + pub(crate) fn outpoint_to_sat_ranges_insert(&self, value: &OutPointValue, data: &[u8]) -> crate::Result<()> { + let mut table = self.outpoint_to_sat_ranges.borrow_mut(); + table.insert(value, data)?; + Ok(()) } - pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { - let table = self.sequence_number_to_inscription_entry.borrow(); - let value = table.get(initial_inscription_sequence_number)?; - if let Some(v) = value { - return Ok(Some(v.value())); - } - let ret = self.internal.use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| { - let ret = table.get(initial_inscription_sequence_number).map_err(move |e| { - anyhow!("sequence_number_to_entry_get error:{}",e) - })?; - if let Some(ret) = ret { - return Ok(Some(ret.value())); - } - return Ok(None); - })?; - if let Some(ret) = ret { - return Ok(Some(ret)); - } - Ok(None) + pub(crate) fn outpoint_to_sat_ranges_remove(&self, k: &OutPointValue) -> crate::Result>> { + let mut table = self.outpoint_to_sat_ranges.borrow_mut(); + let ret: Vec = table.remove(k)?.map(|ranges| ranges.value().to_vec()).unwrap_or_default(); + return Ok(Some(ret)); + } + pub(crate) fn satpoint_to_sequence_number_remove_all(&self, v: &SatPointValue) -> crate::Result<()> { + let mut table = self.satpoint_to_sequence_number.borrow_mut(); + table + .remove_all(v)?; + Ok(()) + } + pub fn sat_to_satpoint_insert(&self, key: &u64, value: &SatPointValue) -> crate::Result<()> { + let mut table = self.sat_to_satpoint.borrow_mut(); + table.insert(key, value)?; + Ok(()) } } \ No newline at end of file diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 8015914a1b..3cad5e50c0 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -14,7 +14,7 @@ use indexer_sdk::storage::db::memory::MemoryDB; use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; use log::{error, info}; -use redb::{ WriteTransaction}; +use redb::{WriteTransaction}; use crate::{Index, Options, Sat, SatPoint}; use crate::height::Height; use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION}; @@ -26,6 +26,7 @@ use crate::okx::datastore::ord::InscriptionOp; use crate::okx::lru::SimpleLru; use crate::okx::protocol::{ProtocolConfig, ProtocolManager}; use crate::okx::protocol::simulate::SimulateContext; +use crate::okx::protocol::trace::TraceNode; pub struct Simulator<'a, 'db, 'tx> { pub internal_index: IndexWrapper, @@ -45,7 +46,8 @@ pub struct SimulatorServer { impl SimulatorServer { pub fn execute_tx(&self, tx: &Transaction, commit: bool) -> crate::Result<(), SimulateError> { let mut wtx = self.simulate_index.begin_write()?; - self.simulate_tx(tx, &wtx)?; + let traces = Rc::new(RefCell::new(vec![])); + self.simulate_tx(tx, &wtx, traces)?; if commit { wtx.commit()?; } @@ -53,7 +55,7 @@ impl SimulatorServer { Ok(()) } - fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction) -> crate::Result<(), SimulateError> { + fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction, traces: Rc>>) -> crate::Result<(), SimulateError> { let height = self.internal_index.internal.block_count()?; let block = self.internal_index.internal.get_block_by_height(height)?.unwrap(); let home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS).unwrap(); @@ -91,6 +93,7 @@ impl SimulatorServer { BRC20_EVENTS: Rc::new(RefCell::new(wtx.open_table(BRC20_EVENTS)?)), BRC20_TRANSFERABLELOG: Rc::new(RefCell::new(wtx.open_table(BRC20_TRANSFERABLELOG)?)), BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new(wtx.open_table(BRC20_INSCRIBE_TRANSFER)?)), + traces: traces.clone(), _marker_a: Default::default(), }; @@ -100,18 +103,19 @@ impl SimulatorServer { home_inscriptions: Rc::new(RefCell::new(home_inscriptions)), id_to_sequence_number: Rc::new(RefCell::new(inscription_id_to_sequence_number)), inscription_number_to_sequence_number: Rc::new(RefCell::new(inscription_number_to_sequence_number)), - outpoint_to_entry: outpoint_to_entry, + outpoint_to_entry, transaction_id_to_transaction: Rc::new(RefCell::new(transaction_id_to_transaction)), sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), - sequence_number_to_inscription_entry: sequence_number_to_inscription_entry, - OUTPOINT_TO_SAT_RANGES: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), + sequence_number_to_inscription_entry, + outpoint_to_sat_ranges: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), sat_to_satpoint: Rc::new(RefCell::new(sat_to_point)), statistic_to_count: Rc::new(RefCell::new(statis_to_count)), _marker_a: Default::default(), client: Some(self.client.clone()), + traces: traces.clone(), context: ctx, }; diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index 2554c03d9e..b2c1ab760e 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -797,6 +797,7 @@ use crate::okx::datastore::ord::collections::CollectionKind; use crate::okx::datastore::ord::redb::table::{get_collection_inscription_id, get_collections_of_inscription, get_inscription_number_by_sequence_number, get_transaction_operations, get_txout_by_outpoint, save_transaction_operations, set_inscription_attributes, set_inscription_by_collection_key}; use crate::okx::datastore::ScriptKey; use crate::okx::protocol::ContextTrait; +use crate::okx::protocol::trace::TraceNode; #[derive(Clone)] pub struct SimulateContext<'a, 'db, 'txn> { @@ -819,6 +820,7 @@ pub struct SimulateContext<'a, 'db, 'txn> { pub(crate) BRC20_EVENTS: Rc>>, pub(crate) BRC20_TRANSFERABLELOG: Rc>>, pub(crate) BRC20_INSCRIBE_TRANSFER: Rc>>, + pub traces: Rc>>, pub _marker_a: PhantomData<&'a ()>, } @@ -990,7 +992,7 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { let mut binding = self.BRC20_TOKEN.borrow_mut(); - let mut table = binding.deref_mut(); + let table = binding.deref_mut(); insert_token_info(table, tick, new_info) } From 34a5e89ca9da546a53db511722474111a1585a47 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sun, 14 Jan 2024 10:28:03 +0800 Subject: [PATCH 33/66] add --- src/index/simulator/simulate.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 3cad5e50c0..4888228906 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -15,6 +15,7 @@ use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; use log::{error, info}; use redb::{WriteTransaction}; +use tempfile::NamedTempFile; use crate::{Index, Options, Sat, SatPoint}; use crate::height::Height; use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION}; @@ -177,8 +178,17 @@ impl SimulatorServer { Ok(()) } - pub fn new(internal_index: Arc, simulate_index: Arc, client: DirectClient>>) -> Self { - Self { tx_out_cache: Rc::new(RefCell::new(SimpleLru::new(500))), internal_index: IndexWrapper::new(internal_index), simulate_index, client } + pub fn new(internal_index: Arc, simualte_ops: Option, client: DirectClient>>) -> crate::Result { + let simulate_index = if let Some(ops) = simualte_ops { + Index::open(&ops)? + } else { + let mut origin_ops = internal_index.options.clone(); + let dbfile = NamedTempFile::new().unwrap(); + origin_ops.index = Some(dbfile.path().to_path_buf()); + Index::open(&origin_ops)? + }; + let simulate_index = Arc::new(simulate_index); + Ok(Self { tx_out_cache: Rc::new(RefCell::new(SimpleLru::new(500))), internal_index: IndexWrapper::new(internal_index), simulate_index, client }) } } @@ -428,9 +438,8 @@ mod tests { let internal = Arc::new(Index::open(&opt).unwrap()); let mut opt2 = opt.clone(); opt2.index = Some(PathBuf::from("./simulate")); - let simulate_index = Arc::new(Index::open(&opt2).unwrap()); let client = new_client_for_test("http://localhost:18443".to_string(), "bitcoinrpc".to_string(), "bitcoinrpc".to_string()); - let simulate_server = SimulatorServer::new(internal.clone(), simulate_index.clone(), client.clone()); + let simulate_server = SimulatorServer::new(internal.clone(), Some(opt2), client.clone()).unwrap(); let client = client.clone().get_btc_client(); let tx = client.get_raw_transaction(&Txid::from_str("f2ecd8708afbb0056709333a60882536c7d070633e1ee7cf80d83ad35e1f8403").unwrap(), None).unwrap(); From 483906a283ce3247090e61c99a999cb76d0ef730 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sun, 14 Jan 2024 10:30:46 +0800 Subject: [PATCH 34/66] add --- src/index/simulator/processor.rs | 39 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/index/simulator/processor.rs b/src/index/simulator/processor.rs index e9d165d664..f3b8ea8c02 100644 --- a/src/index/simulator/processor.rs +++ b/src/index/simulator/processor.rs @@ -39,6 +39,7 @@ impl IndexWrapper { } } +// could be trait #[derive(Clone)] pub struct StorageProcessor<'a, 'db, 'tx> { pub internal: IndexWrapper, @@ -74,7 +75,7 @@ unsafe impl<'a, 'db, 'tx> Sync for StorageProcessor<'a, 'db, 'tx> {} impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { - pub(crate) fn create_context(&self) -> crate::Result { + pub fn create_context(&self) -> crate::Result { todo!() } pub fn get_transaction(&self, tx_id: &Txid) -> crate::Result> { @@ -82,10 +83,10 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { let ret = client.get_transaction_by_tx_id(tx_id.clone())?; Ok(ret) } - pub(crate) fn create_simulate_context(&self) -> crate::Result> { + pub fn create_simulate_context(&self) -> crate::Result> { Ok(self.context.clone()) } - pub(crate) fn next_sequence_number(&self) -> crate::Result { + pub fn next_sequence_number(&self) -> crate::Result { let table = self.sequence_number_to_inscription_entry.borrow(); let ret: u32 = table .iter()? @@ -106,7 +107,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { } Ok(v) } - pub(crate) fn id_to_sequence_number_get(&self, x: &InscriptionIdValue) -> crate::Result> { + pub fn id_to_sequence_number_get(&self, x: &InscriptionIdValue) -> crate::Result> { let table = self.id_to_sequence_number.borrow(); let v = table.get(x)?; if let Some(v) = v { @@ -256,7 +257,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { } Ok(set.into_iter().collect()) } - pub(crate) fn home_inscriptions_len(&self) -> u64 { + pub fn home_inscriptions_len(&self) -> u64 { let table = self.home_inscriptions.borrow(); let sim = table.len().unwrap(); let ret = self.internal.use_internal_table(HOME_INSCRIPTIONS, |table| { @@ -265,7 +266,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { }).unwrap(); return sim + ret; } - pub(crate) fn sequence_number_to_satpoint_insert(&self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { + pub fn sequence_number_to_satpoint_insert(&self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { let mut table = self.sequence_number_to_satpoint.borrow_mut(); table.insert(sequence_number, sat_point)?; @@ -276,7 +277,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // }); Ok(()) } - pub(crate) fn satpoint_to_sequence_number_insert(&self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { + pub fn satpoint_to_sequence_number_insert(&self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { let mut table = self.sequence_number_to_satpoint.borrow_mut(); table.insert(sequence, sat_point)?; @@ -287,7 +288,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // }); Ok(()) } - pub(crate) fn home_inscriptions_pop_first(&self) -> crate::Result<()> { + pub fn home_inscriptions_pop_first(&self) -> crate::Result<()> { let mut table = self.home_inscriptions.borrow_mut(); table.pop_first()?; @@ -296,7 +297,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // }); Ok(()) } - pub(crate) fn home_inscriptions_insert(&self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { + pub fn home_inscriptions_insert(&self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { // let key = u32::as_bytes(sequence_number).to_vec(); // let value = InscriptionIdValue::as_bytes(&value).to_vec(); // self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { @@ -309,7 +310,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { .insert(sequence_number, value)?; Ok(()) } - pub(crate) fn id_to_sequence_number_insert(&self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { + pub fn id_to_sequence_number_insert(&self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { // let key = rmp_serde::to_vec(value).unwrap(); // let value = sequence.to_le_bytes().as_slice(); // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |v| { @@ -321,7 +322,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { .insert(value, sequence_number)?; Ok(()) } - pub(crate) fn sequence_number_to_children_insert(&self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { + pub fn sequence_number_to_children_insert(&self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { // let key = sequence.to_le_bytes().as_slice(); // let value = rmp_serde::to_vec(value).unwrap(); // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_CHILDREN, |v| { @@ -332,7 +333,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { table.insert(parent_sequence_number, sequence_number)?; Ok(()) } - pub(crate) fn sequence_number_to_entry_insert(&self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { + pub fn sequence_number_to_entry_insert(&self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { // let key = sequence.to_le_bytes().as_slice(); // let value = rmp_serde::to_vec(value).unwrap(); // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |v| { @@ -343,7 +344,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { table.insert(sequence, value)?; Ok(()) } - pub(crate) fn sat_to_sequence_number_insert(&self, n: &u64, sequence_number: &u32) -> crate::Result<()> { + pub fn sat_to_sequence_number_insert(&self, n: &u64, sequence_number: &u32) -> crate::Result<()> { // let key = n.to_le_bytes().as_slice(); // let value = sequence.to_le_bytes().as_slice(); // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { @@ -354,7 +355,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { table.insert(n, sequence_number)?; Ok(()) } - pub(crate) fn inscription_number_to_sequence_number_insert(&self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { + pub fn inscription_number_to_sequence_number_insert(&self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { // let key = inscription_number.to_le_bytes().as_slice(); // let value = sequence_number.to_le_bytes().as_slice(); // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, |v| { @@ -365,7 +366,7 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { table.insert(inscription_number, sequence_number)?; Ok(()) } - pub(crate) fn outpoint_to_entry_insert(&self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { + pub fn outpoint_to_entry_insert(&self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { let mut table = self.outpoint_to_entry.borrow_mut(); table.insert(value, entry)?; Ok(()) @@ -376,22 +377,22 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { // }); // Ok(()) } - pub(crate) fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { + pub fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { let mut table = self.transaction_id_to_transaction.borrow_mut(); table.insert(tx_id, value)?; Ok(()) } - pub(crate) fn outpoint_to_sat_ranges_insert(&self, value: &OutPointValue, data: &[u8]) -> crate::Result<()> { + pub fn outpoint_to_sat_ranges_insert(&self, value: &OutPointValue, data: &[u8]) -> crate::Result<()> { let mut table = self.outpoint_to_sat_ranges.borrow_mut(); table.insert(value, data)?; Ok(()) } - pub(crate) fn outpoint_to_sat_ranges_remove(&self, k: &OutPointValue) -> crate::Result>> { + pub fn outpoint_to_sat_ranges_remove(&self, k: &OutPointValue) -> crate::Result>> { let mut table = self.outpoint_to_sat_ranges.borrow_mut(); let ret: Vec = table.remove(k)?.map(|ranges| ranges.value().to_vec()).unwrap_or_default(); return Ok(Some(ret)); } - pub(crate) fn satpoint_to_sequence_number_remove_all(&self, v: &SatPointValue) -> crate::Result<()> { + pub fn satpoint_to_sequence_number_remove_all(&self, v: &SatPointValue) -> crate::Result<()> { let mut table = self.satpoint_to_sequence_number.borrow_mut(); table .remove_all(v)?; From 35b7bcca88cab19897878251f542910253bf44fb Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sun, 14 Jan 2024 17:03:21 +0800 Subject: [PATCH 35/66] add --- src/index/simulator/processor.rs | 5 +---- src/index/simulator/simulate.rs | 23 +++++++++++++++++------ src/okx/protocol/simulate.rs | 5 ++++- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/index/simulator/processor.rs b/src/index/simulator/processor.rs index f3b8ea8c02..723a5e69df 100644 --- a/src/index/simulator/processor.rs +++ b/src/index/simulator/processor.rs @@ -75,15 +75,12 @@ unsafe impl<'a, 'db, 'tx> Sync for StorageProcessor<'a, 'db, 'tx> {} impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { - pub fn create_context(&self) -> crate::Result { - todo!() - } pub fn get_transaction(&self, tx_id: &Txid) -> crate::Result> { let client = self.client.as_ref().unwrap(); let ret = client.get_transaction_by_tx_id(tx_id.clone())?; Ok(ret) } - pub fn create_simulate_context(&self) -> crate::Result> { + pub fn create_context(&self) -> crate::Result> { Ok(self.context.clone()) } pub fn next_sequence_number(&self) -> crate::Result { diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 4888228906..19a38d8f92 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -23,6 +23,7 @@ use crate::index::entry::Entry; use crate::index::simulator::error::SimulateError; use crate::index::simulator::processor::{IndexWrapper, StorageProcessor}; use crate::index::updater::pending_updater::PendingUpdater; +use crate::okx::datastore::brc20::{Brc20Reader, Receipt}; use crate::okx::datastore::ord::InscriptionOp; use crate::okx::lru::SimpleLru; use crate::okx::protocol::{ProtocolConfig, ProtocolManager}; @@ -45,18 +46,19 @@ pub struct SimulatorServer { } impl SimulatorServer { - pub fn execute_tx(&self, tx: &Transaction, commit: bool) -> crate::Result<(), SimulateError> { + pub fn execute_tx(&self, tx: &Transaction, commit: bool) -> crate::Result, SimulateError> { let mut wtx = self.simulate_index.begin_write()?; let traces = Rc::new(RefCell::new(vec![])); - self.simulate_tx(tx, &wtx, traces)?; + let ret = self.simulate_tx(tx, &wtx, traces)?; if commit { wtx.commit()?; } - Ok(()) + Ok(ret) } - fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction, traces: Rc>>) -> crate::Result<(), SimulateError> { + fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction, traces: Rc>>) -> crate::Result, SimulateError> { + let brc20_receipts = Rc::new(RefCell::new(vec![])); let height = self.internal_index.internal.block_count()?; let block = self.internal_index.internal.get_block_by_height(height)?.unwrap(); let home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS).unwrap(); @@ -95,9 +97,16 @@ impl SimulatorServer { BRC20_TRANSFERABLELOG: Rc::new(RefCell::new(wtx.open_table(BRC20_TRANSFERABLELOG)?)), BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new(wtx.open_table(BRC20_INSCRIBE_TRANSFER)?)), traces: traces.clone(), + brc20_receipts: brc20_receipts.clone(), _marker_a: Default::default(), }; + let db_receipts = ctx.get_transaction_receipts(&tx.txid())?; + if db_receipts.len() > 0 { + info!("tx:{:?} already simulated",tx.txid()); + return Ok(db_receipts); + } + let processor = StorageProcessor { internal: self.internal_index.clone(), // wtx: &mut wtx, @@ -121,7 +130,9 @@ impl SimulatorServer { }; self.loop_simulate_tx(&processor, &tx)?; - Ok(()) + let ret = brc20_receipts.borrow(); + let ret = ret.deref().clone(); + Ok(ret) } pub fn loop_simulate_tx(&self, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(), SimulateError> { let tx_id = tx.txid(); @@ -351,7 +362,7 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { } inscription_updater.flush_cache()?; - let mut context = processor.create_simulate_context()?; + let mut context = processor.create_context()?; let config = ProtocolConfig::new_with_options(&self.internal_index.internal.options); ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index b2c1ab760e..00bbd3f7f3 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -821,6 +821,7 @@ pub struct SimulateContext<'a, 'db, 'txn> { pub(crate) BRC20_TRANSFERABLELOG: Rc>>, pub(crate) BRC20_INSCRIBE_TRANSFER: Rc>>, pub traces: Rc>>, + pub brc20_receipts:Rc>>, pub _marker_a: PhantomData<&'a ()>, } @@ -998,7 +999,7 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { let mut binding = self.BRC20_TOKEN.borrow_mut(); - let mut table = binding.deref_mut(); + let table = binding.deref_mut(); let mut info = get_token_info(table, tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); info.minted = minted_amt; info.latest_mint_number = minted_block_number; @@ -1006,6 +1007,8 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { } fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { + let mut receipts=self.brc20_receipts.borrow_mut(); + receipts.extend_from_slice(receipt); let mut table = self.BRC20_EVENTS.borrow_mut(); save_transaction_receipts(&mut table, txid, receipt) } From 93650c6c959d4fb823bdc2874f7dfeacf8c25598 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sun, 14 Jan 2024 23:09:33 +0800 Subject: [PATCH 36/66] add --- src/index/simulator/error.rs | 7 +- src/index/simulator/simulate.rs | 132 ++++++++++++++++++++++++++++++-- src/options.rs | 30 ++++++++ 3 files changed, 162 insertions(+), 7 deletions(-) diff --git a/src/index/simulator/error.rs b/src/index/simulator/error.rs index a472df24a6..172e0befb0 100644 --- a/src/index/simulator/error.rs +++ b/src/index/simulator/error.rs @@ -1,4 +1,5 @@ use bitcoin::Txid; +use indexer_sdk::error::IndexerError; use redb::{CommitError, TableError}; #[derive(Debug, thiserror::Error)] @@ -13,5 +14,9 @@ pub enum SimulateError { CommitError(#[from]CommitError), #[error("table failed: {0}")] - TableError(#[from]TableError) + TableError(#[from]TableError), + + + #[error("indexer failed: {0}")] + IndexerError(#[from]IndexerError) } \ No newline at end of file diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 19a38d8f92..f5a503bac2 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -6,16 +6,24 @@ use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::thread; use anyhow::anyhow; use bitcoin::{OutPoint, Transaction, Txid, TxOut}; use indexer_sdk::client::drect::DirectClient; +use indexer_sdk::client::event::ClientEvent; use indexer_sdk::client::SyncClient; +use indexer_sdk::configuration::base::{IndexerConfiguration, NetConfiguration, ZMQConfiguration}; +use indexer_sdk::factory::common::async_create_and_start_processor; use indexer_sdk::storage::db::memory::MemoryDB; use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; +use indexer_sdk::wait_exit_signal; use log::{error, info}; use redb::{WriteTransaction}; use tempfile::NamedTempFile; +use tokio::runtime::Runtime; +use tokio::sync::watch; +use tokio::task::JoinHandle; use crate::{Index, Options, Sat, SatPoint}; use crate::height::Height; use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION}; @@ -38,6 +46,7 @@ pub struct Simulator<'a, 'db, 'tx> { _marker_tx: PhantomData<&'tx ()>, } +#[derive(Clone)] pub struct SimulatorServer { tx_out_cache: Rc>>, pub internal_index: IndexWrapper, @@ -45,7 +54,57 @@ pub struct SimulatorServer { pub client: DirectClient>>, } +unsafe impl Send for SimulatorServer {} + +unsafe impl Sync for SimulatorServer {} + impl SimulatorServer { + pub async fn start(&self, exit: watch::Receiver<()>) -> JoinHandle<()> { + let internal = self.clone(); + tokio::spawn(async move { + internal.on_start(exit).await; + }) + } + async fn on_start(self, mut exit: watch::Receiver<()>) { + let client = self.client.clone(); + loop { + tokio::select! { + event=self.get_client_event()=>{ + match event{ + Ok(event) => { + if let Err(e)= self.handle_event(&event).await{ + log::error!("handle event error: {:?}", e); + } + } + Err(e) => { + log::error!("receive event error: {:?}", e); + break; + } + } + }, + _ = exit.changed() => { + info!("simulator receive exit signal, exit."); + break; + } + } + } + } + async fn handle_event(&self, event: &ClientEvent) -> crate::Result<()> { + info!("sim receive event:{:?}", event); + match event { + ClientEvent::Transaction(tx) => { + self.execute_tx(tx, true)?; + } + ClientEvent::GetHeight => {} + ClientEvent::TxDroped(_) => {} + ClientEvent::TxConfirmed(_) => {} + } + Ok(()) + } + async fn get_client_event(&self) -> crate::Result { + let ret = self.client.block_get_event()?; + Ok(ret) + } pub fn execute_tx(&self, tx: &Transaction, commit: bool) -> crate::Result, SimulateError> { let mut wtx = self.simulate_index.begin_write()?; let traces = Rc::new(RefCell::new(vec![])); @@ -189,11 +248,11 @@ impl SimulatorServer { Ok(()) } - pub fn new(internal_index: Arc, simualte_ops: Option, client: DirectClient>>) -> crate::Result { - let simulate_index = if let Some(ops) = simualte_ops { + pub fn new(ops: Options, internal_index: Arc, simulate_ops: Option, client: DirectClient>>) -> crate::Result { + let simulate_index = if let Some(ops) = simulate_ops { Index::open(&ops)? } else { - let mut origin_ops = internal_index.options.clone(); + let mut origin_ops = ops.clone(); let dbfile = NamedTempFile::new().unwrap(); origin_ops.index = Some(dbfile.path().to_path_buf()); Index::open(&origin_ops)? @@ -431,14 +490,69 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { } } +pub fn start_simulator(ops: Options, internal: Arc) -> Option { + if !ops.simulate_enable { + return None; + } + let rt = Runtime::new().unwrap(); + let zmq_url = ops.simulate_zmq_url.clone().unwrap(); + let sim_rpc = ops.simulate_bitcoin_rpc_url.clone().unwrap(); + let sim_user = ops.simulate_bitcoin_rpc_user.clone().unwrap(); + let sim_pass = ops.simulate_bitcoin_rpc_pass.clone().unwrap(); + + let config = IndexerConfiguration { + mq: ZMQConfiguration { zmq_url: zmq_url, zmq_topic: vec!["sequence".to_string(), "rawblock".to_string()] }, + net: NetConfiguration { + url: sim_rpc, + username: sim_user, + password: sim_pass, + }, + ..Default::default() + }; + let (tx, rx) = watch::channel(()); + let (server, handlers) = rt.block_on(async { + let ret = async_create_and_start_processor(rx.clone(), config).await; + let mut handlers = ret.1; + let mut sim_ops = ops.clone(); + sim_ops.index = ops.simulate_index.clone(); + let server = SimulatorServer::new(ops.clone(), internal.clone(), Some(sim_ops), ret.0).unwrap(); + handlers.push(server.start(rx.clone()).await); + (server.clone(), handlers) + }); + + thread::spawn(move || { + rt.block_on(async { + wait_exit_signal().await.unwrap(); + tx.send(()).unwrap(); + for h in handlers { + h.await.unwrap(); + } + }); + }); + Some(server) +} + #[cfg(test)] mod tests { use std::str::FromStr; + use std::thread::sleep; use bitcoincore_rpc::RpcApi; use indexer_sdk::factory::common::new_client_for_test; use log::LevelFilter; use super::*; + #[test] + pub fn test_start() { + env_logger::builder() + .filter_level(LevelFilter::Debug) + .format_target(false) + .init(); + let opt = create_options(); + let internal = Arc::new(Index::open(&opt).unwrap()); + let server = start_simulator(opt, internal.clone()); + sleep(std::time::Duration::from_secs(5)) + } + #[test] pub fn test_simulate_tx() { env_logger::builder() @@ -448,12 +562,12 @@ mod tests { let opt = create_options(); let internal = Arc::new(Index::open(&opt).unwrap()); let mut opt2 = opt.clone(); - opt2.index = Some(PathBuf::from("./simulate")); + opt2.index=opt.simulate_index.clone(); let client = new_client_for_test("http://localhost:18443".to_string(), "bitcoinrpc".to_string(), "bitcoinrpc".to_string()); - let simulate_server = SimulatorServer::new(internal.clone(), Some(opt2), client.clone()).unwrap(); + let simulate_server = SimulatorServer::new(internal.options.clone(), internal.clone(), Some(opt2), client.clone()).unwrap(); let client = client.clone().get_btc_client(); - let tx = client.get_raw_transaction(&Txid::from_str("f2ecd8708afbb0056709333a60882536c7d070633e1ee7cf80d83ad35e1f8403").unwrap(), None).unwrap(); + let tx = client.get_raw_transaction(&Txid::from_str("f9028dbd87d723399181d9bdb80a36e991b56405dfae2ccb6ee033d249b5f724").unwrap(), None).unwrap(); println!("{:?}", tx); simulate_server.execute_tx(&tx, true).unwrap(); } @@ -487,6 +601,12 @@ mod tests { enable_index_bitmap: true, enable_index_brc20: true, first_brc20_height: Some(0), + simulate_enable: true, + simulate_zmq_url: Some("tcp://0.0.0.0:28332".to_string()), + simulate_bitcoin_rpc_url: Some("http://localhost:18443".to_string()), + simulate_bitcoin_rpc_pass: Some("bitcoinrpc".to_string()), + simulate_bitcoin_rpc_user: Some("bitcoinrpc".to_string()), + simulate_index: Some("./simulate".to_string().into()), }; opt } diff --git a/src/options.rs b/src/options.rs index bffdac8cd1..aee2aed985 100644 --- a/src/options.rs +++ b/src/options.rs @@ -89,6 +89,36 @@ pub struct Options { help = "Don't look for BRC20 messages below ." )] pub(crate) first_brc20_height: Option, + + + #[arg( + long, + default_value = "false", + help = "Set lru cache to . By default 10000000" + )] + pub(crate) simulate_enable: bool, + #[arg( + long, + help = "bitcoin zmq url." + )] + pub(crate) simulate_zmq_url: Option, + #[arg( + long, + help = "bitcoin rpc url." + )] + pub(crate) simulate_bitcoin_rpc_url: Option, + #[arg( + long, + help = "bitcoin rpc password ." + )] + pub(crate) simulate_bitcoin_rpc_pass: Option, + #[arg( + long, + help = "bitcoin rpc user." + )] + pub(crate) simulate_bitcoin_rpc_user: Option, + #[arg(long, help = "Simulate Use index at .")] + pub(crate) simulate_index: Option, } #[derive(Debug, Clone)] From 3eee8f6ca6324ec4ee6faf0c331eace31d8c300b Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sun, 14 Jan 2024 23:28:03 +0800 Subject: [PATCH 37/66] todo --- src/index/simulator/simulate.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index f5a503bac2..374da8e5bd 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -66,7 +66,6 @@ impl SimulatorServer { }) } async fn on_start(self, mut exit: watch::Receiver<()>) { - let client = self.client.clone(); loop { tokio::select! { event=self.get_client_event()=>{ @@ -248,7 +247,7 @@ impl SimulatorServer { Ok(()) } - pub fn new(ops: Options, internal_index: Arc, simulate_ops: Option, client: DirectClient>>) -> crate::Result { + pub fn new(ops: Options, internal_index: Arc, simulate_ops: Option,client:DirectClient>>) -> crate::Result { let simulate_index = if let Some(ops) = simulate_ops { Index::open(&ops)? } else { @@ -494,6 +493,7 @@ pub fn start_simulator(ops: Options, internal: Arc) -> Option) -> Option Date: Sun, 14 Jan 2024 23:50:14 +0800 Subject: [PATCH 38/66] save --- src/index/simulator/error.rs | 6 +++++- src/index/simulator/simulate.rs | 28 ++++++++-------------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/index/simulator/error.rs b/src/index/simulator/error.rs index 172e0befb0..55c54fe822 100644 --- a/src/index/simulator/error.rs +++ b/src/index/simulator/error.rs @@ -18,5 +18,9 @@ pub enum SimulateError { #[error("indexer failed: {0}")] - IndexerError(#[from]IndexerError) + IndexerError(#[from]IndexerError), + + + #[error("transaction failed: {0}")] + TransactionError(#[from] redb::TransactionError), } \ No newline at end of file diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 374da8e5bd..efcdf4d442 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -19,7 +19,7 @@ use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; use indexer_sdk::wait_exit_signal; use log::{error, info}; -use redb::{WriteTransaction}; +use redb::{Database, WriteTransaction}; use tempfile::NamedTempFile; use tokio::runtime::Runtime; use tokio::sync::watch; @@ -50,7 +50,7 @@ pub struct Simulator<'a, 'db, 'tx> { pub struct SimulatorServer { tx_out_cache: Rc>>, pub internal_index: IndexWrapper, - pub simulate_index: Arc, + pub simulate_index: Arc, pub client: DirectClient>>, } @@ -247,15 +247,8 @@ impl SimulatorServer { Ok(()) } - pub fn new(ops: Options, internal_index: Arc, simulate_ops: Option,client:DirectClient>>) -> crate::Result { - let simulate_index = if let Some(ops) = simulate_ops { - Index::open(&ops)? - } else { - let mut origin_ops = ops.clone(); - let dbfile = NamedTempFile::new().unwrap(); - origin_ops.index = Some(dbfile.path().to_path_buf()); - Index::open(&origin_ops)? - }; + pub fn new>(path:P, internal_index: Arc, client:DirectClient>>) -> crate::Result { + let simulate_index =Database::create(path.into())?; let simulate_index = Arc::new(simulate_index); Ok(Self { tx_out_cache: Rc::new(RefCell::new(SimpleLru::new(500))), internal_index: IndexWrapper::new(internal_index), simulate_index, client }) } @@ -513,9 +506,8 @@ pub fn start_simulator(ops: Options, internal: Arc) -> Option Date: Mon, 15 Jan 2024 00:15:16 +0800 Subject: [PATCH 39/66] ok --- src/index.rs | 7 ++----- src/index/simulator/simulate.rs | 11 ++++------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/index.rs b/src/index.rs index 39260981a3..5c11c0d677 100644 --- a/src/index.rs +++ b/src/index.rs @@ -255,11 +255,8 @@ impl Index { log::info!("Setting DB cache size to {} bytes", db_cache_size); - let durability = if cfg!(test) { - redb::Durability::None - } else { - redb::Durability::Immediate - }; + // TODO: why none? + let durability = redb::Durability::Immediate; let index_runes; let index_sats; diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index efcdf4d442..def4bb1494 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::collections::{HashMap, HashSet, VecDeque}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -247,8 +247,8 @@ impl SimulatorServer { Ok(()) } - pub fn new>(path:P, internal_index: Arc, client:DirectClient>>) -> crate::Result { - let simulate_index =Database::create(path.into())?; + pub fn new(path:impl AsRef, internal_index: Arc, client:DirectClient>>) -> crate::Result { + let simulate_index =Database::create(path)?; let simulate_index = Arc::new(simulate_index); Ok(Self { tx_out_cache: Rc::new(RefCell::new(SimpleLru::new(500))), internal_index: IndexWrapper::new(internal_index), simulate_index, client }) } @@ -506,8 +506,7 @@ pub fn start_simulator(ops: Options, internal: Arc) -> Option Date: Mon, 15 Jan 2024 09:49:31 +0800 Subject: [PATCH 40/66] add trace --- src/index/simulator/processor.rs | 131 +++++++++---------------------- src/index/simulator/simulate.rs | 17 ++-- src/okx/datastore/cache.rs | 3 + src/okx/protocol/simulate.rs | 35 ++++++++- 4 files changed, 82 insertions(+), 104 deletions(-) diff --git a/src/index/simulator/processor.rs b/src/index/simulator/processor.rs index 723a5e69df..970aff0a36 100644 --- a/src/index/simulator/processor.rs +++ b/src/index/simulator/processor.rs @@ -105,11 +105,6 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { Ok(v) } pub fn id_to_sequence_number_get(&self, x: &InscriptionIdValue) -> crate::Result> { - let table = self.id_to_sequence_number.borrow(); - let v = table.get(x)?; - if let Some(v) = v { - return Ok(Some(v.value())); - } let ret = self.internal.use_internal_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |table| { let value = table.get(x).map_err(|e| { anyhow!("id_to_sequence_number_get error:{}",e) @@ -122,14 +117,14 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { if let Some(ret) = ret { return Ok(Some(ret)); } + let table = self.id_to_sequence_number.borrow(); + let v = table.get(x)?; + if let Some(v) = v { + return Ok(Some(v.value())); + } Ok(None) } pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { - let table = self.sequence_number_to_inscription_entry.borrow(); - let value = table.get(initial_inscription_sequence_number)?; - if let Some(v) = value { - return Ok(Some(v.value())); - } let ret = self.internal.use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| { let ret = table.get(initial_inscription_sequence_number).map_err(move |e| { anyhow!("sequence_number_to_entry_get error:{}",e) @@ -142,57 +137,62 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { if let Some(ret) = ret { return Ok(Some(ret)); } + let table = self.sequence_number_to_inscription_entry.borrow(); + let value = table.get(initial_inscription_sequence_number)?; + if let Some(v) = value { + return Ok(Some(v.value())); + } Ok(None) } pub fn get_lost_sats(&self) -> crate::Result { - let table = self.statistic_to_count.borrow(); - let ret = table - .get(&Statistic::LostSats.key())? - .map(|lost_sats| lost_sats.value()) - .unwrap_or(0); + let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ + table + .get(&Statistic::LostSats.key())? + .map(|lost_sats| lost_sats.value()) + .unwrap_or(0) + }))?; if ret == 0 { - let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ - table - .get(&Statistic::LostSats.key())? - .map(|lost_sats| lost_sats.value()) - .unwrap_or(0) - }))?; + let table = self.statistic_to_count.borrow(); + let ret = table + .get(&Statistic::LostSats.key())? + .map(|lost_sats| lost_sats.value()) + .unwrap_or(0); return Ok(ret); } return Ok(ret); } pub fn get_cursed_inscription_count(&self) -> crate::Result { - let table = self.statistic_to_count.borrow(); - let ret = table - .get(&Statistic::CursedInscriptions.key())? - .map(|count| count.value()) - .unwrap_or(0); - if ret != 0 { - return Ok(ret); - } let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ table .get(&Statistic::CursedInscriptions.key())? .map(|count| count.value()) .unwrap_or(0) }))?; - return Ok(ret); - } - pub fn get_blessed_inscription_count(&self) -> crate::Result { + if ret != 0 { + return Ok(ret); + } let table = self.statistic_to_count.borrow(); let ret = table - .get(&Statistic::BlessedInscriptions.key())? + .get(&Statistic::CursedInscriptions.key())? .map(|count| count.value()) .unwrap_or(0); - if ret != 0 { - return Ok(ret); - } + return Ok(ret); + } + pub fn get_blessed_inscription_count(&self) -> crate::Result { let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ table .get(&Statistic::BlessedInscriptions.key())? .map(|count| count.value()) .unwrap_or(0) }))?; + if ret != 0 { + return Ok(ret); + } + let table = self.statistic_to_count.borrow(); + let ret = table + .get(&Statistic::BlessedInscriptions.key())? + .map(|count| count.value()) + .unwrap_or(0); Ok(ret) } pub fn get_unbound_inscriptions(&self) -> crate::Result { @@ -266,99 +266,46 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { pub fn sequence_number_to_satpoint_insert(&self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { let mut table = self.sequence_number_to_satpoint.borrow_mut(); table.insert(sequence_number, sat_point)?; - - // let key = u32::as_bytes(&sequence_number).to_vec(); - // let value = sat_point.to_vec(); - // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_SATPOINT, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); Ok(()) } pub fn satpoint_to_sequence_number_insert(&self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { let mut table = self.sequence_number_to_satpoint.borrow_mut(); table.insert(sequence, sat_point)?; - - // let key = sat_point.to_vec(); - // let value = u32::as_bytes(&sequence).to_vec(); - // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); Ok(()) } pub fn home_inscriptions_pop_first(&self) -> crate::Result<()> { let mut table = self.home_inscriptions.borrow_mut(); table.pop_first()?; - - // self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { - // v.pop_first() - // }); Ok(()) } pub fn home_inscriptions_insert(&self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { - // let key = u32::as_bytes(sequence_number).to_vec(); - // let value = InscriptionIdValue::as_bytes(&value).to_vec(); - // self.cache_writer.use_cache_mut(CacheTableIndex::HOME_INSCRIPTIONS, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) - let mut table = self.home_inscriptions.borrow_mut(); table .insert(sequence_number, value)?; Ok(()) } pub fn id_to_sequence_number_insert(&self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { - // let key = rmp_serde::to_vec(value).unwrap(); - // let value = sequence.to_le_bytes().as_slice(); - // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) let mut table = self.id_to_sequence_number.borrow_mut(); table .insert(value, sequence_number)?; Ok(()) } pub fn sequence_number_to_children_insert(&self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { - // let key = sequence.to_le_bytes().as_slice(); - // let value = rmp_serde::to_vec(value).unwrap(); - // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_CHILDREN, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) let mut table = self.sequence_number_to_children.borrow_mut(); table.insert(parent_sequence_number, sequence_number)?; Ok(()) } pub fn sequence_number_to_entry_insert(&self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { - // let key = sequence.to_le_bytes().as_slice(); - // let value = rmp_serde::to_vec(value).unwrap(); - // self.cache_writer.use_cache_mut(CacheTableIndex::SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) let mut table = self.sequence_number_to_inscription_entry.borrow_mut(); table.insert(sequence, value)?; Ok(()) } pub fn sat_to_sequence_number_insert(&self, n: &u64, sequence_number: &u32) -> crate::Result<()> { - // let key = n.to_le_bytes().as_slice(); - // let value = sequence.to_le_bytes().as_slice(); - // self.cache_writer.use_cache_mut(CacheTableIndex::SAT_TO_SEQUENCE_NUMBER, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) let mut table = self.sat_to_sequence_number.borrow_mut(); table.insert(n, sequence_number)?; Ok(()) } pub fn inscription_number_to_sequence_number_insert(&self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { - // let key = inscription_number.to_le_bytes().as_slice(); - // let value = sequence_number.to_le_bytes().as_slice(); - // self.cache_writer.use_cache_mut(CacheTableIndex::INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) let mut table = self.inscription_number_to_sequence_number.borrow_mut(); table.insert(inscription_number, sequence_number)?; Ok(()) @@ -367,12 +314,6 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { let mut table = self.outpoint_to_entry.borrow_mut(); table.insert(value, entry)?; Ok(()) - // let key = rmp_serde::to_vec(value).unwrap(); - // let value = entry.to_vec(); - // self.cache_writer.use_cache_mut(CacheTableIndex::OUTPOINT_TO_ENTRY, |v| { - // v.insert(key.to_vec(), value.to_vec()); - // }); - // Ok(()) } pub fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { let mut table = self.transaction_id_to_transaction.borrow_mut(); diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index def4bb1494..ee36fcb26a 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -11,7 +11,7 @@ use anyhow::anyhow; use bitcoin::{OutPoint, Transaction, Txid, TxOut}; use indexer_sdk::client::drect::DirectClient; use indexer_sdk::client::event::ClientEvent; -use indexer_sdk::client::SyncClient; +use indexer_sdk::client::{SyncClient}; use indexer_sdk::configuration::base::{IndexerConfiguration, NetConfiguration, ZMQConfiguration}; use indexer_sdk::factory::common::async_create_and_start_processor; use indexer_sdk::storage::db::memory::MemoryDB; @@ -94,7 +94,10 @@ impl SimulatorServer { ClientEvent::Transaction(tx) => { self.execute_tx(tx, true)?; } - ClientEvent::GetHeight => {} + ClientEvent::GetHeight => { + let height = self.internal_index.internal.block_count()?; + self.client.report_height(height)?; + } ClientEvent::TxDroped(_) => {} ClientEvent::TxConfirmed(_) => {} } @@ -247,8 +250,8 @@ impl SimulatorServer { Ok(()) } - pub fn new(path:impl AsRef, internal_index: Arc, client:DirectClient>>) -> crate::Result { - let simulate_index =Database::create(path)?; + pub fn new(path: impl AsRef, internal_index: Arc, client: DirectClient>>) -> crate::Result { + let simulate_index = Database::create(path)?; let simulate_index = Arc::new(simulate_index); Ok(Self { tx_out_cache: Rc::new(RefCell::new(SimpleLru::new(500))), internal_index: IndexWrapper::new(internal_index), simulate_index, client }) } @@ -506,9 +509,9 @@ pub fn start_simulator(ops: Options, internal: Arc) -> Option { pub(crate) BRC20_TRANSFERABLELOG: Rc>>, pub(crate) BRC20_INSCRIBE_TRANSFER: Rc>>, pub traces: Rc>>, - pub brc20_receipts:Rc>>, + pub brc20_receipts: Rc>>, pub _marker_a: PhantomData<&'a ()>, } @@ -987,11 +990,19 @@ impl<'a, 'db, 'txn> Brc20Reader for SimulateContext<'a, 'db, 'txn> { impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let key = serde_json::to_vec(script_key).unwrap(); + traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_BALANCES, key }); let mut table = self.BRC20_BALANCES.borrow_mut(); update_token_balance(&mut table, script_key, new_balance) } fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let key = tick.as_str(); + let key = key.as_bytes().to_vec(); + traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_TOKEN, key }); + let mut binding = self.BRC20_TOKEN.borrow_mut(); let table = binding.deref_mut(); insert_token_info(table, tick, new_info) @@ -1007,13 +1018,18 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { } fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { - let mut receipts=self.brc20_receipts.borrow_mut(); + let mut receipts = self.brc20_receipts.borrow_mut(); receipts.extend_from_slice(receipt); let mut table = self.BRC20_EVENTS.borrow_mut(); save_transaction_receipts(&mut table, txid, receipt) } fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let binding = script_tick_id_key(script, tick, &inscription.inscription_id); + let key = binding.as_str(); + let key = key.as_bytes().to_vec(); + traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, key }); let mut table = self.BRC20_TRANSFERABLELOG.borrow_mut(); insert_transferable(&mut table, script, tick, inscription) } @@ -1024,6 +1040,10 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { } fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let key = &inscription_id.store(); + let key = InscriptionIdValue::as_bytes(&key); + traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, key }); let mut table = self.BRC20_INSCRIBE_TRANSFER.borrow_mut(); insert_inscribe_transfer_inscription(&mut table, inscription_id, transfer_info) } @@ -1036,16 +1056,27 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { impl<'a, 'db, 'txn> OrdReaderWriter for SimulateContext<'a, 'db, 'txn> { fn save_transaction_operations(&mut self, txid: &Txid, operations: &[InscriptionOp]) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let key = &txid.store(); + let key = TxidValue::as_slice(key).to_vec(); + traces.push(TraceNode { trace_type: CacheTableIndex::ORD_TX_TO_OPERATIONS, key }); let mut table = self.ORD_TX_TO_OPERATIONS.borrow_mut(); save_transaction_operations(&mut table, txid, operations) } fn set_inscription_by_collection_key(&mut self, key: &str, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let trace_key = key.as_bytes().to_vec(); + traces.push(TraceNode { trace_type: CacheTableIndex::COLLECTIONS_KEY_TO_INSCRIPTION_ID, key: trace_key }); let mut table = self.COLLECTIONS_KEY_TO_INSCRIPTION_ID.borrow_mut(); set_inscription_by_collection_key(&mut table, key, inscription_id) } fn set_inscription_attributes(&mut self, inscription_id: &InscriptionId, kind: &[CollectionKind]) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let key = inscription_id.store(); + let key = InscriptionIdValue::as_bytes(&key); + traces.push(TraceNode { trace_type: CacheTableIndex::COLLECTIONS_INSCRIPTION_ID_TO_KINDS, key }); let mut table = self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS.borrow_mut(); set_inscription_attributes( &mut table, From 1e7395deca66e3d707d467bb2548f3520ef66a83 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Mon, 15 Jan 2024 12:31:10 +0800 Subject: [PATCH 41/66] save traces --- src/index.rs | 4 ++++ src/index/simulator/processor.rs | 19 ++++++++++++++++--- src/index/simulator/simulate.rs | 5 ++++- src/okx/datastore/cache.rs | 3 ++- src/okx/protocol/trace.rs | 2 +- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/index.rs b/src/index.rs index 5c11c0d677..4cf07c0d83 100644 --- a/src/index.rs +++ b/src/index.rs @@ -37,6 +37,7 @@ use { sync::{Mutex, Once}, }, }; +use crate::okx::protocol::trace::TraceNode; pub use self::entry::RuneEntry; pub(super) use self::entry::{ @@ -102,6 +103,9 @@ define_table! { BRC20_EVENTS, &TxidValue, &[u8] } define_table! { BRC20_TRANSFERABLELOG, &str, &[u8] } define_table! { BRC20_INSCRIBE_TRANSFER, InscriptionIdValue, &[u8] } +// simulate +define_table! { SIMULATE_TRACE_TABLE, &TxidValue, &[u8] } + #[derive(Debug, PartialEq)] pub enum List { Spent, diff --git a/src/index/simulator/processor.rs b/src/index/simulator/processor.rs index 970aff0a36..5ec356a6c4 100644 --- a/src/index/simulator/processor.rs +++ b/src/index/simulator/processor.rs @@ -13,7 +13,7 @@ use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; use redb::{MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition}; use crate::{Index, InscriptionId, SatPoint}; -use crate::index::entry::{SatPointValue}; +use crate::index::entry::{Entry, SatPointValue}; use crate::index::{HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; use crate::okx::protocol::context::Context; @@ -56,11 +56,10 @@ pub struct StorageProcessor<'a, 'db, 'tx> { pub(super) sequence_number_to_children: Rc>>, pub(super) sequence_number_to_satpoint: Rc>>, pub(super) sequence_number_to_inscription_entry: Rc>>, - pub outpoint_to_sat_ranges: Rc>>, pub sat_to_satpoint: Rc>>, - pub statistic_to_count: Rc>>, + pub trace_table: Rc>>, pub _marker_a: PhantomData<&'a ()>, pub client: Option>>>, @@ -341,4 +340,18 @@ impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { table.insert(key, value)?; Ok(()) } + + pub fn save_traces(&self, tx_id: &Txid) -> crate::Result<()> { + let mut traces = self.traces.borrow_mut(); + let insert_traces = traces.clone(); + traces.clear(); + if insert_traces.is_empty() { + return Ok(()); + } + let mut table = self.trace_table.borrow_mut(); + let key = tx_id.store(); + let value=rmp_serde::to_vec(&insert_traces)?; + table.insert(&key, value.as_slice())?; + Ok(()) + } } \ No newline at end of file diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index ee36fcb26a..d95301cd5a 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -26,7 +26,7 @@ use tokio::sync::watch; use tokio::task::JoinHandle; use crate::{Index, Options, Sat, SatPoint}; use crate::height::Height; -use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION}; +use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, SIMULATE_TRACE_TABLE, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION}; use crate::index::entry::Entry; use crate::index::simulator::error::SimulateError; use crate::index::simulator::processor::{IndexWrapper, StorageProcessor}; @@ -138,6 +138,7 @@ impl SimulatorServer { let OUTPOINT_TO_SAT_RANGES_table = wtx.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); let sat_to_point = wtx.open_table(SAT_TO_SATPOINT).unwrap(); let statis_to_count = wtx.open_table(STATISTIC_TO_COUNT).unwrap(); + let traces_table = wtx.open_table(SIMULATE_TRACE_TABLE)?; let h = height; let ts = block.header.time; @@ -184,6 +185,7 @@ impl SimulatorServer { outpoint_to_sat_ranges: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), sat_to_satpoint: Rc::new(RefCell::new(sat_to_point)), statistic_to_count: Rc::new(RefCell::new(statis_to_count)), + trace_table: Rc::new(RefCell::new(traces_table)), _marker_a: Default::default(), client: Some(self.client.clone()), traces: traces.clone(), @@ -246,6 +248,7 @@ impl SimulatorServer { txdata: vec![(tx.clone(), tx.txid())], }; sim.index_block(block.clone(), height, cache, &processor, &mut operations)?; + processor.save_traces(&tx.txid())?; Ok(()) } diff --git a/src/okx/datastore/cache.rs b/src/okx/datastore/cache.rs index da9d05efcf..eb0623ff80 100644 --- a/src/okx/datastore/cache.rs +++ b/src/okx/datastore/cache.rs @@ -3,9 +3,10 @@ use std::collections::HashMap; use std::marker::PhantomData; use std::rc::Rc; use std::sync::Arc; +use serde::{Deserialize, Serialize}; use crate::Index; -#[derive(Clone, Eq, PartialEq, Hash)] +#[derive(Clone, Eq, PartialEq, Hash,Serialize,Deserialize)] pub enum CacheTableIndex { TXID_TO_INSCRIPTION_RECEIPTS, diff --git a/src/okx/protocol/trace.rs b/src/okx/protocol/trace.rs index 1d37519ced..bf62edf7af 100644 --- a/src/okx/protocol/trace.rs +++ b/src/okx/protocol/trace.rs @@ -25,7 +25,7 @@ pub struct MintTokenInfoDelta { pub new_latest_mint_number: u32, } -#[derive(Clone)] +#[derive(Clone,Serialize,Deserialize)] pub struct TraceNode { pub trace_type: CacheTableIndex, // pub operation: TraceOperation, From cd18c6046ecdccb8e84b1faf2a42d87be46fe17f Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Mon, 15 Jan 2024 14:45:21 +0800 Subject: [PATCH 42/66] rm trace --- src/index/simulator/simulate.rs | 97 +++++++++++++++++++++++++++++++-- src/lib.rs | 2 + src/okx/protocol/simulate.rs | 12 +++- 3 files changed, 103 insertions(+), 8 deletions(-) diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index d95301cd5a..666972b8d9 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -19,20 +19,22 @@ use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; use indexer_sdk::wait_exit_signal; use log::{error, info}; -use redb::{Database, WriteTransaction}; +use redb::{Database, ReadableTable, RedbValue, WriteTransaction}; use tempfile::NamedTempFile; use tokio::runtime::Runtime; use tokio::sync::watch; use tokio::task::JoinHandle; use crate::{Index, Options, Sat, SatPoint}; use crate::height::Height; -use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, SIMULATE_TRACE_TABLE, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION}; +use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, InscriptionIdValue, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, SIMULATE_TRACE_TABLE, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION, TxidValue}; use crate::index::entry::Entry; use crate::index::simulator::error::SimulateError; use crate::index::simulator::processor::{IndexWrapper, StorageProcessor}; use crate::index::updater::pending_updater::PendingUpdater; -use crate::okx::datastore::brc20::{Brc20Reader, Receipt}; +use crate::okx::datastore::brc20::{Brc20Reader, Receipt, Tick}; +use crate::okx::datastore::cache::CacheTableIndex; use crate::okx::datastore::ord::InscriptionOp; +use crate::okx::datastore::ScriptKey; use crate::okx::lru::SimpleLru; use crate::okx::protocol::{ProtocolConfig, ProtocolManager}; use crate::okx::protocol::simulate::SimulateContext; @@ -98,11 +100,95 @@ impl SimulatorServer { let height = self.internal_index.internal.block_count()?; self.client.report_height(height)?; } - ClientEvent::TxDroped(_) => {} - ClientEvent::TxConfirmed(_) => {} + ClientEvent::TxDroped(tx) => { + let tx = tx.clone().into(); + self.remove_tx_traces(&tx)?; + } + ClientEvent::TxConfirmed(tx) => { + let tx = tx.clone().into(); + self.remove_tx_traces(&tx)?; + } } Ok(()) } + fn remove_tx_traces(&self, txid: &Txid) -> crate::Result<()> { + let mut wtx = self.simulate_index.begin_write()?; + let commit = self.do_remove_traces(txid, &wtx)?; + if commit { + wtx.commit()?; + } + Ok(()) + } + fn do_remove_traces(&self, txid: &Txid, wtx: &WriteTransaction) -> crate::Result { + let traces_table = wtx.open_table(SIMULATE_TRACE_TABLE)?; + let value = txid.store(); + let traces = traces_table.get(&value)?; + if traces.is_none() { + return Ok(false); + } + + let mut brc20_balances = wtx.open_table(BRC20_BALANCES)?; + let mut brc20_token = wtx.open_table(BRC20_TOKEN)?; + let mut events = wtx.open_table(BRC20_EVENTS)?; + let mut brc20_transferlog = wtx.open_table(BRC20_TRANSFERABLELOG)?; + let mut brc20_inscribe_transfer = wtx.open_table(BRC20_INSCRIBE_TRANSFER)?; + let mut ord_tx_id_to_operations = wtx.open_table(ORD_TX_TO_OPERATIONS)?; + let mut collections_key_to_inscription_id = wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?; + let mut collection_inscription_id_to_kinds = wtx.open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?; + let binding = traces.unwrap(); + let traces = binding.value(); + let traces: Vec = rmp_serde::from_slice(traces)?; + for node in traces { + let key = node.key; + match node.trace_type { + CacheTableIndex::TXID_TO_INSCRIPTION_RECEIPTS => {} + CacheTableIndex::SEQUENCE_NUMBER_TO_SATPOINT => {} + CacheTableIndex::SAT_TO_SEQUENCE_NUMBER => {} + CacheTableIndex::HOME_INSCRIPTIONS => {} + CacheTableIndex::INSCRIPTION_ID_TO_SEQUENCE_NUMBER => {} + CacheTableIndex::SEQUENCE_NUMBER_TO_CHILDREN => {} + CacheTableIndex::SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY => {} + CacheTableIndex::INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER => {} + CacheTableIndex::OUTPOINT_TO_ENTRY => {} + CacheTableIndex::BRC20_BALANCES => { + let key = String::from_utf8(key).unwrap(); + let key = key.as_str(); + brc20_balances.remove(key)?; + } + CacheTableIndex::BRC20_TOKEN => { + let key = String::from_utf8(key).unwrap(); + let key = key.as_str(); + brc20_token.remove(key)?; + } + CacheTableIndex::BRC20_EVENTS => { + let key = key.as_slice(); + let key: &Txid = &rmp_serde::from_slice(key).unwrap(); + events.remove(&key.store())?; + } + CacheTableIndex::BRC20_TRANSFERABLELOG => { + let key = String::from_utf8(key).unwrap(); + brc20_transferlog.remove(key.as_str())?; + } + CacheTableIndex::BRC20_INSCRIBE_TRANSFER => { + let key = InscriptionIdValue::from_bytes(key.as_slice()); + brc20_inscribe_transfer.remove(&key)?; + } + CacheTableIndex::ORD_TX_TO_OPERATIONS => { + let key: [u8; 32] = key.as_slice().try_into().unwrap(); + ord_tx_id_to_operations.remove(&key)?; + } + CacheTableIndex::COLLECTIONS_KEY_TO_INSCRIPTION_ID => { + let key = String::from_utf8(key).unwrap(); + collections_key_to_inscription_id.remove(key.as_str())?; + } + CacheTableIndex::COLLECTIONS_INSCRIPTION_ID_TO_KINDS => { + let key = InscriptionIdValue::from_bytes(&key); + collection_inscription_id_to_kinds.remove(&key)?; + } + } + } + Ok(true) + } async fn get_client_event(&self) -> crate::Result { let ret = self.client.block_get_event()?; Ok(ret) @@ -565,6 +651,7 @@ mod tests { let tx = client.get_raw_transaction(&Txid::from_str("f9028dbd87d723399181d9bdb80a36e991b56405dfae2ccb6ee033d249b5f724").unwrap(), None).unwrap(); println!("{:?}", tx); simulate_server.execute_tx(&tx, true).unwrap(); + simulate_server.remove_tx_traces(&tx.txid()).unwrap(); } fn create_options() -> Options { diff --git a/src/lib.rs b/src/lib.rs index 18a615efb0..6ac234ee2a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,8 @@ clippy::cast_sign_loss )] +extern crate core; + use { self::{ arguments::Arguments, diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index 849fe4aaec..e77f4a604a 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -792,7 +792,7 @@ use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_ use crate::index::entry::Entry; use crate::index::simulator::processor::IndexWrapper; use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; -use crate::okx::datastore::brc20::redb::script_tick_id_key; +use crate::okx::datastore::brc20::redb::{script_tick_id_key, script_tick_key}; use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick, insert_inscribe_transfer_inscription, insert_token_info, insert_transferable, remove_inscribe_transfer_inscription, remove_transferable, save_transaction_receipts, update_token_balance}; use crate::okx::datastore::cache::CacheTableIndex; use crate::okx::datastore::ord::{InscriptionOp, OrdReader, OrdReaderWriter}; @@ -991,7 +991,9 @@ impl<'a, 'db, 'txn> Brc20Reader for SimulateContext<'a, 'db, 'txn> { impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { let mut traces = self.traces.borrow_mut(); - let key = serde_json::to_vec(script_key).unwrap(); + let binding = script_tick_key(script_key, &new_balance.tick); + let key = binding.as_str(); + let key = key.as_bytes().to_vec(); traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_BALANCES, key }); let mut table = self.BRC20_BALANCES.borrow_mut(); update_token_balance(&mut table, script_key, new_balance) @@ -999,7 +1001,8 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { let mut traces = self.traces.borrow_mut(); - let key = tick.as_str(); + let binding = tick.to_lowercase().hex(); + let key =binding.as_str(); let key = key.as_bytes().to_vec(); traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_TOKEN, key }); @@ -1018,6 +1021,9 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { } fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let key = rmp_serde::to_vec(txid).unwrap(); + traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_EVENTS, key }); let mut receipts = self.brc20_receipts.borrow_mut(); receipts.extend_from_slice(receipt); let mut table = self.BRC20_EVENTS.borrow_mut(); From 17a0e255c88da87da3ff17fafa5dc2b17632e189 Mon Sep 17 00:00:00 2001 From: "fan.ke" Date: Mon, 15 Jan 2024 18:34:18 +0800 Subject: [PATCH 43/66] add simulate api --- dev/start.sh | 1 + src/index/simulator/simulate.rs | 20 ++++++++-------- src/options.rs | 2 +- src/subcommand/server.rs | 42 +++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 11 deletions(-) create mode 100755 dev/start.sh diff --git a/dev/start.sh b/dev/start.sh new file mode 100755 index 0000000000..1d7b410e15 --- /dev/null +++ b/dev/start.sh @@ -0,0 +1 @@ +cargo run -- --data-dir=./_cache --regtest --first-brc20-height=0 --log-level=DEBUG --rpc-url=localhost:28443 --bitcoin-rpc-user=bitcoinrpc --bitcoin-rpc-pass=bitcoinrpc --simulate-zmq-url=tcp://0.0.0.0:29000 --simulate-bitcoin-rpc-url=localhost:28443 --simulate-bitcoin-rpc-pass=bitcoinrpc --simulate-bitcoin-rpc-user=bitcoinrpc --simulate-index=simulate --enable-save-ord-receipts --enable-index-brc20 server --http-port=3888 \ No newline at end of file diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 666972b8d9..5e01354172 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -97,8 +97,8 @@ impl SimulatorServer { self.execute_tx(tx, true)?; } ClientEvent::GetHeight => { - let height = self.internal_index.internal.block_count()?; - self.client.report_height(height)?; + let height = self.internal_index.internal.block_height()?.unwrap_or(Height(0)); + self.client.report_height(height.0)?; } ClientEvent::TxDroped(tx) => { let tx = tx.clone().into(); @@ -206,8 +206,8 @@ impl SimulatorServer { fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction, traces: Rc>>) -> crate::Result, SimulateError> { let brc20_receipts = Rc::new(RefCell::new(vec![])); - let height = self.internal_index.internal.block_count()?; - let block = self.internal_index.internal.get_block_by_height(height)?.unwrap(); + let height = self.internal_index.internal.block_height()?.unwrap_or(Height(0)); + let block = self.internal_index.internal.get_block_by_height(height.0)?.unwrap(); let home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS).unwrap(); let inscription_id_to_sequence_number = wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); @@ -230,7 +230,7 @@ impl SimulatorServer { let ts = block.header.time; let ctx = SimulateContext { network: self.internal_index.internal.get_chain_network().clone(), - current_height: h, + current_height: h.0, current_block_time: ts as u32, internal_index: self.internal_index.clone(), ORD_TX_TO_OPERATIONS: Rc::new(RefCell::new(wtx.open_table(crate::index::ORD_TX_TO_OPERATIONS)?)), @@ -323,8 +323,8 @@ impl SimulatorServer { _marker_b: Default::default(), _marker_tx: Default::default(), }; - let height = self.internal_index.internal.block_count()?; - let block = self.internal_index.internal.get_block_by_height(height)?.unwrap(); + let height = self.internal_index.internal.block_height()?.unwrap_or(Height(0)); + let block = self.internal_index.internal.get_block_by_height(height.0)?.unwrap(); let mut cache = self.tx_out_cache.borrow_mut(); let cache = cache.deref_mut(); @@ -333,7 +333,7 @@ impl SimulatorServer { header: block.header, txdata: vec![(tx.clone(), tx.txid())], }; - sim.index_block(block.clone(), height, cache, &processor, &mut operations)?; + sim.index_block(block.clone(), height.0, cache, &processor, &mut operations)?; processor.save_traces(&tx.txid())?; Ok(()) @@ -644,11 +644,11 @@ mod tests { .init(); let opt = create_options(); let internal = Arc::new(Index::open(&opt).unwrap()); - let client = new_client_for_test("http://localhost:18443".to_string(), "bitcoinrpc".to_string(), "bitcoinrpc".to_string()); + let client = new_client_for_test("http://localhost:28443".to_string(), "bitcoinrpc".to_string(), "bitcoinrpc".to_string()); let simulate_server = SimulatorServer::new("./simulate", internal.clone(), client.clone()).unwrap(); let client = client.clone().get_btc_client(); - let tx = client.get_raw_transaction(&Txid::from_str("f9028dbd87d723399181d9bdb80a36e991b56405dfae2ccb6ee033d249b5f724").unwrap(), None).unwrap(); + let tx = client.get_raw_transaction(&Txid::from_str("12353e95e2ed63f20655c437e98a16be75bfae8c10e049f7e4343653429d8821").unwrap(), None).unwrap(); println!("{:?}", tx); simulate_server.execute_tx(&tx, true).unwrap(); simulate_server.remove_tx_traces(&tx.txid()).unwrap(); diff --git a/src/options.rs b/src/options.rs index aee2aed985..f6b8cff7e0 100644 --- a/src/options.rs +++ b/src/options.rs @@ -93,7 +93,7 @@ pub struct Options { #[arg( long, - default_value = "false", + default_value = "true", help = "Set lru cache to . By default 10000000" )] pub(crate) simulate_enable: bool, diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index e7c929ee9c..fd090a0a18 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -1,3 +1,5 @@ +use bitcoincore_rpc::Auth; +use log::info; use { self::{ accept_encoding::AcceptEncoding, @@ -45,6 +47,8 @@ use { }, utoipa::OpenApi, }; +use crate::index::simulator::simulate::{Simulator, SimulatorServer, start_simulator}; +use crate::okx::datastore::brc20::Receipt; mod accept_encoding; mod accept_json; @@ -198,6 +202,19 @@ impl Server { }); INDEXER.lock().unwrap().replace(index_thread); + let sim_option = options.clone(); + let sim_index = index.clone(); + let simulator_server = thread::spawn(move || { + start_simulator(sim_option,sim_index) + }).join().unwrap() ; + + let client = Arc::new(Client::new( + options.rpc_url.as_ref().unwrap().as_ref(), + Auth::UserPass(options.bitcoin_rpc_user.as_ref().unwrap().clone(), options.bitcoin_rpc_pass.as_ref().unwrap().clone()), + ).unwrap()); + + + #[derive(OpenApi)] #[openapi( paths( @@ -402,10 +419,13 @@ impl Server { .route("/static/*path", get(Self::static_asset)) .route("/status", get(Self::status)) .route("/tx/:txid", get(Self::transaction)) + .route("/tx/simulate/:txid", get(Self::simulate_tx)) .nest("/api", api_router) .layer(Extension(index)) .layer(Extension(server_config.clone())) .layer(Extension(config)) + .layer(Extension(client)) + .layer(Extension(simulator_server)) .layer(SetResponseHeaderLayer::if_not_present( header::CONTENT_SECURITY_POLICY, HeaderValue::from_static("default-src 'self'"), @@ -1667,6 +1687,28 @@ impl Server { Redirect::to(&destination) } + + async fn simulate_tx(Extension(client): Extension>, Extension(simulator): Extension>,Path(tx_id): Path) -> ServerResult>> { + if simulator.is_none() { + + return Err(ServerError::BadRequest("simulator not enabled".to_string())); + } + + let tx = client.get_raw_transaction(&tx_id, None); + if tx.is_err() { + return Err(ServerError::BadRequest("tx not found".to_string())); + } + + + match simulator.unwrap().execute_tx(tx.as_ref().unwrap(), false) { + Ok(data) => { + Ok(Json(data)) + } + Err(err) => { + Err(ServerError::BadRequest(err.to_string())) + } + } + } } #[cfg(test)] From bf61f0d3673e6a469a85baf899cb1314b53c1ea1 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Mon, 15 Jan 2024 19:28:03 +0800 Subject: [PATCH 44/66] multi threads --- .gitignore | 1 + src/index/simulator/simulate.rs | 81 ++++++++++++++++----------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index cb0a311337..8f1163b82c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ /target /test-times.txt /tmp +_cache \ No newline at end of file diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 5e01354172..2a65f8a736 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -8,12 +8,12 @@ use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread; use anyhow::anyhow; -use bitcoin::{OutPoint, Transaction, Txid, TxOut}; +use bitcoin::{Block, OutPoint, Transaction, Txid, TxOut}; use indexer_sdk::client::drect::DirectClient; use indexer_sdk::client::event::ClientEvent; use indexer_sdk::client::{SyncClient}; use indexer_sdk::configuration::base::{IndexerConfiguration, NetConfiguration, ZMQConfiguration}; -use indexer_sdk::factory::common::async_create_and_start_processor; +use indexer_sdk::factory::common::{async_create_and_start_processor, sync_create_and_start_processor}; use indexer_sdk::storage::db::memory::MemoryDB; use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; @@ -90,6 +90,11 @@ impl SimulatorServer { } } } + + fn get_current_height(&self) -> crate::Result { + let height = self.internal_index.internal.block_height()?.unwrap_or(Height(0)); + Ok(height.0) + } async fn handle_event(&self, event: &ClientEvent) -> crate::Result<()> { info!("sim receive event:{:?}", event); match event { @@ -97,8 +102,8 @@ impl SimulatorServer { self.execute_tx(tx, true)?; } ClientEvent::GetHeight => { - let height = self.internal_index.internal.block_height()?.unwrap_or(Height(0)); - self.client.report_height(height.0)?; + let height = self.get_current_height()?; + self.client.report_height(height)?; } ClientEvent::TxDroped(tx) => { let tx = tx.clone().into(); @@ -206,8 +211,8 @@ impl SimulatorServer { fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction, traces: Rc>>) -> crate::Result, SimulateError> { let brc20_receipts = Rc::new(RefCell::new(vec![])); - let height = self.internal_index.internal.block_height()?.unwrap_or(Height(0)); - let block = self.internal_index.internal.get_block_by_height(height.0)?.unwrap(); + let height = self.get_current_height()?; + let block = self.internal_index.internal.get_block_by_height(height)?.unwrap(); let home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS).unwrap(); let inscription_id_to_sequence_number = wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); @@ -230,7 +235,7 @@ impl SimulatorServer { let ts = block.header.time; let ctx = SimulateContext { network: self.internal_index.internal.get_chain_network().clone(), - current_height: h.0, + current_height: h, current_block_time: ts as u32, internal_index: self.internal_index.clone(), ORD_TX_TO_OPERATIONS: Rc::new(RefCell::new(wtx.open_table(crate::index::ORD_TX_TO_OPERATIONS)?)), @@ -278,12 +283,12 @@ impl SimulatorServer { context: ctx, }; - self.loop_simulate_tx(&processor, &tx)?; + self.loop_simulate_tx(h, &block, &processor, &tx)?; let ret = brc20_receipts.borrow(); let ret = ret.deref().clone(); Ok(ret) } - pub fn loop_simulate_tx(&self, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(), SimulateError> { + pub fn loop_simulate_tx(&self, h: u32, block: &Block, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(), SimulateError> { let tx_id = tx.txid(); let mut need_handle_first = vec![]; for input in &tx.input { @@ -307,15 +312,15 @@ impl SimulatorServer { } let parent_tx = parent_tx.unwrap(); info!("parent tx :{:?},exist,but not in utxo data,child_hash:{:?},need to simulate parent tx",&parent,&tx_id); - self.loop_simulate_tx(processor, &parent_tx)?; + self.loop_simulate_tx(h, block, processor, &parent_tx)?; info!("parent tx {:?} simulate done,start to simulate child_hash:{:?}",&parent,&tx_id); } - self.do_simulate_tx(processor, &tx)?; + self.do_simulate_tx(h, block, processor, &tx)?; Ok(()) } - pub fn do_simulate_tx(&self, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(), SimulateError> { + pub fn do_simulate_tx(&self, h: u32, block: &Block, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(), SimulateError> { let mut sim = Simulator { internal_index: self.internal_index.clone(), client: None, @@ -323,8 +328,8 @@ impl SimulatorServer { _marker_b: Default::default(), _marker_tx: Default::default(), }; - let height = self.internal_index.internal.block_height()?.unwrap_or(Height(0)); - let block = self.internal_index.internal.get_block_by_height(height.0)?.unwrap(); + let height = h; + let block = block.clone(); let mut cache = self.tx_out_cache.borrow_mut(); let cache = cache.deref_mut(); @@ -333,7 +338,7 @@ impl SimulatorServer { header: block.header, txdata: vec![(tx.clone(), tx.txid())], }; - sim.index_block(block.clone(), height.0, cache, &processor, &mut operations)?; + sim.index_block(block.clone(), height, cache, &processor, &mut operations)?; processor.save_traces(&tx.txid())?; Ok(()) @@ -579,14 +584,13 @@ pub fn start_simulator(ops: Options, internal: Arc) -> Option) -> Option Date: Tue, 16 Jan 2024 09:18:09 +0800 Subject: [PATCH 45/66] log --- src/okx/protocol/context.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/okx/protocol/context.rs b/src/okx/protocol/context.rs index f21654d94b..f5c7c8a690 100644 --- a/src/okx/protocol/context.rs +++ b/src/okx/protocol/context.rs @@ -25,6 +25,7 @@ use crate::okx::protocol::{BlockContext, ContextTrait}; use crate::SatPoint; use anyhow::anyhow; use bitcoin::{Network, OutPoint, TxOut, Txid}; +use log::info; use redb::Table; #[allow(non_snake_case)] @@ -231,6 +232,7 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for Context<'a, 'db, 'txn> { txid: &Txid, receipt: &[Receipt], ) -> crate::Result<(), Self::Error> { + info!("save transaction receipts: txid: {}, receipt: {:?}", txid, receipt); save_transaction_receipts(self.BRC20_EVENTS, txid, receipt) } From 98254a4ebcfe7d9a00c974824daf41df6347c005 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Tue, 16 Jan 2024 09:26:05 +0800 Subject: [PATCH 46/66] log --- src/index/simulator/simulate.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 2a65f8a736..94594b1596 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -298,22 +298,26 @@ impl SimulatorServer { let prev_tx_id = &input.previous_output.txid; let prev_out = processor.get_txout_by_outpoint(&input.previous_output)?; if prev_out.is_none() { - need_handle_first.push(prev_tx_id); + need_handle_first.push(prev_tx_id.clone()); } } if need_handle_first.is_empty() { info!("parent suits is ready,start to simulate tx:{:?}",&tx_id); } - for parent in need_handle_first { - let parent_tx = processor.get_transaction(&parent)?; + for (index, parent) in need_handle_first.iter().enumerate() { + let parent_tx = processor.get_transaction(parent)?; if parent_tx.is_none() { - error!("parent tx not exist,tx_hash:{:?},child_hash:{:?}",&parent,&tx_id); + error!("parent tx not exist,tx_hash:{:?},child_hash:{:?}",*parent,&tx_id); return Err(SimulateError::TxNotFound(parent.clone())); } let parent_tx = parent_tx.unwrap(); info!("parent tx :{:?},exist,but not in utxo data,child_hash:{:?},need to simulate parent tx",&parent,&tx_id); self.loop_simulate_tx(h, block, processor, &parent_tx)?; - info!("parent tx {:?} simulate done,start to simulate child_hash:{:?}",&parent,&tx_id); + if index == need_handle_first.len() - 1 { + info!("all parent txs {:?} simulate done,start to simulate child_hash:{:?}",&need_handle_first,&tx_id); + } else { + info!("parent tx {:?} simulate done,start to simulate next parent:{:?}",&parent,need_handle_first[index+1]); + } } self.do_simulate_tx(h, block, processor, &tx)?; From 216c9ded16c6592ab689f9cbff417973bf04a296 Mon Sep 17 00:00:00 2001 From: "fan.ke" Date: Tue, 16 Jan 2024 16:56:49 +0800 Subject: [PATCH 47/66] add confirm and pending receipt api --- src/index/simulator/simulate.rs | 26 +++++++++++++++++++++++++- src/subcommand/server.rs | 19 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 94594b1596..995b95b30a 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -24,7 +24,7 @@ use tempfile::NamedTempFile; use tokio::runtime::Runtime; use tokio::sync::watch; use tokio::task::JoinHandle; -use crate::{Index, Options, Sat, SatPoint}; +use crate::{Index, InscriptionId, Options, Sat, SatPoint}; use crate::height::Height; use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, InscriptionIdValue, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, SIMULATE_TRACE_TABLE, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION, TxidValue}; use crate::index::entry::Entry; @@ -32,6 +32,7 @@ use crate::index::simulator::error::SimulateError; use crate::index::simulator::processor::{IndexWrapper, StorageProcessor}; use crate::index::updater::pending_updater::PendingUpdater; use crate::okx::datastore::brc20::{Brc20Reader, Receipt, Tick}; +use crate::okx::datastore::brc20::redb::table::get_transaction_receipts; use crate::okx::datastore::cache::CacheTableIndex; use crate::okx::datastore::ord::InscriptionOp; use crate::okx::datastore::ScriptKey; @@ -209,6 +210,29 @@ impl SimulatorServer { Ok(ret) } + pub fn get_receipt(&self,tx_id: Txid) -> Result,anyhow::Error> { + let rx = self.simulate_index.begin_read()?; + let tab = rx.open_table(BRC20_EVENTS)?; + let ret = get_transaction_receipts(&tab, &tx_id)?; + Ok(ret) + // let mut simulate_receipts = ret.into_iter().map(|v| { + // (v.inscription_id.clone(), v) + // }).collect::>(); + // let internal = self.internal_index.use_internal_table(BRC20_EVENTS, |table| { + // get_transaction_receipts(&table, &tx_id) + // })?; + // for node in internal { + // if !simulate_receipts.contains_key(&node.inscription_id) { + // simulate_receipts.insert(node.inscription_id.clone(), node.clone()); + // } + // } + // let ret = simulate_receipts.into_iter().map(|(_, v)| { + // v + // }).collect(); + // Ok(simulate_receipts.into_iter().map(|(_, v)| { + // v + // }).collect()) + } fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction, traces: Rc>>) -> crate::Result, SimulateError> { let brc20_receipts = Rc::new(RefCell::new(vec![])); let height = self.get_current_height()?; diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index fd090a0a18..c41815324e 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -49,6 +49,7 @@ use { }; use crate::index::simulator::simulate::{Simulator, SimulatorServer, start_simulator}; use crate::okx::datastore::brc20::Receipt; +use crate::okx::datastore::brc20::redb::table::get_transaction_receipts; mod accept_encoding; mod accept_json; @@ -420,6 +421,7 @@ impl Server { .route("/status", get(Self::status)) .route("/tx/:txid", get(Self::transaction)) .route("/tx/simulate/:txid", get(Self::simulate_tx)) + .route("/tx/multiple_receipt/:txid",get(Self::confirm_or_pending_receipt)) .nest("/api", api_router) .layer(Extension(index)) .layer(Extension(server_config.clone())) @@ -1709,6 +1711,23 @@ impl Server { } } } + + async fn confirm_or_pending_receipt(Extension(index): Extension>, Extension(simulator): Extension>, Path(tx_id): Path) -> ServerResult>{ + let pending_receipt = simulator.unwrap().get_receipt(tx_id.clone()).unwrap_or(Vec::new()); + let confirm_receipt = index.brc20_get_tx_events_by_txid(&tx_id).unwrap_or(Some(Vec::new())); + let receipt = MultipleReceipt { + confirm: confirm_receipt, + pending: Some(pending_receipt), + }; + + Ok(Json(receipt)) + } +} + +#[derive(Serialize, Deserialize)] +struct MultipleReceipt { + pub confirm: Option>, + pub pending: Option>, } #[cfg(test)] From 2c6e09e4737fc5c0ac54a13b3bf578e1fcbc2329 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:01:54 +0800 Subject: [PATCH 48/66] fix --- src/index/simulator/error.rs | 3 +++ src/okx/protocol/simulate.rs | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/index/simulator/error.rs b/src/index/simulator/error.rs index 55c54fe822..2985d93723 100644 --- a/src/index/simulator/error.rs +++ b/src/index/simulator/error.rs @@ -23,4 +23,7 @@ pub enum SimulateError { #[error("transaction failed: {0}")] TransactionError(#[from] redb::TransactionError), + + #[error("msg error: {0}")] + MsgError(String) } \ No newline at end of file diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index e77f4a604a..d7d90640d4 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -790,6 +790,7 @@ use tempfile::NamedTempFile; use crate::{Index, InscriptionId, SatPoint}; use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; use crate::index::entry::Entry; +use crate::index::simulator::error::SimulateError; use crate::index::simulator::processor::IndexWrapper; use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; use crate::okx::datastore::brc20::redb::{script_tick_id_key, script_tick_key}; @@ -1012,9 +1013,13 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { } fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { + let info = self.get_token_info(tick)?; + if info.is_none() { + return Err( anyhow!(format!("token {:?} not exist", tick.to_lowercase().to_string()))); + } + let mut info = info.unwrap(); let mut binding = self.BRC20_TOKEN.borrow_mut(); let table = binding.deref_mut(); - let mut info = get_token_info(table, tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); info.minted = minted_amt; info.latest_mint_number = minted_block_number; insert_token_info(table, tick, &info) From 339e25de1ba2260d6474a6fc24cae5496ddb4d27 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Wed, 17 Jan 2024 11:44:39 +0800 Subject: [PATCH 49/66] rm debug codes --- Cargo.lock | 1 + Cargo.toml | 3 +- src/index.rs | 8 +- src/index/simulator/error.rs | 3 - src/index/simulator/processor.rs | 1 - src/index/simulator/simulate.rs | 55 +- src/lib.rs | 1 - src/okx/datastore/brc20/redb/mod.rs | 1 - src/okx/datastore/brc20/redb/pending.rs | 225 ------- src/okx/datastore/cache.rs | 82 +-- src/okx/protocol/brc20/msg_executor.rs | 95 ++- src/okx/protocol/brc20/msg_resolver.rs | 399 +++++++----- src/okx/protocol/execute_manager.rs | 2 - src/okx/protocol/mod.rs | 3 +- src/okx/protocol/ord/bitmap.rs | 2 - src/okx/protocol/protocol_manager.rs | 2 - src/okx/protocol/resolve_manager.rs | 1 - src/okx/protocol/simulate.rs | 793 +----------------------- src/okx/protocol/trace.rs | 41 -- src/subcommand/server.rs | 4 +- 20 files changed, 343 insertions(+), 1379 deletions(-) delete mode 100644 src/okx/datastore/brc20/redb/pending.rs diff --git a/Cargo.lock b/Cargo.lock index 5a6e7d1a6c..1799efbc72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1911,6 +1911,7 @@ dependencies = [ [[package]] name = "indexer-sdk" version = "0.1.0" +source = "git+https://github.com/ItsFunny/indexer-sdk.git#855079394cd5331996532f7fc06377ab55dc3a82" dependencies = [ "async-channel 1.9.0", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index 176a736ba4..c563977cef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,8 +74,7 @@ log4rs = { version = "1.2.0", features = ["gzip"] } once_cell = "1.19.0" rmp-serde = "1.1.2" rayon = "1.8.0" -#indexer-sdk={git="https://github.com/ItsFunny/indexer-sdk.git"} -indexer-sdk={path="/Users/lvcong/RustroverProjects/indexer-sdk"} +indexer-sdk={git="https://github.com/ItsFunny/indexer-sdk.git"} [dev-dependencies] criterion = "0.5.1" executable-path = "1.0.0" diff --git a/src/index.rs b/src/index.rs index 4cf07c0d83..865a02f2c6 100644 --- a/src/index.rs +++ b/src/index.rs @@ -37,7 +37,6 @@ use { sync::{Mutex, Once}, }, }; -use crate::okx::protocol::trace::TraceNode; pub use self::entry::RuneEntry; pub(super) use self::entry::{ @@ -259,8 +258,11 @@ impl Index { log::info!("Setting DB cache size to {} bytes", db_cache_size); - // TODO: why none? - let durability = redb::Durability::Immediate; + let durability = if cfg!(test) { + redb::Durability::None + } else { + redb::Durability::Immediate + }; let index_runes; let index_sats; diff --git a/src/index/simulator/error.rs b/src/index/simulator/error.rs index 2985d93723..55c54fe822 100644 --- a/src/index/simulator/error.rs +++ b/src/index/simulator/error.rs @@ -23,7 +23,4 @@ pub enum SimulateError { #[error("transaction failed: {0}")] TransactionError(#[from] redb::TransactionError), - - #[error("msg error: {0}")] - MsgError(String) } \ No newline at end of file diff --git a/src/index/simulator/processor.rs b/src/index/simulator/processor.rs index 5ec356a6c4..9eaec662ce 100644 --- a/src/index/simulator/processor.rs +++ b/src/index/simulator/processor.rs @@ -16,7 +16,6 @@ use crate::{Index, InscriptionId, SatPoint}; use crate::index::entry::{Entry, SatPointValue}; use crate::index::{HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; -use crate::okx::protocol::context::Context; use crate::okx::protocol::simulate::SimulateContext; use crate::okx::protocol::trace::TraceNode; diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 995b95b30a..4109fd4fb8 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::collections::{HashMap, HashSet, VecDeque}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; -use std::path::{Path, PathBuf}; +use std::path::{Path}; use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -13,29 +13,27 @@ use indexer_sdk::client::drect::DirectClient; use indexer_sdk::client::event::ClientEvent; use indexer_sdk::client::{SyncClient}; use indexer_sdk::configuration::base::{IndexerConfiguration, NetConfiguration, ZMQConfiguration}; -use indexer_sdk::factory::common::{async_create_and_start_processor, sync_create_and_start_processor}; +use indexer_sdk::factory::common::{sync_create_and_start_processor}; use indexer_sdk::storage::db::memory::MemoryDB; use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; use indexer_sdk::wait_exit_signal; use log::{error, info}; use redb::{Database, ReadableTable, RedbValue, WriteTransaction}; -use tempfile::NamedTempFile; use tokio::runtime::Runtime; use tokio::sync::watch; use tokio::task::JoinHandle; -use crate::{Index, InscriptionId, Options, Sat, SatPoint}; +use crate::{Index, Options, Sat, SatPoint}; use crate::height::Height; -use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, InscriptionIdValue, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, SIMULATE_TRACE_TABLE, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION, TxidValue}; +use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, InscriptionIdValue, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, SIMULATE_TRACE_TABLE, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION}; use crate::index::entry::Entry; use crate::index::simulator::error::SimulateError; use crate::index::simulator::processor::{IndexWrapper, StorageProcessor}; use crate::index::updater::pending_updater::PendingUpdater; -use crate::okx::datastore::brc20::{Brc20Reader, Receipt, Tick}; +use crate::okx::datastore::brc20::{Brc20Reader, Receipt}; use crate::okx::datastore::brc20::redb::table::get_transaction_receipts; use crate::okx::datastore::cache::CacheTableIndex; use crate::okx::datastore::ord::InscriptionOp; -use crate::okx::datastore::ScriptKey; use crate::okx::lru::SimpleLru; use crate::okx::protocol::{ProtocolConfig, ProtocolManager}; use crate::okx::protocol::simulate::SimulateContext; @@ -118,7 +116,7 @@ impl SimulatorServer { Ok(()) } fn remove_tx_traces(&self, txid: &Txid) -> crate::Result<()> { - let mut wtx = self.simulate_index.begin_write()?; + let wtx = self.simulate_index.begin_write()?; let commit = self.do_remove_traces(txid, &wtx)?; if commit { wtx.commit()?; @@ -200,7 +198,7 @@ impl SimulatorServer { Ok(ret) } pub fn execute_tx(&self, tx: &Transaction, commit: bool) -> crate::Result, SimulateError> { - let mut wtx = self.simulate_index.begin_write()?; + let wtx = self.simulate_index.begin_write()?; let traces = Rc::new(RefCell::new(vec![])); let ret = self.simulate_tx(tx, &wtx, traces)?; if commit { @@ -210,28 +208,11 @@ impl SimulatorServer { Ok(ret) } - pub fn get_receipt(&self,tx_id: Txid) -> Result,anyhow::Error> { + pub fn get_receipt(&self, tx_id: Txid) -> Result, anyhow::Error> { let rx = self.simulate_index.begin_read()?; let tab = rx.open_table(BRC20_EVENTS)?; let ret = get_transaction_receipts(&tab, &tx_id)?; Ok(ret) - // let mut simulate_receipts = ret.into_iter().map(|v| { - // (v.inscription_id.clone(), v) - // }).collect::>(); - // let internal = self.internal_index.use_internal_table(BRC20_EVENTS, |table| { - // get_transaction_receipts(&table, &tx_id) - // })?; - // for node in internal { - // if !simulate_receipts.contains_key(&node.inscription_id) { - // simulate_receipts.insert(node.inscription_id.clone(), node.clone()); - // } - // } - // let ret = simulate_receipts.into_iter().map(|(_, v)| { - // v - // }).collect(); - // Ok(simulate_receipts.into_iter().map(|(_, v)| { - // v - // }).collect()) } fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction, traces: Rc>>) -> crate::Result, SimulateError> { let brc20_receipts = Rc::new(RefCell::new(vec![])); @@ -245,12 +226,12 @@ impl SimulatorServer { let sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); let satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); let sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); - let mut sequence_number_to_inscription_entry = + let sequence_number_to_inscription_entry = Rc::new(RefCell::new(wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap())); let sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); let transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); let outpoint_to_entry = Rc::new(RefCell::new(wtx.open_table(OUTPOINT_TO_ENTRY).unwrap())); - let OUTPOINT_TO_SAT_RANGES_table = wtx.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); + let outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); let sat_to_point = wtx.open_table(SAT_TO_SATPOINT).unwrap(); let statis_to_count = wtx.open_table(STATISTIC_TO_COUNT).unwrap(); let traces_table = wtx.open_table(SIMULATE_TRACE_TABLE)?; @@ -297,7 +278,7 @@ impl SimulatorServer { sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), sequence_number_to_inscription_entry, - outpoint_to_sat_ranges: Rc::new(RefCell::new(OUTPOINT_TO_SAT_RANGES_table)), + outpoint_to_sat_ranges: Rc::new(RefCell::new(outpoint_to_sat_ranges)), sat_to_satpoint: Rc::new(RefCell::new(sat_to_point)), statistic_to_count: Rc::new(RefCell::new(statis_to_count)), trace_table: Rc::new(RefCell::new(traces_table)), @@ -645,24 +626,12 @@ pub fn start_simulator(ops: Options, internal: Arc) -> Option crate::Result, Self::Error> { - let value: Option> = self.0.use_cache(CacheTableIndex::BRC20_BALANCES, |maybe_cache| { - if maybe_cache.is_none() { - return None; - } - todo!() - }); - if value.is_none() { - let index = self.0.get_index(); - let rtx = index.begin_read()?; - let table = rtx.0.open_table(BRC20_BALANCES)?; - return get_balances(&table, script_key); - } - - todo!() - } - - fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { - let value: Option = self.0.use_cache(CacheTableIndex::BRC20_BALANCES, |maybe_cache| { - if maybe_cache.is_none() { - return None; - } - todo!() - }); - if value.is_none() { - let index = self.0.get_index(); - let rtx = index.begin_read()?; - let table = rtx.0.open_table(BRC20_BALANCES)?; - return get_balance(&table, script_key, tick); - } - todo!() - } - - fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { - let value: Option = self.0.use_cache(CacheTableIndex::BRC20_TOKEN, |maybe_cache| { - if maybe_cache.is_none() { - return None; - } - todo!() - }); - if value.is_none() { - let index = self.0.get_index(); - let rtx = index.begin_read()?; - let table = rtx.0.open_table(BRC20_TOKEN)?; - return get_token_info(&table, tick); - } - todo!() - } - - fn get_tokens_info(&self) -> crate::Result, Self::Error> { - let value: Option> = self.0.use_cache(CacheTableIndex::BRC20_TOKEN, |maybe_cache| { - if maybe_cache.is_none() { - return None; - } - todo!() - }); - if value.is_none() { - let index = self.0.get_index(); - let rtx = index.begin_read()?; - let table = rtx.0.open_table(BRC20_TOKEN)?; - return get_tokens_info(&table); - } - todo!() - } - - fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { - let value: Option> = self.0.use_cache(CacheTableIndex::BRC20_EVENTS, |maybe_cache| { - if maybe_cache.is_none() { - return None; - } - todo!() - }); - if value.is_none() { - let index = self.0.get_index(); - let rtx = index.begin_read()?; - let table = rtx.0.open_table(BRC20_EVENTS)?; - return get_transaction_receipts(&table, txid); - } - - todo!() - } - - fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { - let value: Option> = self.0.use_cache(CacheTableIndex::BRC20_TRANSFERABLELOG, |maybe_cache| { - if maybe_cache.is_none() { - return None; - } - todo!() - }); - if value.is_none() { - let index = self.0.get_index(); - let rtx = index.begin_read()?; - let table = rtx.0.open_table(BRC20_TRANSFERABLELOG)?; - return get_transferable(&table, script); - } - todo!() - } - - fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { - let value: Option> = self.0.use_cache(CacheTableIndex::BRC20_TRANSFERABLELOG, |maybe_cache| { - if maybe_cache.is_none() { - return None; - } - todo!() - }); - if value.is_none() { - let index = self.0.get_index(); - let rtx = index.begin_read()?; - let table = rtx.0.open_table(BRC20_TRANSFERABLELOG)?; - return get_transferable_by_tick(&table, script, tick); - } - todo!() - } - - fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { - let value: Option = self.0.use_cache(CacheTableIndex::BRC20_TRANSFERABLELOG, |maybe_cache| { - if maybe_cache.is_none() { - return None; - } - todo!() - }); - if value.is_none() { - let index = self.0.get_index(); - let rtx = index.begin_read()?; - let table = rtx.0.open_table(BRC20_TRANSFERABLELOG)?; - return get_transferable_by_id(&table, script, inscription_id); - } - todo!() - } - - fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { - let value: Option = self.0.use_cache(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |maybe_cache| { - if maybe_cache.is_none() { - return None; - } - todo!() - }); - if value.is_none() { - let index = self.0.get_index(); - let rtx = index.begin_read()?; - let table = rtx.0.open_table(BRC20_INSCRIBE_TRANSFER)?; - return get_inscribe_transfer_inscription(&table, inscription_id); - } - todo!() - } -} - -impl Brc20ReaderWriter for BRC20CacheWrapper { - fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { - let binding = script_tick_key(script_key, &new_balance.tick); - let key = binding.as_str(); - let binding = rmp_serde::to_vec(&new_balance).unwrap(); - let value = binding.as_slice(); - let key = string_to_bytes(key); - self.0.use_cache_mut(CacheTableIndex::BRC20_TOKEN, |v| { - v.data.insert(key, value.to_vec()); - }); - Ok(()) - } - - fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { - let binding = tick.to_lowercase().hex(); - let key = binding.as_str(); - let binding = rmp_serde::to_vec(new_info).unwrap(); - let value = binding.as_slice(); - self.0.use_cache_mut(CacheTableIndex::BRC20_TOKEN, |v| { - v.data.insert(key.as_bytes().to_vec(), value.to_vec()); - }); - Ok(()) - } - - fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { - let mut info = self - .get_token_info(tick)? - .unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); - - info.minted = minted_amt; - info.latest_mint_number = minted_block_number; - self.0.use_cache_mut(CacheTableIndex::BRC20_TOKEN, |v| { - let binding = tick.to_lowercase().hex(); - let key = binding.as_str(); - let key = string_to_bytes(key); - let value = rmp_serde::to_vec(&info).unwrap(); - v.data.insert(key, value.to_vec()); - }); - Ok(()) - } - - fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { - todo!() - } - - fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { - todo!() - } - - fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - todo!() - } - - fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { - todo!() - } - - fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - todo!() - } -} \ No newline at end of file diff --git a/src/okx/datastore/cache.rs b/src/okx/datastore/cache.rs index eb0623ff80..72c026be38 100644 --- a/src/okx/datastore/cache.rs +++ b/src/okx/datastore/cache.rs @@ -1,12 +1,7 @@ -use std::cell::Cell; -use std::collections::HashMap; -use std::marker::PhantomData; -use std::rc::Rc; -use std::sync::Arc; use serde::{Deserialize, Serialize}; -use crate::Index; -#[derive(Clone, Eq, PartialEq, Hash,Serialize,Deserialize)] +#[allow(non_camel_case_types)] +#[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] pub enum CacheTableIndex { TXID_TO_INSCRIPTION_RECEIPTS, @@ -18,7 +13,6 @@ pub enum CacheTableIndex { SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, - BRC20_BALANCES, BRC20_TOKEN, BRC20_EVENTS, @@ -27,76 +21,4 @@ pub enum CacheTableIndex { ORD_TX_TO_OPERATIONS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, -} - -#[derive(Clone)] -pub struct MultiCache { - caches: HashMap, -} - -#[derive(Clone)] -pub enum KeyPrefix {} - -#[derive(Clone, Default)] -pub struct CacheTable { - pub data: HashMap, Vec>, -} - -impl CacheTable { - pub fn insert(&mut self, key: Vec, value: Vec) { - self.data.insert(key, value); - } - pub fn pop_first(&mut self) {} - pub fn get(&self, key: Vec) -> Option> { - self.data.get(&key).map_or(None, |v| { - Some(v.clone()) - }) - } - pub fn remove(&mut self, key: Vec) { - self.data.remove(&key); - } -} - -#[derive(Clone)] -pub struct CacheWriter { - cache: Rc>>, - pub internal_index: Arc, -} - - -pub fn string_to_bytes(s: &str) -> Vec { - let byte_slice: &[u8] = s.as_bytes(); - let byte_vec: Vec = byte_slice.to_vec(); - byte_vec -} - -impl CacheWriter { - pub fn use_cache(&self, table: CacheTableIndex, f: impl FnOnce(Option<&CacheTable>) -> T) -> T { - let cache = self.cache.take(); - let m_cache = cache.as_ref().unwrap(); - let table_cache = m_cache.caches.get(&table); - let ret = f(table_cache); - self.cache.set(cache); - ret - } - pub fn use_cache_mut(&self, table: CacheTableIndex, f: impl FnOnce(&mut CacheTable) -> T) -> T { - let mut cache = self.cache.take(); - let mut m_cache = cache.as_mut().unwrap(); - let mut table_cache = m_cache.caches.get_mut(&table); - if table_cache.is_none() { - let internal_table = CacheTable::default(); - m_cache.caches.insert(table.clone(), internal_table); - table_cache = m_cache.caches.get_mut(&table); - } - - let ret = f(table_cache.as_mut().unwrap()); - self.cache.set(cache); - ret - } - pub fn get_index(&self) -> Arc { - self.internal_index.clone() - } - pub fn new(internal_index: Arc) -> Self { - Self { cache: Default::default(), internal_index } - } } \ No newline at end of file diff --git a/src/okx/protocol/brc20/msg_executor.rs b/src/okx/protocol/brc20/msg_executor.rs index 3575341aaf..4a70c782bf 100644 --- a/src/okx/protocol/brc20/msg_executor.rs +++ b/src/okx/protocol/brc20/msg_executor.rs @@ -3,8 +3,6 @@ use super::{ *, }; -use crate::okx::datastore::brc20::{Brc20Reader, Brc20ReaderWriter}; -use crate::okx::datastore::ord::OrdReader; use crate::{ okx::{ datastore::brc20::{ @@ -34,22 +32,22 @@ pub struct ExecutionMessage { } impl ExecutionMessage { - pub fn from_message(context: &mut T, msg: &Message, network: Network) -> Result { + pub fn from_message(context: &mut T, msg: &Message, network: Network) -> Result { Ok(Self { txid: msg.txid, inscription_id: msg.inscription_id, - inscription_number: context.get_inscription_number_by_sequence_number(msg.sequence_number).map_err(|e| { + inscription_number: context.get_inscription_number_by_sequence_number(msg.sequence_number).map_err(|e|{ anyhow!("failed to get inscription number from state! error: {e}") })?, old_satpoint: msg.old_satpoint, new_satpoint: msg .new_satpoint .ok_or(anyhow!("new satpoint cannot be None"))?, - from: context.get_script_key_on_satpoint(&msg.old_satpoint, network).map_err(|e| { + from: context.get_script_key_on_satpoint(&msg.old_satpoint, network).map_err(|e|{ anyhow!("failed to get script key from state! error: {e}") })?, to: if msg.sat_in_outputs { - Some(context.get_script_key_on_satpoint(msg.new_satpoint.as_ref().unwrap(), network).map_err(|e| { + Some(context.get_script_key_on_satpoint(msg.new_satpoint.as_ref().unwrap(), network).map_err(|e|{ anyhow!("failed to get script key from state! error: {e}") })?) } else { @@ -60,7 +58,7 @@ impl ExecutionMessage { } } -pub fn execute(context: &mut T, msg: &ExecutionMessage) -> Result { +pub fn execute(context: &mut T, msg: &ExecutionMessage) -> Result { log::debug!("BRC20 execute message: {:?}", msg); let event = match &msg.op { Operation::Deploy(deploy) => process_deploy(context, msg, deploy.clone()), @@ -91,7 +89,7 @@ pub fn execute(context: &mut T, msg: &ExecutionMessage) -> Resu Ok(receipt) } -fn process_deploy( +fn process_deploy( context: &mut T, msg: &ExecutionMessage, deploy: Deploy, @@ -101,10 +99,9 @@ fn process_deploy( let tick = deploy.tick.parse::()?; - if let Some(stored_tick_info) = context - .get_token_info(&tick) - .map_err(|e| Error::LedgerError(anyhow!("failed")))? - { + if let Some(stored_tick_info) = context.get_token_info(&tick).map_err(|e|{ + Error::LedgerError(anyhow!("failed to get token info from database: {}", e)) + })? { return Err(Error::BRC20Error(BRC20Error::DuplicateTick( stored_tick_info.tick.to_string(), ))); @@ -158,7 +155,9 @@ fn process_deploy( }; context .insert_token_info(&tick, &new_info) - .map_err(|e| Error::LedgerError(anyhow!("failed2")))?; + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to insert token info to database: {}", e)) + })?; Ok(Event::Deploy(DeployEvent { supply, @@ -168,7 +167,7 @@ fn process_deploy( })) } -fn process_mint(context: &mut T, msg: &ExecutionMessage, mint: Mint) -> Result { +fn process_mint(context: &mut T, msg: &ExecutionMessage, mint: Mint) -> Result { // ignore inscribe inscription to coinbase. let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; @@ -176,7 +175,9 @@ fn process_mint(context: &mut T, msg: &ExecutionMessage, mint: let token_info = context .get_token_info(&tick) - .map_err(|e| Error::LedgerError(anyhow!("failed3")))? + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to get token info from database: {}", e)) + })? .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; let base = BIGDECIMAL_TEN.checked_powu(u64::from(token_info.decimal))?; @@ -223,7 +224,9 @@ fn process_mint(context: &mut T, msg: &ExecutionMessage, mint: // get or initialize user balance. let mut balance = context .get_balance(&to_script_key, &tick) - .map_err(|e| Error::LedgerError(anyhow!("failed4")))? + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to get balance from database: {}", e)) + })? .map_or(Balance::new(&tick), |v| v); // add amount to available balance. @@ -234,13 +237,17 @@ fn process_mint(context: &mut T, msg: &ExecutionMessage, mint: // store to database. context .update_token_balance(&to_script_key, balance) - .map_err(|e| Error::LedgerError(anyhow!("failed5")))?; + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to update balance to database: {}", e)) + })?; // update token minted. let minted = minted.checked_add(&amt)?.checked_to_u128()?; context .update_mint_token_info(&tick, minted, context.block_height()) - .map_err(|e| Error::LedgerError(anyhow!("failed6")))?; + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to update minted to database: {}", e)) + })?; Ok(Event::Mint(MintEvent { tick: token_info.tick, @@ -261,7 +268,9 @@ fn process_inscribe_transfer( let token_info = context .get_token_info(&tick) - .map_err(|e| Error::LedgerError(anyhow!("failed7")))? + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to get token info from database: {}", e)) + })? .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; let base = BIGDECIMAL_TEN.checked_powu(u64::from(token_info.decimal))?; @@ -283,7 +292,9 @@ fn process_inscribe_transfer( let mut balance = context .get_balance(&to_script_key, &tick) - .map_err(|e| Error::LedgerError(anyhow!("failed8")))? + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to get balance from database: {}", e)) + })? .map_or(Balance::new(&tick), |v| v); let overall = Into::::into(balance.overall_balance); @@ -301,7 +312,9 @@ fn process_inscribe_transfer( let amt = amt.checked_to_u128()?; context .update_token_balance(&to_script_key, balance) - .map_err(|e| Error::LedgerError(anyhow!("failed9")))?; + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to update balance to database: {}", e)) + })?; let inscription = TransferableLog { inscription_id: msg.inscription_id, @@ -313,7 +326,9 @@ fn process_inscribe_transfer( context .insert_transferable(&inscription.owner, &tick, &inscription) - .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to insert transferable to database: {}", e)) + })?; context .insert_inscribe_transfer_inscription( @@ -323,7 +338,9 @@ fn process_inscribe_transfer( amt, }, ) - .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to insert inscribe transfer inscription to database: {}", e)) + })?; Ok(Event::InscribeTransfer(InscripbeTransferEvent { tick: inscription.tick, @@ -334,7 +351,9 @@ fn process_inscribe_transfer( fn process_transfer(context: &mut T, msg: &ExecutionMessage) -> Result { let transferable = context .get_transferable_by_id(&msg.from, &msg.inscription_id) - .map_err(|e| Error::LedgerError(anyhow!("failed10")))? + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to get transferable from database: {}", e)) + })? .ok_or(BRC20Error::TransferableNotFound(msg.inscription_id))?; let amt = Into::::into(transferable.amount); @@ -349,13 +368,17 @@ fn process_transfer(context: &mut T, msg: &ExecutionMessage) -> let token_info = context .get_token_info(&tick) - .map_err(|e| Error::LedgerError(anyhow!("failed10")))? + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to get token info from database: {}", e)) + })? .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; // update from key balance. let mut from_balance = context .get_balance(&msg.from, &tick) - .map_err(|e| Error::LedgerError(anyhow!("failed10")))? + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to get balance from database: {}", e)) + })? .map_or(Balance::new(&tick), |v| v); let from_overall = Into::::into(from_balance.overall_balance); @@ -369,7 +392,9 @@ fn process_transfer(context: &mut T, msg: &ExecutionMessage) -> context .update_token_balance(&msg.from, from_balance) - .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to update balance to database: {}", e)) + })?; // redirect receiver to sender if transfer to conibase. let mut out_msg = None; @@ -385,7 +410,9 @@ fn process_transfer(context: &mut T, msg: &ExecutionMessage) -> // update to key balance. let mut to_balance = context .get_balance(&to_script_key, &tick) - .map_err(|e| Error::LedgerError(anyhow!("failed10")))? + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to get balance from database: {}", e)) + })? .map_or(Balance::new(&tick), |v| v); let to_overall = Into::::into(to_balance.overall_balance); @@ -393,15 +420,21 @@ fn process_transfer(context: &mut T, msg: &ExecutionMessage) -> context .update_token_balance(&to_script_key, to_balance) - .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to update balance to database: {}", e)) + })?; context .remove_transferable(&msg.from, &tick, &msg.inscription_id) - .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to remove transferable from database: {}", e)) + })?; context .remove_inscribe_transfer_inscription(&msg.inscription_id) - .map_err(|e| Error::LedgerError(anyhow!("failed10")))?; + .map_err(|e|{ + Error::LedgerError(anyhow!("failed to remove inscribe transfer inscription from database: {}", e)) + })?; Ok(Event::Transfer(TransferEvent { msg: out_msg, diff --git a/src/okx/protocol/brc20/msg_resolver.rs b/src/okx/protocol/brc20/msg_resolver.rs index 4c9aa20a94..5dc84c0ee1 100644 --- a/src/okx/protocol/brc20/msg_resolver.rs +++ b/src/okx/protocol/brc20/msg_resolver.rs @@ -1,6 +1,4 @@ use super::*; -use crate::index::InscriptionIdValue; -use crate::okx::datastore::brc20::redb::table::get_inscribe_transfer_inscription; use crate::{ inscriptions::Inscription, okx::{ @@ -10,9 +8,7 @@ use crate::{ Result, }; use anyhow::anyhow; -use redb::ReadableTable; use crate::okx::datastore::brc20::Brc20ReaderWriter; -use crate::okx::protocol::ContextTrait; impl Message { pub(crate) fn resolve( @@ -82,13 +78,16 @@ impl Message { #[cfg(test)] mod tests { use super::*; - use crate::index::BRC20_INSCRIBE_TRANSFER; + use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY}; use crate::okx::datastore::brc20::redb::table::insert_inscribe_transfer_inscription; use crate::okx::datastore::brc20::{Tick, TransferInfo}; - use bitcoin::OutPoint; - use redb::Database; + use bitcoin::{Network, OutPoint}; + use redb::{Database, WriteTransaction}; use std::str::FromStr; use tempfile::NamedTempFile; + use crate::okx::lru::SimpleLru; + use crate::okx::protocol::BlockContext; + use crate::okx::protocol::context::Context; fn create_inscription(str: &str) -> Inscription { Inscription::new( @@ -158,150 +157,252 @@ mod tests { } } - // #[test] - // fn test_invalid_protocol() { - // let db_file = NamedTempFile::new().unwrap(); - // let db = Database::create(db_file.path()).unwrap(); - // let wtx = db.begin_write().unwrap(); - // let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); - // - // let (inscriptions, op) = create_inscribe_operation( - // r#"{ "p": "brc-20s","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, - // ); - // assert_matches!(Message::resolve(&table, &inscriptions, &op), Ok(None)); - // } - // #[test] - // fn test_cursed_or_unbound_inscription() { - // let db_file = NamedTempFile::new().unwrap(); - // let db = Database::create(db_file.path()).unwrap(); - // let wtx = db.begin_write().unwrap(); - // let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); - // - // let (inscriptions, op) = create_inscribe_operation( - // r#"{ "p": "brc-20","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, - // ); - // let op = InscriptionOp { - // action: Action::New { - // cursed: true, - // unbound: false, - // inscription: inscriptions.get(0).unwrap().clone(), - // vindicated: false, - // }, - // ..op - // }; - // assert_matches!(Message::resolve(&table, &inscriptions, &op), Ok(None)); - // - // let op2 = InscriptionOp { - // action: Action::New { - // cursed: false, - // unbound: true, - // inscription: inscriptions.get(0).unwrap().clone(), - // vindicated: false, - // }, - // ..op - // }; - // assert_matches!(Message::resolve(&table, &inscriptions, &op2), Ok(None)); - // let op3 = InscriptionOp { - // action: Action::New { - // cursed: true, - // unbound: true, - // inscription: inscriptions.get(0).unwrap().clone(), - // vindicated: false, - // }, - // ..op - // }; - // assert_matches!(Message::resolve(&table, &inscriptions, &op3), Ok(None)); - // } + #[test] + fn test_invalid_protocol() { + let db_file = NamedTempFile::new().unwrap(); + let db = Database::create(db_file.path()).unwrap(); + let wtx = db.begin_write().unwrap(); + let context= Context { + chain: BlockContext { + network: Network::Regtest, + blockheight: 0, + blocktime: 0, + }, + tx_out_cache:&mut SimpleLru::new(10), + hit: 0, + miss: 0, + ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS).unwrap(), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID).unwrap(), + COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS).unwrap(), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(), + OUTPOINT_TO_ENTRY: &mut wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(), + BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES).unwrap(), + BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN).unwrap(), + BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS).unwrap(), + BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG).unwrap(), + BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(), + }; + let (inscriptions, op) = create_inscribe_operation( + r#"{ "p": "brc-20s","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, + ); + assert_matches!(Message::resolve(&context, &inscriptions, &op), Ok(None)); + } - // #[test] - // fn test_valid_inscribe_operation() { - // let db_file = NamedTempFile::new().unwrap(); - // let db = Database::create(db_file.path()).unwrap(); - // let wtx = db.begin_write().unwrap(); - // let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); - // - // let (inscriptions, op) = create_inscribe_operation( - // r#"{ "p": "brc-20","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, - // ); - // let _result_msg = Message { - // txid: op.txid, - // sequence_number: op.sequence_number, - // inscription_id: op.inscription_id, - // old_satpoint: op.old_satpoint, - // new_satpoint: op.new_satpoint, - // op: Operation::Deploy(Deploy { - // tick: "ordi".to_string(), - // max_supply: "1000".to_string(), - // mint_limit: Some("10".to_string()), - // decimals: None, - // }), - // sat_in_outputs: true, - // }; - // assert_matches!( - // Message::resolve(&table, &inscriptions, &op), - // Ok(Some(_result_msg)) - // ); - // } + #[test] + fn test_cursed_or_unbound_inscription() { + let db_file = NamedTempFile::new().unwrap(); + let db = Database::create(db_file.path()).unwrap(); + let wtx = db.begin_write().unwrap(); + let context= Context { + chain: BlockContext { + network: Network::Regtest, + blockheight: 0, + blocktime: 0, + }, + tx_out_cache:&mut SimpleLru::new(10), + hit: 0, + miss: 0, + ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS).unwrap(), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID).unwrap(), + COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS).unwrap(), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(), + OUTPOINT_TO_ENTRY: &mut wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(), + BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES).unwrap(), + BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN).unwrap(), + BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS).unwrap(), + BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG).unwrap(), + BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(), + }; + + let (inscriptions, op) = create_inscribe_operation( + r#"{ "p": "brc-20","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, + ); + let op = InscriptionOp { + action: Action::New { + cursed: true, + unbound: false, + inscription: inscriptions.get(0).unwrap().clone(), + vindicated: false, + }, + ..op + }; + assert_matches!(Message::resolve(&context, &inscriptions, &op), Ok(None)); + + let op2 = InscriptionOp { + action: Action::New { + cursed: false, + unbound: true, + inscription: inscriptions.get(0).unwrap().clone(), + vindicated: false, + }, + ..op + }; + assert_matches!(Message::resolve(&context, &inscriptions, &op2), Ok(None)); + let op3 = InscriptionOp { + action: Action::New { + cursed: true, + unbound: true, + inscription: inscriptions.get(0).unwrap().clone(), + vindicated: false, + }, + ..op + }; + assert_matches!(Message::resolve(&context, &inscriptions, &op3), Ok(None)); + } - // #[test] - // fn test_invalid_transfer() { - // let db_file = NamedTempFile::new().unwrap(); - // let db = Database::create(db_file.path()).unwrap(); - // let wtx = db.begin_write().unwrap(); - // let table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); - // - // // inscribe transfer not found - // let op = create_transfer_operation(); - // assert_matches!(Message::resolve(&table, &[], &op), Ok(None)); - // - // // non-first transfer operations. - // let op1 = InscriptionOp { - // old_satpoint: SatPoint { - // outpoint: OutPoint { - // txid: Txid::from_str("3111111111111111111111111111111111111111111111111111111111111111") - // .unwrap(), - // vout: 0, - // }, - // offset: 0, - // }, - // ..op - // }; - // assert_matches!(Message::resolve(&table, &[], &op1), Ok(None)); - // } + #[test] + fn test_valid_inscribe_operation() { + let db_file = NamedTempFile::new().unwrap(); + let db = Database::create(db_file.path()).unwrap(); + let wtx = db.begin_write().unwrap(); + let context= Context { + chain: BlockContext { + network: Network::Regtest, + blockheight: 0, + blocktime: 0, + }, + tx_out_cache:&mut SimpleLru::new(10), + hit: 0, + miss: 0, + ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS).unwrap(), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID).unwrap(), + COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS).unwrap(), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(), + OUTPOINT_TO_ENTRY: &mut wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(), + BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES).unwrap(), + BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN).unwrap(), + BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS).unwrap(), + BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG).unwrap(), + BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(), + }; - // #[test] - // fn test_valid_transfer() { - // let db_file = NamedTempFile::new().unwrap(); - // let db = Database::create(db_file.path()).unwrap(); - // let wtx = db.begin_write().unwrap(); - // let mut table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); - // - // // inscribe transfer not found - // let op = create_transfer_operation(); - // - // insert_inscribe_transfer_inscription( - // &mut table, - // &op.inscription_id, - // TransferInfo { - // tick: Tick::from_str("ordi").unwrap(), - // amt: 100, - // }, - // ) - // .unwrap(); - // let _msg = Message { - // txid: op.txid, - // sequence_number: op.sequence_number, - // inscription_id: op.inscription_id, - // old_satpoint: op.old_satpoint, - // new_satpoint: op.new_satpoint, - // op: Operation::Transfer(Transfer { - // tick: "ordi".to_string(), - // amount: "100".to_string(), - // }), - // sat_in_outputs: true, - // }; - // - // assert_matches!(Message::resolve(&table, &[], &op), Ok(Some(_msg))); - // } + let (inscriptions, op) = create_inscribe_operation( + r#"{ "p": "brc-20","op": "deploy", "tick": "ordi", "max": "1000", "lim": "10" }"#, + ); + let _result_msg = Message { + txid: op.txid, + sequence_number: op.sequence_number, + inscription_id: op.inscription_id, + old_satpoint: op.old_satpoint, + new_satpoint: op.new_satpoint, + op: Operation::Deploy(Deploy { + tick: "ordi".to_string(), + max_supply: "1000".to_string(), + mint_limit: Some("10".to_string()), + decimals: None, + }), + sat_in_outputs: true, + }; + assert_matches!( + Message::resolve(&context, &inscriptions, &op), + Ok(Some(_result_msg)) + ); + } + + #[test] + fn test_invalid_transfer() { + let db_file = NamedTempFile::new().unwrap(); + let db = Database::create(db_file.path()).unwrap(); + let wtx = db.begin_write().unwrap(); + let context= Context { + chain: BlockContext { + network: Network::Regtest, + blockheight: 0, + blocktime: 0, + }, + tx_out_cache:&mut SimpleLru::new(10), + hit: 0, + miss: 0, + ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS).unwrap(), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID).unwrap(), + COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS).unwrap(), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(), + OUTPOINT_TO_ENTRY: &mut wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(), + BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES).unwrap(), + BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN).unwrap(), + BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS).unwrap(), + BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG).unwrap(), + BRC20_INSCRIBE_TRANSFER: &mut wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(), + }; + + // inscribe transfer not found + let op = create_transfer_operation(); + assert_matches!(Message::resolve(&context, &[], &op), Ok(None)); + + // non-first transfer operations. + let op1 = InscriptionOp { + old_satpoint: SatPoint { + outpoint: OutPoint { + txid: Txid::from_str("3111111111111111111111111111111111111111111111111111111111111111") + .unwrap(), + vout: 0, + }, + offset: 0, + }, + ..op + }; + assert_matches!(Message::resolve(&context, &[], &op1), Ok(None)); + } + + #[test] + fn test_valid_transfer() { + let db_file = NamedTempFile::new().unwrap(); + let db = Database::create(db_file.path()).unwrap(); + let wtx = db.begin_write().unwrap(); + let mut table = wtx.open_table(BRC20_INSCRIBE_TRANSFER).unwrap(); + + // inscribe transfer not found + let op = create_transfer_operation(); + + insert_inscribe_transfer_inscription( + &mut table, + &op.inscription_id, + TransferInfo { + tick: Tick::from_str("ordi").unwrap(), + amt: 100, + }, + ) + .unwrap(); + let _msg = Message { + txid: op.txid, + sequence_number: op.sequence_number, + inscription_id: op.inscription_id, + old_satpoint: op.old_satpoint, + new_satpoint: op.new_satpoint, + op: Operation::Transfer(Transfer { + tick: "ordi".to_string(), + amount: "100".to_string(), + }), + sat_in_outputs: true, + }; + + let context= Context { + chain: BlockContext { + network: Network::Regtest, + blockheight: 0, + blocktime: 0, + }, + tx_out_cache:&mut SimpleLru::new(10), + hit: 0, + miss: 0, + ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS).unwrap(), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID).unwrap(), + COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS).unwrap(), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(), + OUTPOINT_TO_ENTRY: &mut wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(), + BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES).unwrap(), + BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN).unwrap(), + BRC20_EVENTS: &mut wtx.open_table(BRC20_EVENTS).unwrap(), + BRC20_TRANSFERABLELOG: &mut wtx.open_table(BRC20_TRANSFERABLELOG).unwrap(), + BRC20_INSCRIBE_TRANSFER: &mut table, + }; + + assert_matches!(Message::resolve(&context, &[], &op), Ok(Some(_msg))); + } } diff --git a/src/okx/protocol/execute_manager.rs b/src/okx/protocol/execute_manager.rs index e4d7a1a50e..b800267a02 100644 --- a/src/okx/protocol/execute_manager.rs +++ b/src/okx/protocol/execute_manager.rs @@ -1,5 +1,3 @@ -use crate::okx::datastore::brc20::Brc20ReaderWriter; -use crate::okx::protocol::context::Context; use anyhow::anyhow; use bitcoin::Txid; use { diff --git a/src/okx/protocol/mod.rs b/src/okx/protocol/mod.rs index 90bfe1a17d..b829c97117 100644 --- a/src/okx/protocol/mod.rs +++ b/src/okx/protocol/mod.rs @@ -8,7 +8,6 @@ pub(crate) mod resolve_manager; pub mod simulate; pub mod trace; -use redb::ReadableTable; pub use self::protocol_manager::ProtocolManager; use { @@ -16,7 +15,7 @@ use { crate::Options, bitcoin::Network, }; -use crate::okx::datastore::brc20::{Brc20ReaderWriter, TransferInfo}; +use crate::okx::datastore::brc20::{Brc20ReaderWriter}; use crate::okx::datastore::ord::OrdReaderWriter; #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/src/okx/protocol/ord/bitmap.rs b/src/okx/protocol/ord/bitmap.rs index 618323f870..b73123db3d 100644 --- a/src/okx/protocol/ord/bitmap.rs +++ b/src/okx/protocol/ord/bitmap.rs @@ -1,5 +1,3 @@ -use crate::okx::datastore::ord::{OrdReader, OrdReaderWriter}; -use crate::okx::protocol::context::Context; use { crate::{ okx::datastore::ord::{ diff --git a/src/okx/protocol/protocol_manager.rs b/src/okx/protocol/protocol_manager.rs index fb55fcf2ce..ffed215196 100644 --- a/src/okx/protocol/protocol_manager.rs +++ b/src/okx/protocol/protocol_manager.rs @@ -1,6 +1,4 @@ use anyhow::anyhow; -use crate::okx::datastore::ord::OrdReaderWriter; -use crate::okx::protocol::context::Context; use { super::*, crate::{ diff --git a/src/okx/protocol/resolve_manager.rs b/src/okx/protocol/resolve_manager.rs index 353d4b9c4f..a6493b80f9 100644 --- a/src/okx/protocol/resolve_manager.rs +++ b/src/okx/protocol/resolve_manager.rs @@ -1,5 +1,4 @@ use crate::inscriptions::ParsedEnvelope; -use crate::okx::protocol::context::Context; use { super::*, crate::{ diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index d7d90640d4..3fe7d08d15 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -1,796 +1,14 @@ -// use std::collections::HashMap; -// use std::sync::Arc; -// use bitcoin::{OutPoint, Txid, TxOut}; -// use redb::{Database, ReadableTable, ReadOnlyTable, ReadTransaction, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; -// use tempfile::NamedTempFile; -// use crate::{Index, InscriptionId}; -// use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionIdValue, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; -// use crate::index::entry::Entry; -// use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; -// use crate::okx::datastore::brc20::redb::{script_tick_id_key, script_tick_key}; -// use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick}; -// use crate::okx::datastore::cache::{CacheTableIndex, CacheWriter}; -// use crate::okx::datastore::ScriptKey; -// use crate::okx::protocol::trace::{BalanceDelta, IndexTracer, MintTokenInfoDelta, string_to_bytes, TraceNode}; -// -// pub struct SimulateContext { -// simulate: CacheWriter, -// internal_index: Arc, -// } -// -// impl SimulateContext { -// // pub fn new( -// // internal_index: Arc, simulate: Context) -> crate::Result { -// // // let mut simulate_tx = simulate_index.begin_write()?; -// // // let ctx = Context { -// // // chain, -// // // tx_out_cache, -// // // hit: 0, -// // // miss: 0, -// // // ORD_TX_TO_OPERATIONS: &mut simulate_tx.open_table(ORD_TX_TO_OPERATIONS)?, -// // // COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut simulate_tx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, -// // // COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut simulate_tx.open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, -// // // SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut simulate_tx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?, -// // // OUTPOINT_TO_ENTRY: &mut simulate_tx.open_table(OUTPOINT_TO_ENTRY)?, -// // // BRC20_BALANCES: &mut simulate_tx.open_table(BRC20_BALANCES)?, -// // // BRC20_TOKEN: &mut simulate_tx.open_table(BRC20_TOKEN)?, -// // // BRC20_EVENTS: &mut simulate_tx.open_table(BRC20_EVENTS)?, -// // // BRC20_TRANSFERABLELOG: &mut simulate_tx.open_table(BRC20_TRANSFERABLELOG)?, -// // // BRC20_INSCRIBE_TRANSFER: &mut simulate_tx.open_table(BRC20_INSCRIBE_TRANSFER)?, -// // // }; -// // Ok(Self { -// // // simulate: ctx, -// // internal_index, -// // simulate, -// // }) -// // } -// pub fn new(simulate: CacheWriter, internal_index: Arc) -> Self { -// Self { simulate, internal_index } -// } -// } -// -// impl SimulateContext { -// fn use_internal_table(&self, -// table_def: TableDefinition, -// f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { -// let rtx = self.internal_index.begin_read()?; -// let table = rtx.0.open_table(table_def)?; -// let ret = f(table); -// ret -// } -// } -// -// // impl Brc20Reader for SimulateContext { -// // type Error = anyhow::Error; -// // -// // fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { -// // let simulate = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { -// // get_balances(&table, script_key) -// // })?; -// // let mut simulate_balances: HashMap = simulate.into_iter() -// // .map(|v| { -// // (v.tick.clone(), v.clone()) -// // }).collect(); -// // let internal = self.use_internal_table(BRC20_BALANCES, |v| { -// // get_balances(&v, script_key) -// // })?; -// // for node in internal { -// // let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); -// // v.transferable_balance = v.transferable_balance + node.transferable_balance; -// // v.overall_balance = v.overall_balance + node.overall_balance; -// // } -// // let ret = simulate_balances -// // .into_iter() -// // .map(|(k, v)| { -// // v.clone() -// // }).collect(); -// // Ok(ret) -// // } -// // -// // fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { -// // let ret = self.simulate_index.use_read_table(BRC20_BALANCES, |table| { -// // get_balance(&table, script_key, tick) -// // })?; -// // if let Some(ret) = ret { -// // return Ok(Some(ret)); -// // } -// // self.use_internal_table(BRC20_BALANCES, |table| { -// // get_balance(&table, script_key, tick) -// // }) -// // } -// // -// // fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { -// // let ret = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { -// // get_token_info(&table, tick) -// // })?; -// // if let Some(ret) = ret { -// // return Ok(Some(ret)); -// // } -// // self.use_internal_table(BRC20_TOKEN, |table| { -// // get_token_info(&table, tick) -// // }) -// // } -// // -// // fn get_tokens_info(&self) -> crate::Result, Self::Error> { -// // let simulate = self.simulate_index.use_read_table(BRC20_TOKEN, |table| { -// // get_tokens_info(&table) -// // })?; -// // let internal = self.use_internal_table(BRC20_TOKEN, |table| { -// // get_tokens_info(&table) -// // })?; -// // // TODO:merge -// // todo!() -// // } -// // -// // fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { -// // let simulate = self.simulate_index.use_read_table(BRC20_EVENTS, |table| { -// // get_transaction_receipts(&table, txid) -// // })?; -// // let internal = self.use_internal_table(BRC20_EVENTS, |table| { -// // get_transaction_receipts(&table, txid) -// // })?; -// // // TODO:merge -// // todo!() -// // } -// // -// // fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { -// // let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable(&table, script) -// // })?; -// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable(&table, script) -// // })?; -// // // TODO: merge -// // todo!() -// // } -// // -// // -// // fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { -// // let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable_by_tick(&table, script, tick) -// // })?; -// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable_by_tick(&table, script, tick) -// // })?; -// // // TODO:merge -// // todo!() -// // } -// // -// // fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { -// // let simulate = self.simulate_index.use_read_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable_by_id(&table, script, inscription_id) -// // })?; -// // if let Some(ret) = simulate { -// // return Ok(Some(ret)); -// // } -// // self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable_by_id(&table, script, inscription_id) -// // }) -// // } -// // -// // fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { -// // let simulate = self.simulate_index.use_read_table(BRC20_INSCRIBE_TRANSFER, |table| { -// // get_inscribe_transfer_inscription(&table, inscription_id) -// // })?; -// // if let Some(ret) = simulate { -// // return Ok(Some(ret)); -// // } -// // self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { -// // get_inscribe_transfer_inscription(&table, inscription_id) -// // }) -// // } -// // } -// // -// // impl Brc20ReaderWriter for SimulateContext { -// // fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { -// // self.simulate_index -// // .use_write_table(BRC20_BALANCES, |mut table| { -// // let binding = script_tick_key(script_key, &new_balance.tick); -// // let key = binding.as_str(); -// // let binding = rmp_serde::to_vec(&new_balance).unwrap(); -// // let value = binding.as_slice(); -// // // let origin = table.get(key)?.map_or(None, |v| { -// // // Some(v.value().to_vec()) -// // // }); -// // table.insert(key, value)?; -// // // let mut delta = BalanceDelta::default(); -// // // if let Some(origin) = origin { -// // // let origin: Balance = rmp_serde::from_slice(&origin).unwrap(); -// // // delta.origin_transferable_balance_delta = origin.transferable_balance; -// // // delta.origin_overall_balance_delta = origin.overall_balance; -// // // delta.new_overall_balance_delta = new_balance.overall_balance; -// // // delta.new_transferable_balance_delta = new_balance.transferable_balance; -// // // } else { -// // // delta.origin_transferable_balance_delta = 0; -// // // delta.origin_overall_balance_delta = 0; -// // // delta.new_overall_balance_delta = new_balance.overall_balance; -// // // delta.new_transferable_balance_delta = new_balance.transferable_balance; -// // // } -// // // let op = TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()); -// // let node = TraceNode { trace_type: CacheTableIndex::BRC20_BALANCES, key: string_to_bytes(key) }; -// // Ok(((), node)) -// // })?; -// // Ok(()) -// // } -// // -// // fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { -// // self.simulate_index -// // .use_write_table(BRC20_TOKEN, |mut table| { -// // let binding = tick.to_lowercase().hex(); -// // let key = binding.as_str(); -// // let binding = rmp_serde::to_vec(new_info).unwrap(); -// // let value = binding.as_slice(); -// // table.insert(key, value)?; -// // -// // let trace = TraceNode { -// // trace_type: CacheTableIndex::BRC20_TOKEN, -// // // operation: TraceOperation::Insert, -// // key: string_to_bytes(key), -// // }; -// // Ok(((), trace)) -// // })?; -// // Ok(()) -// // } -// // -// // -// // fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { -// // let mut info = self.get_token_info(tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); -// // let origin = info.minted; -// // info.minted = minted_amt; -// // info.latest_mint_number = minted_block_number; -// // self.simulate_index -// // .use_write_table(BRC20_TOKEN, |mut table| { -// // let binding = tick.to_lowercase().hex(); -// // let key = binding.as_str(); -// // let binding = rmp_serde::to_vec(&info).unwrap(); -// // let value = binding.as_slice(); -// // table.insert(key, value)?; -// // // let delta = MintTokenInfoDelta { -// // // origin_minted: origin, -// // // new_minted: info.minted, -// // // new_latest_mint_number: minted_block_number, -// // // }; -// // let trace = TraceNode { -// // trace_type: CacheTableIndex::BRC20_TOKEN, -// // // operation: TraceOperation::Update(rmp_serde::to_vec(&delta).unwrap()), -// // key: string_to_bytes(key), -// // }; -// // Ok(((), trace)) -// // })?; -// // Ok(()) -// // } -// // -// // fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { -// // self.simulate_index -// // .use_write_table(BRC20_EVENTS, |mut table| { -// // let tx_id_value = txid.store(); -// // let key = tx_id_value.to_vec(); -// // let binding = rmp_serde::to_vec(receipt).unwrap(); -// // let value = binding.as_slice(); -// // table.insert(&txid.store(), value)?; -// // let trace = TraceNode { -// // trace_type: CacheTableIndex::BRC20_EVENTS, -// // key, -// // }; -// // Ok(((), trace)) -// // })?; -// // Ok(()) -// // // self.simulate.save_transaction_receipts(txid, receipt) -// // } -// // -// // fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { -// // self.simulate_index -// // .use_write_table(BRC20_TRANSFERABLELOG, |mut table| { -// // let binding = script_tick_id_key(script, tick, &inscription.inscription_id); -// // let key = binding.as_str(); -// // let binding = rmp_serde::to_vec(inscription).unwrap(); -// // let value = binding.as_slice(); -// // table.insert(key, value)?; -// // let trace = TraceNode { -// // trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, -// // key: string_to_bytes(key), -// // }; -// // Ok(((), trace)) -// // })?; -// // Ok(()) -// // } -// // -// // fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { -// // self.simulate_index.use_write_table(BRC20_TRANSFERABLELOG, |mut table| { -// // let binding = script_tick_id_key(script, tick, inscription_id); -// // let key = binding.as_str(); -// // table.remove(key)?; -// // let trace = TraceNode { -// // trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, -// // key: string_to_bytes(key), -// // }; -// // Ok(((), trace)) -// // })?; -// // Ok(()) -// // } -// // -// // fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { -// // self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { -// // let key = inscription_id.store(); -// // let key_bytes = InscriptionIdValue::as_bytes(&key); -// // let binding = rmp_serde::to_vec(&transfer_info).unwrap(); -// // let value = binding.as_slice(); -// // table.insert(&key, value)?; -// // let trace = TraceNode { -// // trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, -// // key: key_bytes, -// // }; -// // Ok(((), trace)) -// // })?; -// // Ok(()) -// // } -// // -// // fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { -// // self.simulate_index.use_write_table(BRC20_INSCRIBE_TRANSFER, |mut table| { -// // let key = inscription_id.store(); -// // let key_bytes = InscriptionIdValue::as_bytes(&key); -// // table.remove(&key)?; -// // let trace = TraceNode { -// // trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, -// // key: key_bytes, -// // }; -// // Ok(((), trace)) -// // })?; -// // Ok(()) -// // } -// // } -// -// // impl Brc20Reader for SimulateContext { -// // type Error = anyhow::Error; -// // -// // fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { -// // let simulate = self.simulate.get_balances(script_key)?; -// // let mut simulate_balances: HashMap = simulate.into_iter() -// // .map(|v| { -// // (v.tick.clone(), v.clone()) -// // }).collect(); -// // let internal = self.use_internal_table(BRC20_BALANCES, |v| { -// // get_balances(&v, script_key) -// // })?; -// // for node in internal { -// // let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); -// // v.transferable_balance = v.transferable_balance + node.transferable_balance; -// // v.overall_balance = v.overall_balance + node.overall_balance; -// // } -// // let ret = simulate_balances -// // .into_iter() -// // .map(|(k, v)| { -// // v.clone() -// // }).collect(); -// // Ok(ret) -// // } -// // -// // fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { -// // let ret = self.simulate.get_balance(script_key, tick)?; -// // if let Some(ret) = ret { -// // return Ok(Some(ret)); -// // } -// // self.use_internal_table(BRC20_BALANCES, |table| { -// // get_balance(&table, script_key, tick) -// // }) -// // } -// // -// // fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { -// // let ret = self.simulate.get_token_info(tick)?; -// // if let Some(ret) = ret { -// // return Ok(Some(ret)); -// // } -// // self.use_internal_table(BRC20_TOKEN, |table| { -// // get_token_info(&table, tick) -// // }) -// // } -// // -// // fn get_tokens_info(&self) -> crate::Result, Self::Error> { -// // let simulate = self.simulate.get_tokens_info()?; -// // let internal = self.use_internal_table(BRC20_TOKEN, |table| { -// // get_tokens_info(&table) -// // })?; -// // // TODO:merge -// // todo!() -// // } -// // -// // fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { -// // let simulate = self.simulate.get_transaction_receipts(txid)?; -// // let internal = self.use_internal_table(BRC20_EVENTS, |table| { -// // get_transaction_receipts(&table, txid) -// // })?; -// // // TODO:merge -// // todo!() -// // } -// // -// // fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { -// // let simulate = self.simulate.get_transferable(script)?; -// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable(&table, script) -// // })?; -// // // TODO: merge -// // todo!() -// // } -// // -// // -// // fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { -// // let simulate = self.simulate.get_transferable_by_tick(script, tick)?; -// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable_by_tick(&table, script, tick) -// // })?; -// // // TODO:merge -// // todo!() -// // } -// // -// // fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { -// // let simulate = self.simulate.get_transferable_by_id(script, inscription_id)?; -// // if let Some(ret) = simulate { -// // return Ok(Some(ret)); -// // } -// // self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable_by_id(&table, script, inscription_id) -// // }) -// // } -// // -// // fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { -// // let simulate = self.simulate.get_inscribe_transfer_inscription(inscription_id)?; -// // if let Some(ret) = simulate { -// // return Ok(Some(ret)); -// // } -// // self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { -// // get_inscribe_transfer_inscription(&table, inscription_id) -// // }) -// // } -// // } -// // -// // impl Brc20ReaderWriter for SimulateContext { -// // fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { -// // self.simulate.update_token_balance(script_key, new_balance) -// // } -// // -// // fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { -// // self.simulate.insert_token_info(tick, new_info) -// // } -// // -// // -// // fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { -// // self.simulate.update_mint_token_info(tick, minted_amt, minted_block_number) -// // } -// // -// // fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { -// // self.simulate.save_transaction_receipts(txid, receipt) -// // } -// // -// // fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { -// // self.simulate.insert_transferable(script, tick, inscription) -// // } -// // -// // fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { -// // self.simulate.remove_transferable(script, tick, inscription_id) -// // } -// // -// // fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { -// // self.simulate.insert_inscribe_transfer_inscription(inscription_id, transfer_info) -// // } -// // -// // fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { -// // self.simulate.remove_inscribe_transfer_inscription(inscription_id) -// // } -// // } -// -// impl Brc20Reader for SimulateContext { -// type Error = anyhow::Error; -// -// fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { -// // self.simulate.use_cache_mut(CacheTableIndex::BRC20_BALANCES,|table|{ -// // -// // }) -// // let simulate = self.simulate.get_balances(script_key)?; -// // let mut simulate_balances: HashMap = simulate.into_iter() -// // .map(|v| { -// // (v.tick.clone(), v.clone()) -// // }).collect(); -// // let internal = self.use_internal_table(BRC20_BALANCES, |v| { -// // get_balances(&v, script_key) -// // })?; -// // for node in internal { -// // let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); -// // v.transferable_balance = v.transferable_balance + node.transferable_balance; -// // v.overall_balance = v.overall_balance + node.overall_balance; -// // } -// // let ret = simulate_balances -// // .into_iter() -// // .map(|(k, v)| { -// // v.clone() -// // }).collect(); -// // Ok(ret) -// todo!() -// } -// -// fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { -// let ret = self.simulate.use_cache(CacheTableIndex::BRC20_BALANCES, |table| { -// if table.is_none() { -// return Ok::, Self::Error>(None); -// } -// let key = script_tick_key(script_key, tick); -// let key = key.as_str(); -// let table = table.unwrap(); -// let value = table.get(string_to_bytes(key)); -// if value.is_none() { -// return Ok::, Self::Error>(None); -// } -// let bal: Balance = rmp_serde::from_slice(&value.unwrap()).unwrap(); -// Ok(Some(bal)) -// })?; -// if let Some(ret) = ret { -// return Ok(Some(ret)); -// } -// self.use_internal_table(BRC20_BALANCES, |table| { -// get_balance(&table, script_key, tick) -// }) -// } -// -// fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { -// let ret = self.simulate -// .use_cache(CacheTableIndex::BRC20_TOKEN, |table| { -// if table.is_none() { -// return Ok::, Self::Error>(None); -// } -// let table = table.unwrap(); -// let binding = tick.to_lowercase().hex(); -// let key = binding.as_str(); -// let value = table.get(string_to_bytes(key)); -// if value.is_none() { -// return Ok::, Self::Error>(None); -// } -// let value = value.unwrap(); -// let info: TokenInfo = rmp_serde::from_slice(&value).unwrap(); -// return Ok(Some(info)); -// })?; -// if let Some(ret) = ret { -// return Ok(Some(ret)); -// } -// self.use_internal_table(BRC20_TOKEN, |table| { -// get_token_info(&table, tick) -// }) -// } -// -// fn get_tokens_info(&self) -> crate::Result, Self::Error> { -// // let simulate = self.simulate.get_tokens_info()?; -// // let internal = self.use_internal_table(BRC20_TOKEN, |table| { -// // get_tokens_info(&table) -// // })?; -// // TODO:merge -// todo!() -// } -// -// fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { -// let simulate = self.simulate -// .use_cache(CacheTableIndex::BRC20_EVENTS, |table| { -// if table.is_none() { -// return Ok::>, Self::Error>(None); -// } -// let table = table.unwrap(); -// let key = &txid.store(); -// let key: Vec = key.to_vec(); -// // let key = TxidValue::as_bytes(&key).as_ref(); -// let value = table.get(key); -// if value.is_none() { -// return Ok::>, Self::Error>(None); -// } -// let value = value.unwrap(); -// let ret = rmp_serde::from_slice::>(&value).unwrap(); -// Ok(Some(ret)) -// })?; -// let internal = self.use_internal_table(BRC20_EVENTS, |table| { -// get_transaction_receipts(&table, txid) -// })?; -// // TODO:merge -// todo!() -// } -// -// fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { -// // let simulate = self.simulate.get_transferable(script)?; -// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable(&table, script) -// // })?; -// // TODO: merge -// todo!() -// } -// -// -// fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { -// // let simulate = self.simulate.get_transferable_by_tick(script, tick)?; -// // let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable_by_tick(&table, script, tick) -// // })?; -// // TODO:merge -// todo!() -// } -// -// fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { -// // let simulate = self.simulate.get_transferable_by_id(script, inscription_id)?; -// // if let Some(ret) = simulate { -// // return Ok(Some(ret)); -// // } -// // self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { -// // get_transferable_by_id(&table, script, inscription_id) -// // }) -// todo!() -// } -// -// fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { -// let simulate = self.simulate -// .use_cache(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { -// if table.is_none() { -// return Ok::, Self::Error>(None); -// } -// let table = table.unwrap(); -// let key = inscription_id.store(); -// let key_bytes = InscriptionIdValue::as_bytes(&key); -// let value = table.get(key_bytes); -// if value.is_none() { -// return Ok::, Self::Error>(None); -// } -// let value = value.unwrap(); -// let ret: TransferInfo = rmp_serde::from_slice::(&value).unwrap(); -// return Ok(Some(ret)); -// })?; -// // let simulate = self.simulate.get_inscribe_transfer_inscription(inscription_id)?; -// if let Some(ret) = simulate { -// return Ok(Some(ret)); -// } -// self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { -// get_inscribe_transfer_inscription(&table, inscription_id) -// }) -// } -// } -// -// impl Brc20ReaderWriter for SimulateContext { -// fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { -// self.simulate.use_cache_mut(CacheTableIndex::BRC20_BALANCES, |table| { -// let key = script_tick_key(script_key, &new_balance.tick); -// let key = key.as_str(); -// let binding = rmp_serde::to_vec(&new_balance).unwrap(); -// let value = binding.as_slice(); -// table.insert(string_to_bytes(key), value.to_vec()); -// Ok(()) -// }) -// } -// -// fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { -// self.simulate.use_cache_mut(CacheTableIndex::BRC20_TOKEN, |table| { -// let binding = tick.to_lowercase().hex(); -// let key = binding.as_str(); -// let binding = rmp_serde::to_vec(new_info).unwrap(); -// let value = binding.as_slice(); -// table.insert(string_to_bytes(key), value.to_vec()); -// Ok(()) -// }) -// } -// -// -// fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { -// let mut info = self. -// get_token_info(tick)?.unwrap_or_else(|| panic!("token {} not exist", tick.as_str())); -// info.minted = minted_amt; -// info.latest_mint_number = minted_block_number; -// self.simulate -// .use_cache_mut(CacheTableIndex::BRC20_TOKEN, |table| { -// let binding = tick.to_lowercase().hex(); -// let key = binding.as_str(); -// let value = rmp_serde::to_vec(&info).unwrap(); -// table.insert(string_to_bytes(key), value.to_vec()); -// Ok(()) -// }) -// } -// -// fn save_transaction_receipts(&mut self, txid: &Txid, receipts: &[Receipt]) -> crate::Result<(), Self::Error> { -// self.simulate.use_cache_mut(CacheTableIndex::BRC20_EVENTS, |table| { -// let v = txid.store(); -// let key = v.to_vec(); -// let value = rmp_serde::to_vec(receipts).unwrap(); -// table.insert(key, value); -// Ok(()) -// }) -// } -// -// fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { -// self.simulate -// .use_cache_mut(CacheTableIndex::BRC20_TRANSFERABLELOG, |table| { -// let binding = script_tick_id_key(script, tick, &inscription.inscription_id); -// let key = binding.as_str(); -// let binding = rmp_serde::to_vec(inscription).unwrap(); -// let value = binding.as_slice(); -// table.insert(string_to_bytes(key), value.to_vec()); -// Ok(()) -// }) -// } -// -// fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { -// self.simulate.use_cache_mut(CacheTableIndex::BRC20_TRANSFERABLELOG, |table| { -// let binding = script_tick_id_key(script, tick, inscription_id); -// let key = binding.as_str(); -// table.remove(string_to_bytes(key)); -// Ok(()) -// }) -// } -// -// fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { -// self.simulate.use_cache_mut(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { -// let key = inscription_id.store(); -// let key_bytes = InscriptionIdValue::as_bytes(&key); -// let value = rmp_serde::to_vec(&transfer_info).unwrap(); -// table.insert(key_bytes, value); -// Ok(()) -// }) -// } -// -// fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { -// self.simulate.use_cache_mut(CacheTableIndex::BRC20_INSCRIBE_TRANSFER, |table| { -// let key = inscription_id.store(); -// let key_bytes = InscriptionIdValue::as_bytes(&key); -// table.remove(key_bytes); -// Ok(()) -// }) -// } -// } -// -// #[test] -// pub fn test_asd() {} -// -#[test] -fn test_write() { - let tmpfile = NamedTempFile::new().unwrap(); - let db = Database::builder() - .create(tmpfile.path()) - .unwrap(); - let table_definition: TableDefinition = TableDefinition::new("x"); - - { - let mut wtx = db.begin_write().unwrap(); - let mut table = wtx.open_table(table_definition).unwrap(); - table.insert(1, 1).unwrap(); - let vv = table.get(&1).unwrap().unwrap().value(); - assert_eq!(vv, 1); - } - - - { - let mut wtx = db.begin_write().unwrap(); - let mut table = wtx.open_table(table_definition).unwrap(); - table.insert(2, 2).unwrap(); - let vv = table.get(&2).unwrap().unwrap().value(); - assert_eq!(vv, 2); - let v1 = table.get(&1).unwrap().unwrap().value(); - assert_eq!(v1, 1); - } - - // wtx.commit().unwrap(); - // { - // let rtx = db.begin_read().unwrap(); - // let table = rtx.open_table(table_definition).unwrap(); - // assert_eq!(table.get(&1).unwrap().unwrap().value(), 1); - // } -} - - -////////// - use std::cell::RefCell; use std::collections::HashMap; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::rc::Rc; -use std::sync::Arc; use anyhow::anyhow; use bitcoin::{Network, Txid}; -use redb::{Database, MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition, WriteTransaction}; -use tempfile::NamedTempFile; -use crate::{Index, InscriptionId, SatPoint}; +use redb::{ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition}; +use crate::{InscriptionId, SatPoint}; use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; use crate::index::entry::Entry; -use crate::index::simulator::error::SimulateError; use crate::index::simulator::processor::IndexWrapper; use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; use crate::okx::datastore::brc20::redb::{script_tick_id_key, script_tick_key}; @@ -803,6 +21,7 @@ use crate::okx::datastore::ScriptKey; use crate::okx::protocol::ContextTrait; use crate::okx::protocol::trace::TraceNode; +#[allow(non_snake_case)] #[derive(Clone)] pub struct SimulateContext<'a, 'db, 'txn> { pub network: Network, @@ -850,7 +69,7 @@ impl<'a, 'db, 'txn> Brc20Reader for SimulateContext<'a, 'db, 'txn> { } let ret = simulate_balances .into_iter() - .map(|(k, v)| { + .map(|(_, v)| { v.clone() }).collect(); Ok(ret) @@ -1003,7 +222,7 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { let mut traces = self.traces.borrow_mut(); let binding = tick.to_lowercase().hex(); - let key =binding.as_str(); + let key = binding.as_str(); let key = key.as_bytes().to_vec(); traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_TOKEN, key }); @@ -1015,7 +234,7 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { let info = self.get_token_info(tick)?; if info.is_none() { - return Err( anyhow!(format!("token {:?} not exist", tick.to_lowercase().to_string()))); + return Err(anyhow!(format!("token {:?} not exist", tick.to_lowercase().to_string()))); } let mut info = info.unwrap(); let mut binding = self.BRC20_TOKEN.borrow_mut(); diff --git a/src/okx/protocol/trace.rs b/src/okx/protocol/trace.rs index bf62edf7af..ed6f55292b 100644 --- a/src/okx/protocol/trace.rs +++ b/src/okx/protocol/trace.rs @@ -1,15 +1,6 @@ -use std::sync::Arc; -use redb::{ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition}; use serde::{Deserialize, Serialize}; -use crate::{Index}; use crate::okx::datastore::cache::CacheTableIndex; -// pub enum TraceOperation { -// Update(Vec), -// Delete(Vec), -// Insert, -// } - #[derive(Clone, Default, Serialize, Deserialize)] pub struct BalanceDelta { pub origin_overall_balance_delta: u128, @@ -31,35 +22,3 @@ pub struct TraceNode { // pub operation: TraceOperation, pub key: Vec, } - -#[derive(Clone)] -pub struct IndexTracer { - pub index: Arc, - pub traces: Vec, -} - -pub fn string_to_bytes(s: &str) -> Vec { - let byte_slice: &[u8] = s.as_bytes(); - let byte_vec: Vec = byte_slice.to_vec(); - byte_vec -} - -impl IndexTracer { - pub fn use_read_table(&self, - table_def: TableDefinition, - f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { - let rtx = self.index.begin_read()?; - let table = rtx.0.open_table(table_def)?; - let ret = f(table); - ret - } - pub fn use_write_table(&mut self, - table_def: TableDefinition, - mut f: impl FnMut(Table) -> crate::Result<(T, TraceNode)>) -> crate::Result { - let rtx = self.index.begin_write()?; - let table = rtx.open_table(table_def)?; - let (ret, node) = f(table)?; - self.traces.push(node); - Ok(ret) - } -} \ No newline at end of file diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index c41815324e..ce8c8c8662 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -1,5 +1,4 @@ use bitcoincore_rpc::Auth; -use log::info; use { self::{ accept_encoding::AcceptEncoding, @@ -47,9 +46,8 @@ use { }, utoipa::OpenApi, }; -use crate::index::simulator::simulate::{Simulator, SimulatorServer, start_simulator}; +use crate::index::simulator::simulate::{SimulatorServer, start_simulator}; use crate::okx::datastore::brc20::Receipt; -use crate::okx::datastore::brc20::redb::table::get_transaction_receipts; mod accept_encoding; mod accept_json; From 9fd50bfa26fd4b62b5c7c4f98c9a206e1a1546b0 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Wed, 17 Jan 2024 11:47:29 +0800 Subject: [PATCH 50/66] to revert --- src/index.rs | 2 +- src/index/simulator/error.rs | 28 +- src/index/simulator/mod.rs | 4 +- src/index/simulator/processor.rs | 681 ++++++------ src/index/simulator/simulate.rs | 1333 +++++++++++++----------- src/index/updater.rs | 3 +- src/index/updater/pending_updater.rs | 1108 ++++++++++---------- src/lib.rs | 1 - src/okx/datastore/brc20/redb/mod.rs | 6 +- src/okx/datastore/brc20/tick.rs | 2 +- src/okx/datastore/cache.rs | 36 +- src/okx/datastore/mod.rs | 2 +- src/okx/protocol/brc20/msg_executor.rs | 823 ++++++++------- src/okx/protocol/brc20/msg_resolver.rs | 90 +- src/okx/protocol/context.rs | 482 ++++----- src/okx/protocol/execute_manager.rs | 7 +- src/okx/protocol/mod.rs | 55 +- src/okx/protocol/ord/bitmap.rs | 140 +-- src/okx/protocol/protocol_manager.rs | 10 +- src/okx/protocol/resolve_manager.rs | 96 +- src/okx/protocol/simulate.rs | 898 +++++++++------- src/okx/protocol/trace.rs | 24 +- src/options.rs | 27 +- src/sat_point.rs | 2 +- src/subcommand/server.rs | 70 +- 25 files changed, 3125 insertions(+), 2805 deletions(-) diff --git a/src/index.rs b/src/index.rs index 865a02f2c6..31bc373386 100644 --- a/src/index.rs +++ b/src/index.rs @@ -50,9 +50,9 @@ mod reorg; mod rtx; pub(crate) mod updater; +pub mod simulator; #[cfg(test)] pub(crate) mod testing; -pub mod simulator; const SCHEMA_VERSION: u64 = 16; diff --git a/src/index/simulator/error.rs b/src/index/simulator/error.rs index 55c54fe822..630a26098a 100644 --- a/src/index/simulator/error.rs +++ b/src/index/simulator/error.rs @@ -4,23 +4,21 @@ use redb::{CommitError, TableError}; #[derive(Debug, thiserror::Error)] pub enum SimulateError { - #[error("tx not found: {0}")] - TxNotFound(Txid), + #[error("tx not found: {0}")] + TxNotFound(Txid), - #[error("error: {0}")] - Anyhow(#[from] anyhow::Error), + #[error("error: {0}")] + Anyhow(#[from] anyhow::Error), - #[error("commit failed: {0}")] - CommitError(#[from]CommitError), + #[error("commit failed: {0}")] + CommitError(#[from] CommitError), - #[error("table failed: {0}")] - TableError(#[from]TableError), + #[error("table failed: {0}")] + TableError(#[from] TableError), + #[error("indexer failed: {0}")] + IndexerError(#[from] IndexerError), - #[error("indexer failed: {0}")] - IndexerError(#[from]IndexerError), - - - #[error("transaction failed: {0}")] - TransactionError(#[from] redb::TransactionError), -} \ No newline at end of file + #[error("transaction failed: {0}")] + TransactionError(#[from] redb::TransactionError), +} diff --git a/src/index/simulator/mod.rs b/src/index/simulator/mod.rs index d2e4494444..a5e57cca69 100644 --- a/src/index/simulator/mod.rs +++ b/src/index/simulator/mod.rs @@ -1,3 +1,3 @@ -pub mod simulate; +pub mod error; pub mod processor; -pub mod error; \ No newline at end of file +pub mod simulate; diff --git a/src/index/simulator/processor.rs b/src/index/simulator/processor.rs index 9eaec662ce..cc9091f4c0 100644 --- a/src/index/simulator/processor.rs +++ b/src/index/simulator/processor.rs @@ -1,356 +1,433 @@ -use std::cell::RefCell; -use std::collections::HashSet; -use std::marker::PhantomData; -use std::ops::Deref; -use std::rc::Rc; -use std::sync::Arc; +use crate::index::entry::{Entry, SatPointValue}; +use crate::index::{ + InscriptionEntryValue, InscriptionIdValue, OutPointValue, Statistic, TxidValue, + HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, OUTPOINT_TO_ENTRY, + SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, STATISTIC_TO_COUNT, +}; +use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; +use crate::okx::protocol::simulate::SimulateContext; +use crate::okx::protocol::trace::TraceNode; +use crate::{Index, InscriptionId, SatPoint}; use anyhow::anyhow; -use bitcoin::{OutPoint, Transaction, Txid, TxOut}; +use bitcoin::{OutPoint, Transaction, TxOut, Txid}; use indexer_sdk::client::drect::DirectClient; use indexer_sdk::client::SyncClient; use indexer_sdk::storage::db::memory::MemoryDB; use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; -use redb::{MultimapTable, ReadableTable, ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition}; -use crate::{Index, InscriptionId, SatPoint}; -use crate::index::entry::{Entry, SatPointValue}; -use crate::index::{HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, Statistic, STATISTIC_TO_COUNT, TxidValue}; -use crate::okx::datastore::ord::redb::table::get_txout_by_outpoint; -use crate::okx::protocol::simulate::SimulateContext; -use crate::okx::protocol::trace::TraceNode; +use redb::{ + MultimapTable, ReadOnlyTable, ReadableTable, RedbKey, RedbValue, Table, TableDefinition, +}; +use std::cell::RefCell; +use std::collections::HashSet; +use std::marker::PhantomData; +use std::ops::Deref; +use std::rc::Rc; +use std::sync::Arc; #[derive(Clone)] pub struct IndexWrapper { - pub internal: Arc, + pub internal: Arc, } impl IndexWrapper { - pub fn use_internal_table(&self, - table_def: TableDefinition, - f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { - let rtx = self.internal.begin_read()?; - let table = rtx.0.open_table(table_def)?; - let ret = f(table); - ret - } - pub fn new(internal: Arc) -> Self { - Self { internal } - } + pub fn use_internal_table( + &self, + table_def: TableDefinition, + f: impl FnOnce(ReadOnlyTable) -> crate::Result, + ) -> crate::Result { + let rtx = self.internal.begin_read()?; + let table = rtx.0.open_table(table_def)?; + let ret = f(table); + ret + } + pub fn new(internal: Arc) -> Self { + Self { internal } + } } // could be trait #[derive(Clone)] pub struct StorageProcessor<'a, 'db, 'tx> { - pub internal: IndexWrapper, + pub internal: IndexWrapper, - pub(super) home_inscriptions: Rc>>, - pub(super) id_to_sequence_number: Rc>>, - pub(super) inscription_number_to_sequence_number: Rc>>, - pub(super) outpoint_to_entry: Rc>>, - pub(super) transaction_id_to_transaction: + pub(super) home_inscriptions: Rc>>, + pub(super) id_to_sequence_number: Rc>>, + pub(super) inscription_number_to_sequence_number: Rc>>, + pub(super) outpoint_to_entry: Rc>>, + pub(super) transaction_id_to_transaction: Rc>>, - pub(super) sat_to_sequence_number: Rc>>, - pub(super) satpoint_to_sequence_number: + pub(super) sat_to_sequence_number: Rc>>, + pub(super) satpoint_to_sequence_number: Rc>>, - pub(super) sequence_number_to_children: Rc>>, - pub(super) sequence_number_to_satpoint: Rc>>, - pub(super) sequence_number_to_inscription_entry: Rc>>, - pub outpoint_to_sat_ranges: Rc>>, - pub sat_to_satpoint: Rc>>, - pub statistic_to_count: Rc>>, - pub trace_table: Rc>>, - pub _marker_a: PhantomData<&'a ()>, + pub(super) sequence_number_to_children: Rc>>, + pub(super) sequence_number_to_satpoint: Rc>>, + pub(super) sequence_number_to_inscription_entry: + Rc>>, + pub outpoint_to_sat_ranges: Rc>>, + pub sat_to_satpoint: Rc>>, + pub statistic_to_count: Rc>>, + pub trace_table: Rc>>, + pub _marker_a: PhantomData<&'a ()>, - pub client: Option>>>, + pub client: Option>>>, - pub traces: Rc>>, - pub context: SimulateContext<'a, 'db, 'tx>, + pub traces: Rc>>, + pub context: SimulateContext<'a, 'db, 'tx>, } unsafe impl<'a, 'db, 'tx> Send for StorageProcessor<'a, 'db, 'tx> {} unsafe impl<'a, 'db, 'tx> Sync for StorageProcessor<'a, 'db, 'tx> {} - impl<'a, 'db, 'tx> StorageProcessor<'a, 'db, 'tx> { - pub fn get_transaction(&self, tx_id: &Txid) -> crate::Result> { - let client = self.client.as_ref().unwrap(); - let ret = client.get_transaction_by_tx_id(tx_id.clone())?; - Ok(ret) - } - pub fn create_context(&self) -> crate::Result> { - Ok(self.context.clone()) - } - pub fn next_sequence_number(&self) -> crate::Result { - let table = self.sequence_number_to_inscription_entry.borrow(); - let ret: u32 = table + pub fn get_transaction(&self, tx_id: &Txid) -> crate::Result> { + let client = self.client.as_ref().unwrap(); + let ret = client.get_transaction_by_tx_id(tx_id.clone())?; + Ok(ret) + } + pub fn create_context(&self) -> crate::Result> { + Ok(self.context.clone()) + } + pub fn next_sequence_number(&self) -> crate::Result { + let table = self.sequence_number_to_inscription_entry.borrow(); + let ret: u32 = table + .iter()? + .next_back() + .and_then(|result| result.ok()) + .map(|(number, _id)| number.value() + 1) + .unwrap_or(0); + let v = self + .internal + .use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| { + Ok({ + table .iter()? .next_back() .and_then(|result| result.ok()) .map(|(number, _id)| number.value() + 1) - .unwrap_or(0); - let v = self.internal.use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| Ok({ - table - .iter()? - .next_back() - .and_then(|result| result.ok()) - .map(|(number, _id)| number.value() + 1) - .unwrap_or(0) - }))?; - if ret > v { - return Ok(ret); - } - Ok(v) + .unwrap_or(0) + }) + })?; + if ret > v { + return Ok(ret); } - pub fn id_to_sequence_number_get(&self, x: &InscriptionIdValue) -> crate::Result> { - let ret = self.internal.use_internal_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |table| { - let value = table.get(x).map_err(|e| { - anyhow!("id_to_sequence_number_get error:{}",e) - })?; - if let Some(value) = value { - return Ok(Some(value.value())); - } - return Ok(None); - })?; - if let Some(ret) = ret { - return Ok(Some(ret)); + Ok(v) + } + pub fn id_to_sequence_number_get(&self, x: &InscriptionIdValue) -> crate::Result> { + let ret = self + .internal + .use_internal_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER, |table| { + let value = table + .get(x) + .map_err(|e| anyhow!("id_to_sequence_number_get error:{}", e))?; + if let Some(value) = value { + return Ok(Some(value.value())); } - let table = self.id_to_sequence_number.borrow(); - let v = table.get(x)?; - if let Some(v) = v { - return Ok(Some(v.value())); - } - Ok(None) + return Ok(None); + })?; + if let Some(ret) = ret { + return Ok(Some(ret)); + } + let table = self.id_to_sequence_number.borrow(); + let v = table.get(x)?; + if let Some(v) = v { + return Ok(Some(v.value())); } - pub fn sequence_number_to_entry_get(&self, initial_inscription_sequence_number: u32) -> crate::Result> { - let ret = self.internal.use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| { - let ret = table.get(initial_inscription_sequence_number).map_err(move |e| { - anyhow!("sequence_number_to_entry_get error:{}",e) - })?; - if let Some(ret) = ret { - return Ok(Some(ret.value())); - } - return Ok(None); - })?; + Ok(None) + } + pub fn sequence_number_to_entry_get( + &self, + initial_inscription_sequence_number: u32, + ) -> crate::Result> { + let ret = self + .internal + .use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| { + let ret = table + .get(initial_inscription_sequence_number) + .map_err(move |e| anyhow!("sequence_number_to_entry_get error:{}", e))?; if let Some(ret) = ret { - return Ok(Some(ret)); - } - let table = self.sequence_number_to_inscription_entry.borrow(); - let value = table.get(initial_inscription_sequence_number)?; - if let Some(v) = value { - return Ok(Some(v.value())); + return Ok(Some(ret.value())); } - Ok(None) + return Ok(None); + })?; + if let Some(ret) = ret { + return Ok(Some(ret)); } - pub fn get_lost_sats(&self) -> crate::Result { - let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ - table - .get(&Statistic::LostSats.key())? - .map(|lost_sats| lost_sats.value()) - .unwrap_or(0) - }))?; - if ret == 0 { - let table = self.statistic_to_count.borrow(); - let ret = table - .get(&Statistic::LostSats.key())? - .map(|lost_sats| lost_sats.value()) - .unwrap_or(0); - return Ok(ret); - } - return Ok(ret); + let table = self.sequence_number_to_inscription_entry.borrow(); + let value = table.get(initial_inscription_sequence_number)?; + if let Some(v) = value { + return Ok(Some(v.value())); } - pub fn get_cursed_inscription_count(&self) -> crate::Result { - let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ - table - .get(&Statistic::CursedInscriptions.key())? - .map(|count| count.value()) - .unwrap_or(0) - }))?; - if ret != 0 { - return Ok(ret); - } - let table = self.statistic_to_count.borrow(); - let ret = table + Ok(None) + } + pub fn get_lost_sats(&self) -> crate::Result { + let ret = self + .internal + .use_internal_table(STATISTIC_TO_COUNT, |table| { + Ok({ + table + .get(&Statistic::LostSats.key())? + .map(|lost_sats| lost_sats.value()) + .unwrap_or(0) + }) + })?; + if ret == 0 { + let table = self.statistic_to_count.borrow(); + let ret = table + .get(&Statistic::LostSats.key())? + .map(|lost_sats| lost_sats.value()) + .unwrap_or(0); + return Ok(ret); + } + return Ok(ret); + } + pub fn get_cursed_inscription_count(&self) -> crate::Result { + let ret = self + .internal + .use_internal_table(STATISTIC_TO_COUNT, |table| { + Ok({ + table .get(&Statistic::CursedInscriptions.key())? .map(|count| count.value()) - .unwrap_or(0); - return Ok(ret); + .unwrap_or(0) + }) + })?; + if ret != 0 { + return Ok(ret); } - pub fn get_blessed_inscription_count(&self) -> crate::Result { - let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ - table - .get(&Statistic::BlessedInscriptions.key())? - .map(|count| count.value()) - .unwrap_or(0) - }))?; - if ret != 0 { - return Ok(ret); - } - let table = self.statistic_to_count.borrow(); - let ret = table + let table = self.statistic_to_count.borrow(); + let ret = table + .get(&Statistic::CursedInscriptions.key())? + .map(|count| count.value()) + .unwrap_or(0); + return Ok(ret); + } + pub fn get_blessed_inscription_count(&self) -> crate::Result { + let ret = self + .internal + .use_internal_table(STATISTIC_TO_COUNT, |table| { + Ok({ + table .get(&Statistic::BlessedInscriptions.key())? .map(|count| count.value()) - .unwrap_or(0); - Ok(ret) + .unwrap_or(0) + }) + })?; + if ret != 0 { + return Ok(ret); } - pub fn get_unbound_inscriptions(&self) -> crate::Result { - let table = self.statistic_to_count.borrow(); - let ret = table - .get(&Statistic::UnboundInscriptions.key())? - .map(|unbound_inscriptions| unbound_inscriptions.value()) - .unwrap_or(0); - if ret > 0 { - return Ok(ret); - } - let ret = self.internal.use_internal_table(STATISTIC_TO_COUNT, |table| Ok({ - table - .get(&Statistic::UnboundInscriptions.key())? - .map(|count| count.value()) - .unwrap_or(0) - }))?; - Ok(ret) + let table = self.statistic_to_count.borrow(); + let ret = table + .get(&Statistic::BlessedInscriptions.key())? + .map(|count| count.value()) + .unwrap_or(0); + Ok(ret) + } + pub fn get_unbound_inscriptions(&self) -> crate::Result { + let table = self.statistic_to_count.borrow(); + let ret = table + .get(&Statistic::UnboundInscriptions.key())? + .map(|unbound_inscriptions| unbound_inscriptions.value()) + .unwrap_or(0); + if ret > 0 { + return Ok(ret); } - pub fn get_txout_by_outpoint(&self, x: &OutPoint) -> crate::Result> { - let bindind = self.outpoint_to_entry.borrow(); - let ret = get_txout_by_outpoint(bindind.deref(), x)?; - if let Some(ret) = ret { - return Ok(Some(ret)); - } - let ret = self.internal.use_internal_table(OUTPOINT_TO_ENTRY, |table| { - get_txout_by_outpoint(&table, x) - })?; - Ok(ret) + let ret = self + .internal + .use_internal_table(STATISTIC_TO_COUNT, |table| { + Ok({ + table + .get(&Statistic::UnboundInscriptions.key())? + .map(|count| count.value()) + .unwrap_or(0) + }) + })?; + Ok(ret) + } + pub fn get_txout_by_outpoint(&self, x: &OutPoint) -> crate::Result> { + let bindind = self.outpoint_to_entry.borrow(); + let ret = get_txout_by_outpoint(bindind.deref(), x)?; + if let Some(ret) = ret { + return Ok(Some(ret)); } - pub fn inscriptions_on_output(&self, prev_output: &OutPoint) -> crate::Result> { - let table = self.satpoint_to_sequence_number.borrow(); - let satpoint_to_sequence_number = table.deref(); + let ret = self + .internal + .use_internal_table(OUTPOINT_TO_ENTRY, |table| get_txout_by_outpoint(&table, x))?; + Ok(ret) + } + pub fn inscriptions_on_output( + &self, + prev_output: &OutPoint, + ) -> crate::Result> { + let table = self.satpoint_to_sequence_number.borrow(); + let satpoint_to_sequence_number = table.deref(); - let table = self.sequence_number_to_inscription_entry.borrow(); - let sequence_number_to_entry = table.deref(); - let ret = Index::inscriptions_on_output( - satpoint_to_sequence_number, - sequence_number_to_entry, - prev_output.clone())?; + let table = self.sequence_number_to_inscription_entry.borrow(); + let sequence_number_to_entry = table.deref(); + let ret = Index::inscriptions_on_output( + satpoint_to_sequence_number, + sequence_number_to_entry, + prev_output.clone(), + )?; - let mut set: HashSet<(SatPoint, InscriptionId)> = ret.into_iter() - .map(|(k, v)| { - (k, v) - }).collect(); + let mut set: HashSet<(SatPoint, InscriptionId)> = + ret.into_iter().map(|(k, v)| (k, v)).collect(); - let rtx = self.internal.internal.begin_read()?; - let satpoint_to_sequence_number = rtx.0.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; - let sequence_number_to_entry = rtx.0.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; - let ret = Index::inscriptions_on_output( - &satpoint_to_sequence_number, - &sequence_number_to_entry, - prev_output.clone())?; - for node in ret { - if set.contains(&node) { - continue; - } - set.insert(node); - } - Ok(set.into_iter().collect()) - } - pub fn home_inscriptions_len(&self) -> u64 { - let table = self.home_inscriptions.borrow(); - let sim = table.len().unwrap(); - let ret = self.internal.use_internal_table(HOME_INSCRIPTIONS, |table| { - // TODO - Ok(table.len().unwrap()) - }).unwrap(); - return sim + ret; - } - pub fn sequence_number_to_satpoint_insert(&self, sequence_number: u32, sat_point: &SatPointValue) -> crate::Result<()> { - let mut table = self.sequence_number_to_satpoint.borrow_mut(); - table.insert(sequence_number, sat_point)?; - Ok(()) - } - pub fn satpoint_to_sequence_number_insert(&self, sat_point: &SatPointValue, sequence: u32) -> crate::Result<()> { - let mut table = self.sequence_number_to_satpoint.borrow_mut(); - table.insert(sequence, sat_point)?; - Ok(()) - } - pub fn home_inscriptions_pop_first(&self) -> crate::Result<()> { - let mut table = self.home_inscriptions.borrow_mut(); - table.pop_first()?; - Ok(()) - } - pub fn home_inscriptions_insert(&self, sequence_number: &u32, value: InscriptionIdValue) -> crate::Result<()> { - let mut table = self.home_inscriptions.borrow_mut(); - table - .insert(sequence_number, value)?; - Ok(()) - } - pub fn id_to_sequence_number_insert(&self, value: &InscriptionIdValue, sequence_number: u32) -> crate::Result<()> { - let mut table = self.id_to_sequence_number.borrow_mut(); - table - .insert(value, sequence_number)?; - Ok(()) - } - pub fn sequence_number_to_children_insert(&self, parent_sequence_number: u32, sequence_number: u32) -> crate::Result<()> { - let mut table = self.sequence_number_to_children.borrow_mut(); - table.insert(parent_sequence_number, sequence_number)?; - Ok(()) - } - pub fn sequence_number_to_entry_insert(&self, sequence: u32, value: &InscriptionEntryValue) -> crate::Result<()> { - let mut table = self.sequence_number_to_inscription_entry.borrow_mut(); - table.insert(sequence, value)?; - Ok(()) - } - pub fn sat_to_sequence_number_insert(&self, n: &u64, sequence_number: &u32) -> crate::Result<()> { - let mut table = self.sat_to_sequence_number.borrow_mut(); - table.insert(n, sequence_number)?; - Ok(()) - } - pub fn inscription_number_to_sequence_number_insert(&self, inscription_number: i32, sequence_number: u32) -> crate::Result<()> { - let mut table = self.inscription_number_to_sequence_number.borrow_mut(); - table.insert(inscription_number, sequence_number)?; - Ok(()) - } - pub fn outpoint_to_entry_insert(&self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { - let mut table = self.outpoint_to_entry.borrow_mut(); - table.insert(value, entry)?; - Ok(()) - } - pub fn transaction_id_to_transaction_insert(&self, tx_id: &TxidValue, value: &[u8]) -> crate::Result<()> { - let mut table = self.transaction_id_to_transaction.borrow_mut(); - table.insert(tx_id, value)?; - Ok(()) - } - pub fn outpoint_to_sat_ranges_insert(&self, value: &OutPointValue, data: &[u8]) -> crate::Result<()> { - let mut table = self.outpoint_to_sat_ranges.borrow_mut(); - table.insert(value, data)?; - Ok(()) - } - pub fn outpoint_to_sat_ranges_remove(&self, k: &OutPointValue) -> crate::Result>> { - let mut table = self.outpoint_to_sat_ranges.borrow_mut(); - let ret: Vec = table.remove(k)?.map(|ranges| ranges.value().to_vec()).unwrap_or_default(); - return Ok(Some(ret)); - } - pub fn satpoint_to_sequence_number_remove_all(&self, v: &SatPointValue) -> crate::Result<()> { - let mut table = self.satpoint_to_sequence_number.borrow_mut(); - table - .remove_all(v)?; - Ok(()) - } - pub fn sat_to_satpoint_insert(&self, key: &u64, value: &SatPointValue) -> crate::Result<()> { - let mut table = self.sat_to_satpoint.borrow_mut(); - table.insert(key, value)?; - Ok(()) + let rtx = self.internal.internal.begin_read()?; + let satpoint_to_sequence_number = rtx.0.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?; + let sequence_number_to_entry = rtx.0.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?; + let ret = Index::inscriptions_on_output( + &satpoint_to_sequence_number, + &sequence_number_to_entry, + prev_output.clone(), + )?; + for node in ret { + if set.contains(&node) { + continue; + } + set.insert(node); } + Ok(set.into_iter().collect()) + } + pub fn home_inscriptions_len(&self) -> u64 { + let table = self.home_inscriptions.borrow(); + let sim = table.len().unwrap(); + let ret = self + .internal + .use_internal_table(HOME_INSCRIPTIONS, |table| { + // TODO + Ok(table.len().unwrap()) + }) + .unwrap(); + return sim + ret; + } + pub fn sequence_number_to_satpoint_insert( + &self, + sequence_number: u32, + sat_point: &SatPointValue, + ) -> crate::Result<()> { + let mut table = self.sequence_number_to_satpoint.borrow_mut(); + table.insert(sequence_number, sat_point)?; + Ok(()) + } + pub fn satpoint_to_sequence_number_insert( + &self, + sat_point: &SatPointValue, + sequence: u32, + ) -> crate::Result<()> { + let mut table = self.sequence_number_to_satpoint.borrow_mut(); + table.insert(sequence, sat_point)?; + Ok(()) + } + pub fn home_inscriptions_pop_first(&self) -> crate::Result<()> { + let mut table = self.home_inscriptions.borrow_mut(); + table.pop_first()?; + Ok(()) + } + pub fn home_inscriptions_insert( + &self, + sequence_number: &u32, + value: InscriptionIdValue, + ) -> crate::Result<()> { + let mut table = self.home_inscriptions.borrow_mut(); + table.insert(sequence_number, value)?; + Ok(()) + } + pub fn id_to_sequence_number_insert( + &self, + value: &InscriptionIdValue, + sequence_number: u32, + ) -> crate::Result<()> { + let mut table = self.id_to_sequence_number.borrow_mut(); + table.insert(value, sequence_number)?; + Ok(()) + } + pub fn sequence_number_to_children_insert( + &self, + parent_sequence_number: u32, + sequence_number: u32, + ) -> crate::Result<()> { + let mut table = self.sequence_number_to_children.borrow_mut(); + table.insert(parent_sequence_number, sequence_number)?; + Ok(()) + } + pub fn sequence_number_to_entry_insert( + &self, + sequence: u32, + value: &InscriptionEntryValue, + ) -> crate::Result<()> { + let mut table = self.sequence_number_to_inscription_entry.borrow_mut(); + table.insert(sequence, value)?; + Ok(()) + } + pub fn sat_to_sequence_number_insert(&self, n: &u64, sequence_number: &u32) -> crate::Result<()> { + let mut table = self.sat_to_sequence_number.borrow_mut(); + table.insert(n, sequence_number)?; + Ok(()) + } + pub fn inscription_number_to_sequence_number_insert( + &self, + inscription_number: i32, + sequence_number: u32, + ) -> crate::Result<()> { + let mut table = self.inscription_number_to_sequence_number.borrow_mut(); + table.insert(inscription_number, sequence_number)?; + Ok(()) + } + pub fn outpoint_to_entry_insert(&self, value: &OutPointValue, entry: &[u8]) -> crate::Result<()> { + let mut table = self.outpoint_to_entry.borrow_mut(); + table.insert(value, entry)?; + Ok(()) + } + pub fn transaction_id_to_transaction_insert( + &self, + tx_id: &TxidValue, + value: &[u8], + ) -> crate::Result<()> { + let mut table = self.transaction_id_to_transaction.borrow_mut(); + table.insert(tx_id, value)?; + Ok(()) + } + pub fn outpoint_to_sat_ranges_insert( + &self, + value: &OutPointValue, + data: &[u8], + ) -> crate::Result<()> { + let mut table = self.outpoint_to_sat_ranges.borrow_mut(); + table.insert(value, data)?; + Ok(()) + } + pub fn outpoint_to_sat_ranges_remove(&self, k: &OutPointValue) -> crate::Result>> { + let mut table = self.outpoint_to_sat_ranges.borrow_mut(); + let ret: Vec = table + .remove(k)? + .map(|ranges| ranges.value().to_vec()) + .unwrap_or_default(); + return Ok(Some(ret)); + } + pub fn satpoint_to_sequence_number_remove_all(&self, v: &SatPointValue) -> crate::Result<()> { + let mut table = self.satpoint_to_sequence_number.borrow_mut(); + table.remove_all(v)?; + Ok(()) + } + pub fn sat_to_satpoint_insert(&self, key: &u64, value: &SatPointValue) -> crate::Result<()> { + let mut table = self.sat_to_satpoint.borrow_mut(); + table.insert(key, value)?; + Ok(()) + } - pub fn save_traces(&self, tx_id: &Txid) -> crate::Result<()> { - let mut traces = self.traces.borrow_mut(); - let insert_traces = traces.clone(); - traces.clear(); - if insert_traces.is_empty() { - return Ok(()); - } - let mut table = self.trace_table.borrow_mut(); - let key = tx_id.store(); - let value=rmp_serde::to_vec(&insert_traces)?; - table.insert(&key, value.as_slice())?; - Ok(()) + pub fn save_traces(&self, tx_id: &Txid) -> crate::Result<()> { + let mut traces = self.traces.borrow_mut(); + let insert_traces = traces.clone(); + traces.clear(); + if insert_traces.is_empty() { + return Ok(()); } -} \ No newline at end of file + let mut table = self.trace_table.borrow_mut(); + let key = tx_id.store(); + let value = rmp_serde::to_vec(&insert_traces)?; + table.insert(&key, value.as_slice())?; + Ok(()) + } +} diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 4109fd4fb8..d5b8ff2065 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -1,58 +1,66 @@ -use std::cell::RefCell; -use std::collections::{HashMap, HashSet, VecDeque}; -use std::marker::PhantomData; -use std::ops::{Deref, DerefMut}; -use std::path::{Path}; -use std::rc::Rc; -use std::sync::Arc; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::thread; +use crate::height::Height; +use crate::index::entry::Entry; +use crate::index::simulator::error::SimulateError; +use crate::index::simulator::processor::{IndexWrapper, StorageProcessor}; +use crate::index::updater::pending_updater::PendingUpdater; +use crate::index::{ + BlockData, InscriptionIdValue, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, + BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, + COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, + INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, + OUTPOINT_TO_SAT_RANGES, SATPOINT_TO_SEQUENCE_NUMBER, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, + SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, + SIMULATE_TRACE_TABLE, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION, +}; +use crate::okx::datastore::brc20::redb::table::get_transaction_receipts; +use crate::okx::datastore::brc20::{Brc20Reader, Receipt}; +use crate::okx::datastore::cache::CacheTableIndex; +use crate::okx::datastore::ord::InscriptionOp; +use crate::okx::lru::SimpleLru; +use crate::okx::protocol::simulate::SimulateContext; +use crate::okx::protocol::trace::TraceNode; +use crate::okx::protocol::{ProtocolConfig, ProtocolManager}; +use crate::{Index, Options, Sat, SatPoint}; use anyhow::anyhow; -use bitcoin::{Block, OutPoint, Transaction, Txid, TxOut}; +use bitcoin::{Block, OutPoint, Transaction, TxOut, Txid}; use indexer_sdk::client::drect::DirectClient; use indexer_sdk::client::event::ClientEvent; -use indexer_sdk::client::{SyncClient}; +use indexer_sdk::client::SyncClient; use indexer_sdk::configuration::base::{IndexerConfiguration, NetConfiguration, ZMQConfiguration}; -use indexer_sdk::factory::common::{sync_create_and_start_processor}; +use indexer_sdk::factory::common::sync_create_and_start_processor; use indexer_sdk::storage::db::memory::MemoryDB; use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; use indexer_sdk::wait_exit_signal; use log::{error, info}; use redb::{Database, ReadableTable, RedbValue, WriteTransaction}; +use std::cell::RefCell; +use std::collections::{HashMap, HashSet, VecDeque}; +use std::marker::PhantomData; +use std::ops::{Deref, DerefMut}; +use std::path::Path; +use std::rc::Rc; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; +use std::thread; use tokio::runtime::Runtime; use tokio::sync::watch; use tokio::task::JoinHandle; -use crate::{Index, Options, Sat, SatPoint}; -use crate::height::Height; -use crate::index::{BlockData, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, HOME_INSCRIPTIONS, INSCRIPTION_ID_TO_SEQUENCE_NUMBER, INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, InscriptionIdValue, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, OUTPOINT_TO_SAT_RANGES, SAT_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, SATPOINT_TO_SEQUENCE_NUMBER, SEQUENCE_NUMBER_TO_CHILDREN, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, SEQUENCE_NUMBER_TO_SATPOINT, SIMULATE_TRACE_TABLE, STATISTIC_TO_COUNT, TRANSACTION_ID_TO_TRANSACTION}; -use crate::index::entry::Entry; -use crate::index::simulator::error::SimulateError; -use crate::index::simulator::processor::{IndexWrapper, StorageProcessor}; -use crate::index::updater::pending_updater::PendingUpdater; -use crate::okx::datastore::brc20::{Brc20Reader, Receipt}; -use crate::okx::datastore::brc20::redb::table::get_transaction_receipts; -use crate::okx::datastore::cache::CacheTableIndex; -use crate::okx::datastore::ord::InscriptionOp; -use crate::okx::lru::SimpleLru; -use crate::okx::protocol::{ProtocolConfig, ProtocolManager}; -use crate::okx::protocol::simulate::SimulateContext; -use crate::okx::protocol::trace::TraceNode; pub struct Simulator<'a, 'db, 'tx> { - pub internal_index: IndexWrapper, - pub client: Option>>>, - _marker_a: PhantomData<&'a ()>, - _marker_b: PhantomData<&'db ()>, - _marker_tx: PhantomData<&'tx ()>, + pub internal_index: IndexWrapper, + pub client: Option>>>, + _marker_a: PhantomData<&'a ()>, + _marker_b: PhantomData<&'db ()>, + _marker_tx: PhantomData<&'tx ()>, } #[derive(Clone)] pub struct SimulatorServer { - tx_out_cache: Rc>>, - pub internal_index: IndexWrapper, - pub simulate_index: Arc, - pub client: DirectClient>>, + tx_out_cache: Rc>>, + pub internal_index: IndexWrapper, + pub simulate_index: Arc, + pub client: DirectClient>>, } unsafe impl Send for SimulatorServer {} @@ -60,632 +68,715 @@ unsafe impl Send for SimulatorServer {} unsafe impl Sync for SimulatorServer {} impl SimulatorServer { - pub async fn start(&self, exit: watch::Receiver<()>) -> JoinHandle<()> { - let internal = self.clone(); - tokio::spawn(async move { - internal.on_start(exit).await; - }) - } - async fn on_start(self, mut exit: watch::Receiver<()>) { - loop { - tokio::select! { - event=self.get_client_event()=>{ - match event{ - Ok(event) => { - if let Err(e)= self.handle_event(&event).await{ - log::error!("handle event error: {:?}", e); - } - } - Err(e) => { - log::error!("receive event error: {:?}", e); - break; - } - } - }, - _ = exit.changed() => { - info!("simulator receive exit signal, exit."); - break; + pub async fn start(&self, exit: watch::Receiver<()>) -> JoinHandle<()> { + let internal = self.clone(); + tokio::spawn(async move { + internal.on_start(exit).await; + }) + } + async fn on_start(self, mut exit: watch::Receiver<()>) { + loop { + tokio::select! { + event=self.get_client_event()=>{ + match event{ + Ok(event) => { + if let Err(e)= self.handle_event(&event).await{ + log::error!("handle event error: {:?}", e); + } } - } - } + Err(e) => { + log::error!("receive event error: {:?}", e); + break; + } + } + }, + _ = exit.changed() => { + info!("simulator receive exit signal, exit."); + break; + } + } } - - fn get_current_height(&self) -> crate::Result { - let height = self.internal_index.internal.block_height()?.unwrap_or(Height(0)); - Ok(height.0) + } + + fn get_current_height(&self) -> crate::Result { + let height = self + .internal_index + .internal + .block_height()? + .unwrap_or(Height(0)); + Ok(height.0) + } + async fn handle_event(&self, event: &ClientEvent) -> crate::Result<()> { + info!("sim receive event:{:?}", event); + match event { + ClientEvent::Transaction(tx) => { + self.execute_tx(tx, true)?; + } + ClientEvent::GetHeight => { + let height = self.get_current_height()?; + self.client.report_height(height)?; + } + ClientEvent::TxDroped(tx) => { + let tx = tx.clone().into(); + self.remove_tx_traces(&tx)?; + } + ClientEvent::TxConfirmed(tx) => { + let tx = tx.clone().into(); + self.remove_tx_traces(&tx)?; + } } - async fn handle_event(&self, event: &ClientEvent) -> crate::Result<()> { - info!("sim receive event:{:?}", event); - match event { - ClientEvent::Transaction(tx) => { - self.execute_tx(tx, true)?; - } - ClientEvent::GetHeight => { - let height = self.get_current_height()?; - self.client.report_height(height)?; - } - ClientEvent::TxDroped(tx) => { - let tx = tx.clone().into(); - self.remove_tx_traces(&tx)?; - } - ClientEvent::TxConfirmed(tx) => { - let tx = tx.clone().into(); - self.remove_tx_traces(&tx)?; - } - } - Ok(()) + Ok(()) + } + fn remove_tx_traces(&self, txid: &Txid) -> crate::Result<()> { + let wtx = self.simulate_index.begin_write()?; + let commit = self.do_remove_traces(txid, &wtx)?; + if commit { + wtx.commit()?; } - fn remove_tx_traces(&self, txid: &Txid) -> crate::Result<()> { - let wtx = self.simulate_index.begin_write()?; - let commit = self.do_remove_traces(txid, &wtx)?; - if commit { - wtx.commit()?; - } - Ok(()) + Ok(()) + } + fn do_remove_traces(&self, txid: &Txid, wtx: &WriteTransaction) -> crate::Result { + let traces_table = wtx.open_table(SIMULATE_TRACE_TABLE)?; + let value = txid.store(); + let traces = traces_table.get(&value)?; + if traces.is_none() { + return Ok(false); } - fn do_remove_traces(&self, txid: &Txid, wtx: &WriteTransaction) -> crate::Result { - let traces_table = wtx.open_table(SIMULATE_TRACE_TABLE)?; - let value = txid.store(); - let traces = traces_table.get(&value)?; - if traces.is_none() { - return Ok(false); - } - let mut brc20_balances = wtx.open_table(BRC20_BALANCES)?; - let mut brc20_token = wtx.open_table(BRC20_TOKEN)?; - let mut events = wtx.open_table(BRC20_EVENTS)?; - let mut brc20_transferlog = wtx.open_table(BRC20_TRANSFERABLELOG)?; - let mut brc20_inscribe_transfer = wtx.open_table(BRC20_INSCRIBE_TRANSFER)?; - let mut ord_tx_id_to_operations = wtx.open_table(ORD_TX_TO_OPERATIONS)?; - let mut collections_key_to_inscription_id = wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?; - let mut collection_inscription_id_to_kinds = wtx.open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?; - let binding = traces.unwrap(); - let traces = binding.value(); - let traces: Vec = rmp_serde::from_slice(traces)?; - for node in traces { - let key = node.key; - match node.trace_type { - CacheTableIndex::TXID_TO_INSCRIPTION_RECEIPTS => {} - CacheTableIndex::SEQUENCE_NUMBER_TO_SATPOINT => {} - CacheTableIndex::SAT_TO_SEQUENCE_NUMBER => {} - CacheTableIndex::HOME_INSCRIPTIONS => {} - CacheTableIndex::INSCRIPTION_ID_TO_SEQUENCE_NUMBER => {} - CacheTableIndex::SEQUENCE_NUMBER_TO_CHILDREN => {} - CacheTableIndex::SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY => {} - CacheTableIndex::INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER => {} - CacheTableIndex::OUTPOINT_TO_ENTRY => {} - CacheTableIndex::BRC20_BALANCES => { - let key = String::from_utf8(key).unwrap(); - let key = key.as_str(); - brc20_balances.remove(key)?; - } - CacheTableIndex::BRC20_TOKEN => { - let key = String::from_utf8(key).unwrap(); - let key = key.as_str(); - brc20_token.remove(key)?; - } - CacheTableIndex::BRC20_EVENTS => { - let key = key.as_slice(); - let key: &Txid = &rmp_serde::from_slice(key).unwrap(); - events.remove(&key.store())?; - } - CacheTableIndex::BRC20_TRANSFERABLELOG => { - let key = String::from_utf8(key).unwrap(); - brc20_transferlog.remove(key.as_str())?; - } - CacheTableIndex::BRC20_INSCRIBE_TRANSFER => { - let key = InscriptionIdValue::from_bytes(key.as_slice()); - brc20_inscribe_transfer.remove(&key)?; - } - CacheTableIndex::ORD_TX_TO_OPERATIONS => { - let key: [u8; 32] = key.as_slice().try_into().unwrap(); - ord_tx_id_to_operations.remove(&key)?; - } - CacheTableIndex::COLLECTIONS_KEY_TO_INSCRIPTION_ID => { - let key = String::from_utf8(key).unwrap(); - collections_key_to_inscription_id.remove(key.as_str())?; - } - CacheTableIndex::COLLECTIONS_INSCRIPTION_ID_TO_KINDS => { - let key = InscriptionIdValue::from_bytes(&key); - collection_inscription_id_to_kinds.remove(&key)?; - } - } + let mut brc20_balances = wtx.open_table(BRC20_BALANCES)?; + let mut brc20_token = wtx.open_table(BRC20_TOKEN)?; + let mut events = wtx.open_table(BRC20_EVENTS)?; + let mut brc20_transferlog = wtx.open_table(BRC20_TRANSFERABLELOG)?; + let mut brc20_inscribe_transfer = wtx.open_table(BRC20_INSCRIBE_TRANSFER)?; + let mut ord_tx_id_to_operations = wtx.open_table(ORD_TX_TO_OPERATIONS)?; + let mut collections_key_to_inscription_id = + wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?; + let mut collection_inscription_id_to_kinds = + wtx.open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?; + let binding = traces.unwrap(); + let traces = binding.value(); + let traces: Vec = rmp_serde::from_slice(traces)?; + for node in traces { + let key = node.key; + match node.trace_type { + CacheTableIndex::TXID_TO_INSCRIPTION_RECEIPTS => {} + CacheTableIndex::SEQUENCE_NUMBER_TO_SATPOINT => {} + CacheTableIndex::SAT_TO_SEQUENCE_NUMBER => {} + CacheTableIndex::HOME_INSCRIPTIONS => {} + CacheTableIndex::INSCRIPTION_ID_TO_SEQUENCE_NUMBER => {} + CacheTableIndex::SEQUENCE_NUMBER_TO_CHILDREN => {} + CacheTableIndex::SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY => {} + CacheTableIndex::INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER => {} + CacheTableIndex::OUTPOINT_TO_ENTRY => {} + CacheTableIndex::BRC20_BALANCES => { + let key = String::from_utf8(key).unwrap(); + let key = key.as_str(); + brc20_balances.remove(key)?; } - Ok(true) - } - async fn get_client_event(&self) -> crate::Result { - let ret = self.client.block_get_event()?; - Ok(ret) - } - pub fn execute_tx(&self, tx: &Transaction, commit: bool) -> crate::Result, SimulateError> { - let wtx = self.simulate_index.begin_write()?; - let traces = Rc::new(RefCell::new(vec![])); - let ret = self.simulate_tx(tx, &wtx, traces)?; - if commit { - wtx.commit()?; + CacheTableIndex::BRC20_TOKEN => { + let key = String::from_utf8(key).unwrap(); + let key = key.as_str(); + brc20_token.remove(key)?; } - - Ok(ret) - } - - pub fn get_receipt(&self, tx_id: Txid) -> Result, anyhow::Error> { - let rx = self.simulate_index.begin_read()?; - let tab = rx.open_table(BRC20_EVENTS)?; - let ret = get_transaction_receipts(&tab, &tx_id)?; - Ok(ret) - } - fn simulate_tx(&self, tx: &Transaction, wtx: &WriteTransaction, traces: Rc>>) -> crate::Result, SimulateError> { - let brc20_receipts = Rc::new(RefCell::new(vec![])); - let height = self.get_current_height()?; - let block = self.internal_index.internal.get_block_by_height(height)?.unwrap(); - let home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS).unwrap(); - let inscription_id_to_sequence_number = - wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); - let inscription_number_to_sequence_number = - wtx.open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER).unwrap(); - let sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); - let satpoint_to_sequence_number = wtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER).unwrap(); - let sequence_number_to_children = wtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN).unwrap(); - let sequence_number_to_inscription_entry = - Rc::new(RefCell::new(wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap())); - let sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); - let transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); - let outpoint_to_entry = Rc::new(RefCell::new(wtx.open_table(OUTPOINT_TO_ENTRY).unwrap())); - let outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); - let sat_to_point = wtx.open_table(SAT_TO_SATPOINT).unwrap(); - let statis_to_count = wtx.open_table(STATISTIC_TO_COUNT).unwrap(); - let traces_table = wtx.open_table(SIMULATE_TRACE_TABLE)?; - - let h = height; - let ts = block.header.time; - let ctx = SimulateContext { - network: self.internal_index.internal.get_chain_network().clone(), - current_height: h, - current_block_time: ts as u32, - internal_index: self.internal_index.clone(), - ORD_TX_TO_OPERATIONS: Rc::new(RefCell::new(wtx.open_table(crate::index::ORD_TX_TO_OPERATIONS)?)), - COLLECTIONS_KEY_TO_INSCRIPTION_ID: Rc::new(RefCell::new(wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?)), - COLLECTIONS_INSCRIPTION_ID_TO_KINDS: Rc::new(RefCell::new(wtx - .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?)), - SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: sequence_number_to_inscription_entry.clone(), - OUTPOINT_TO_ENTRY: outpoint_to_entry.clone(), - BRC20_BALANCES: Rc::new(RefCell::new(wtx.open_table(BRC20_BALANCES)?)), - BRC20_TOKEN: Rc::new(RefCell::new(wtx.open_table(BRC20_TOKEN)?)), - BRC20_EVENTS: Rc::new(RefCell::new(wtx.open_table(BRC20_EVENTS)?)), - BRC20_TRANSFERABLELOG: Rc::new(RefCell::new(wtx.open_table(BRC20_TRANSFERABLELOG)?)), - BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new(wtx.open_table(BRC20_INSCRIBE_TRANSFER)?)), - traces: traces.clone(), - brc20_receipts: brc20_receipts.clone(), - _marker_a: Default::default(), - }; - - let db_receipts = ctx.get_transaction_receipts(&tx.txid())?; - if db_receipts.len() > 0 { - info!("tx:{:?} already simulated",tx.txid()); - return Ok(db_receipts); + CacheTableIndex::BRC20_EVENTS => { + let key = key.as_slice(); + let key: &Txid = &rmp_serde::from_slice(key).unwrap(); + events.remove(&key.store())?; } - - let processor = StorageProcessor { - internal: self.internal_index.clone(), - // wtx: &mut wtx, - home_inscriptions: Rc::new(RefCell::new(home_inscriptions)), - id_to_sequence_number: Rc::new(RefCell::new(inscription_id_to_sequence_number)), - inscription_number_to_sequence_number: Rc::new(RefCell::new(inscription_number_to_sequence_number)), - outpoint_to_entry, - transaction_id_to_transaction: Rc::new(RefCell::new(transaction_id_to_transaction)), - sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), - satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), - sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), - sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), - sequence_number_to_inscription_entry, - outpoint_to_sat_ranges: Rc::new(RefCell::new(outpoint_to_sat_ranges)), - sat_to_satpoint: Rc::new(RefCell::new(sat_to_point)), - statistic_to_count: Rc::new(RefCell::new(statis_to_count)), - trace_table: Rc::new(RefCell::new(traces_table)), - _marker_a: Default::default(), - client: Some(self.client.clone()), - traces: traces.clone(), - context: ctx, - }; - - self.loop_simulate_tx(h, &block, &processor, &tx)?; - let ret = brc20_receipts.borrow(); - let ret = ret.deref().clone(); - Ok(ret) - } - pub fn loop_simulate_tx(&self, h: u32, block: &Block, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(), SimulateError> { - let tx_id = tx.txid(); - let mut need_handle_first = vec![]; - for input in &tx.input { - if input.previous_output.is_null() { - continue; - } - let prev_tx_id = &input.previous_output.txid; - let prev_out = processor.get_txout_by_outpoint(&input.previous_output)?; - if prev_out.is_none() { - need_handle_first.push(prev_tx_id.clone()); - } + CacheTableIndex::BRC20_TRANSFERABLELOG => { + let key = String::from_utf8(key).unwrap(); + brc20_transferlog.remove(key.as_str())?; } - if need_handle_first.is_empty() { - info!("parent suits is ready,start to simulate tx:{:?}",&tx_id); + CacheTableIndex::BRC20_INSCRIBE_TRANSFER => { + let key = InscriptionIdValue::from_bytes(key.as_slice()); + brc20_inscribe_transfer.remove(&key)?; } - for (index, parent) in need_handle_first.iter().enumerate() { - let parent_tx = processor.get_transaction(parent)?; - if parent_tx.is_none() { - error!("parent tx not exist,tx_hash:{:?},child_hash:{:?}",*parent,&tx_id); - return Err(SimulateError::TxNotFound(parent.clone())); - } - let parent_tx = parent_tx.unwrap(); - info!("parent tx :{:?},exist,but not in utxo data,child_hash:{:?},need to simulate parent tx",&parent,&tx_id); - self.loop_simulate_tx(h, block, processor, &parent_tx)?; - if index == need_handle_first.len() - 1 { - info!("all parent txs {:?} simulate done,start to simulate child_hash:{:?}",&need_handle_first,&tx_id); - } else { - info!("parent tx {:?} simulate done,start to simulate next parent:{:?}",&parent,need_handle_first[index+1]); - } + CacheTableIndex::ORD_TX_TO_OPERATIONS => { + let key: [u8; 32] = key.as_slice().try_into().unwrap(); + ord_tx_id_to_operations.remove(&key)?; } - self.do_simulate_tx(h, block, processor, &tx)?; - - Ok(()) + CacheTableIndex::COLLECTIONS_KEY_TO_INSCRIPTION_ID => { + let key = String::from_utf8(key).unwrap(); + collections_key_to_inscription_id.remove(key.as_str())?; + } + CacheTableIndex::COLLECTIONS_INSCRIPTION_ID_TO_KINDS => { + let key = InscriptionIdValue::from_bytes(&key); + collection_inscription_id_to_kinds.remove(&key)?; + } + } + } + Ok(true) + } + async fn get_client_event(&self) -> crate::Result { + let ret = self.client.block_get_event()?; + Ok(ret) + } + pub fn execute_tx( + &self, + tx: &Transaction, + commit: bool, + ) -> crate::Result, SimulateError> { + let wtx = self.simulate_index.begin_write()?; + let traces = Rc::new(RefCell::new(vec![])); + let ret = self.simulate_tx(tx, &wtx, traces)?; + if commit { + wtx.commit()?; } - pub fn do_simulate_tx(&self, h: u32, block: &Block, processor: &StorageProcessor, tx: &Transaction) -> crate::Result<(), SimulateError> { - let mut sim = Simulator { - internal_index: self.internal_index.clone(), - client: None, - _marker_a: Default::default(), - _marker_b: Default::default(), - _marker_tx: Default::default(), - }; - let height = h; - let block = block.clone(); - let mut cache = self.tx_out_cache.borrow_mut(); - let cache = cache.deref_mut(); - - let mut operations: HashMap> = HashMap::new(); - let block = BlockData { - header: block.header, - txdata: vec![(tx.clone(), tx.txid())], - }; - sim.index_block(block.clone(), height, cache, &processor, &mut operations)?; - processor.save_traces(&tx.txid())?; + Ok(ret) + } + + pub fn get_receipt(&self, tx_id: Txid) -> Result, anyhow::Error> { + let rx = self.simulate_index.begin_read()?; + let tab = rx.open_table(BRC20_EVENTS)?; + let ret = get_transaction_receipts(&tab, &tx_id)?; + Ok(ret) + } + fn simulate_tx( + &self, + tx: &Transaction, + wtx: &WriteTransaction, + traces: Rc>>, + ) -> crate::Result, SimulateError> { + let brc20_receipts = Rc::new(RefCell::new(vec![])); + let height = self.get_current_height()?; + let block = self + .internal_index + .internal + .get_block_by_height(height)? + .unwrap(); + let home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS).unwrap(); + let inscription_id_to_sequence_number = + wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); + let inscription_number_to_sequence_number = wtx + .open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER) + .unwrap(); + let sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); + let satpoint_to_sequence_number = wtx + .open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER) + .unwrap(); + let sequence_number_to_children = wtx + .open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN) + .unwrap(); + let sequence_number_to_inscription_entry = Rc::new(RefCell::new( + wtx + .open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY) + .unwrap(), + )); + let sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); + let transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); + let outpoint_to_entry = Rc::new(RefCell::new(wtx.open_table(OUTPOINT_TO_ENTRY).unwrap())); + let outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); + let sat_to_point = wtx.open_table(SAT_TO_SATPOINT).unwrap(); + let statis_to_count = wtx.open_table(STATISTIC_TO_COUNT).unwrap(); + let traces_table = wtx.open_table(SIMULATE_TRACE_TABLE)?; + + let h = height; + let ts = block.header.time; + let ctx = SimulateContext { + network: self.internal_index.internal.get_chain_network().clone(), + current_height: h, + current_block_time: ts as u32, + internal_index: self.internal_index.clone(), + ORD_TX_TO_OPERATIONS: Rc::new(RefCell::new( + wtx.open_table(crate::index::ORD_TX_TO_OPERATIONS)?, + )), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: Rc::new(RefCell::new( + wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID)?, + )), + COLLECTIONS_INSCRIPTION_ID_TO_KINDS: Rc::new(RefCell::new( + wtx.open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS)?, + )), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: sequence_number_to_inscription_entry.clone(), + OUTPOINT_TO_ENTRY: outpoint_to_entry.clone(), + BRC20_BALANCES: Rc::new(RefCell::new(wtx.open_table(BRC20_BALANCES)?)), + BRC20_TOKEN: Rc::new(RefCell::new(wtx.open_table(BRC20_TOKEN)?)), + BRC20_EVENTS: Rc::new(RefCell::new(wtx.open_table(BRC20_EVENTS)?)), + BRC20_TRANSFERABLELOG: Rc::new(RefCell::new(wtx.open_table(BRC20_TRANSFERABLELOG)?)), + BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new(wtx.open_table(BRC20_INSCRIBE_TRANSFER)?)), + traces: traces.clone(), + brc20_receipts: brc20_receipts.clone(), + _marker_a: Default::default(), + }; - Ok(()) + let db_receipts = ctx.get_transaction_receipts(&tx.txid())?; + if db_receipts.len() > 0 { + info!("tx:{:?} already simulated", tx.txid()); + return Ok(db_receipts); } - pub fn new(path: impl AsRef, internal_index: Arc, client: DirectClient>>) -> crate::Result { - let simulate_index = Database::create(path)?; - let simulate_index = Arc::new(simulate_index); - Ok(Self { tx_out_cache: Rc::new(RefCell::new(SimpleLru::new(500))), internal_index: IndexWrapper::new(internal_index), simulate_index, client }) + let processor = StorageProcessor { + internal: self.internal_index.clone(), + // wtx: &mut wtx, + home_inscriptions: Rc::new(RefCell::new(home_inscriptions)), + id_to_sequence_number: Rc::new(RefCell::new(inscription_id_to_sequence_number)), + inscription_number_to_sequence_number: Rc::new(RefCell::new( + inscription_number_to_sequence_number, + )), + outpoint_to_entry, + transaction_id_to_transaction: Rc::new(RefCell::new(transaction_id_to_transaction)), + sat_to_sequence_number: Rc::new(RefCell::new(sat_to_sequence_number)), + satpoint_to_sequence_number: Rc::new(RefCell::new(satpoint_to_sequence_number)), + sequence_number_to_children: Rc::new(RefCell::new(sequence_number_to_children)), + sequence_number_to_satpoint: Rc::new(RefCell::new(sequence_number_to_satpoint)), + sequence_number_to_inscription_entry, + outpoint_to_sat_ranges: Rc::new(RefCell::new(outpoint_to_sat_ranges)), + sat_to_satpoint: Rc::new(RefCell::new(sat_to_point)), + statistic_to_count: Rc::new(RefCell::new(statis_to_count)), + trace_table: Rc::new(RefCell::new(traces_table)), + _marker_a: Default::default(), + client: Some(self.client.clone()), + traces: traces.clone(), + context: ctx, + }; + + self.loop_simulate_tx(h, &block, &processor, &tx)?; + let ret = brc20_receipts.borrow(); + let ret = ret.deref().clone(); + Ok(ret) + } + pub fn loop_simulate_tx( + &self, + h: u32, + block: &Block, + processor: &StorageProcessor, + tx: &Transaction, + ) -> crate::Result<(), SimulateError> { + let tx_id = tx.txid(); + let mut need_handle_first = vec![]; + for input in &tx.input { + if input.previous_output.is_null() { + continue; + } + let prev_tx_id = &input.previous_output.txid; + let prev_out = processor.get_txout_by_outpoint(&input.previous_output)?; + if prev_out.is_none() { + need_handle_first.push(prev_tx_id.clone()); + } + } + if need_handle_first.is_empty() { + info!("parent suits is ready,start to simulate tx:{:?}", &tx_id); } + for (index, parent) in need_handle_first.iter().enumerate() { + let parent_tx = processor.get_transaction(parent)?; + if parent_tx.is_none() { + error!( + "parent tx not exist,tx_hash:{:?},child_hash:{:?}", + *parent, &tx_id + ); + return Err(SimulateError::TxNotFound(parent.clone())); + } + let parent_tx = parent_tx.unwrap(); + info!( + "parent tx :{:?},exist,but not in utxo data,child_hash:{:?},need to simulate parent tx", + &parent, &tx_id + ); + self.loop_simulate_tx(h, block, processor, &parent_tx)?; + if index == need_handle_first.len() - 1 { + info!( + "all parent txs {:?} simulate done,start to simulate child_hash:{:?}", + &need_handle_first, &tx_id + ); + } else { + info!( + "parent tx {:?} simulate done,start to simulate next parent:{:?}", + &parent, + need_handle_first[index + 1] + ); + } + } + self.do_simulate_tx(h, block, processor, &tx)?; + + Ok(()) + } + + pub fn do_simulate_tx( + &self, + h: u32, + block: &Block, + processor: &StorageProcessor, + tx: &Transaction, + ) -> crate::Result<(), SimulateError> { + let mut sim = Simulator { + internal_index: self.internal_index.clone(), + client: None, + _marker_a: Default::default(), + _marker_b: Default::default(), + _marker_tx: Default::default(), + }; + let height = h; + let block = block.clone(); + let mut cache = self.tx_out_cache.borrow_mut(); + let cache = cache.deref_mut(); + + let mut operations: HashMap> = HashMap::new(); + let block = BlockData { + header: block.header, + txdata: vec![(tx.clone(), tx.txid())], + }; + sim.index_block(block.clone(), height, cache, &processor, &mut operations)?; + processor.save_traces(&tx.txid())?; + + Ok(()) + } + + pub fn new( + path: impl AsRef, + internal_index: Arc, + client: DirectClient>>, + ) -> crate::Result { + let simulate_index = Database::create(path)?; + let simulate_index = Arc::new(simulate_index); + Ok(Self { + tx_out_cache: Rc::new(RefCell::new(SimpleLru::new(500))), + internal_index: IndexWrapper::new(internal_index), + simulate_index, + client, + }) + } } impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { - fn index_block( - &mut self, - block: BlockData, - height: u32, - tx_out_cache: &'a mut SimpleLru, - processor: &StorageProcessor<'a, 'db, 'tx>, - operations: &'a mut HashMap>, - ) -> crate::Result<()> { - let mut sat_ranges_written = 0; - let mut outputs_in_block = 0; - - - let index_inscriptions = true; - - let fetching_outputs_count = AtomicUsize::new(0); - let total_outputs_count = AtomicUsize::new(0); - let cache_outputs_count = AtomicUsize::new(0); - let miss_outputs_count = AtomicUsize::new(0); - let meet_outputs_count = AtomicUsize::new(0); - if index_inscriptions { - // Send all missing input outpoints to be fetched right away - let txids = block - .txdata - .iter() - .map(|(_, txid)| txid) - .collect::>(); - use rayon::prelude::*; - let tx_outs = block - .txdata - .par_iter() - .flat_map(|(tx, _)| tx.input.par_iter()) - .filter_map(|input| { - total_outputs_count.fetch_add(1, Ordering::Relaxed); - let prev_output = input.previous_output; - // We don't need coinbase input value - if prev_output.is_null() { - None - } else if txids.contains(&prev_output.txid) { - meet_outputs_count.fetch_add(1, Ordering::Relaxed); - None - } else if tx_out_cache.contains(&prev_output) { - cache_outputs_count.fetch_add(1, Ordering::Relaxed); - None - } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output).unwrap() - { - miss_outputs_count.fetch_add(1, Ordering::Relaxed); - Some((prev_output, Some(txout))) - } else { - fetching_outputs_count.fetch_add(1, Ordering::Relaxed); - Some((prev_output, None)) - } - }) - .collect::>(); - for (out_point, value) in tx_outs.into_iter() { - if let Some(tx_out) = value { - tx_out_cache.insert(out_point, tx_out); - } else { - let tx = processor.get_transaction(&out_point.txid)?.unwrap(); - let out = tx.output[out_point.vout as usize].clone(); - let tx_out = TxOut { - value: out.value, - script_pubkey: out.script_pubkey.clone(), - }; - tx_out_cache.insert(out_point, tx_out); - } - } + fn index_block( + &mut self, + block: BlockData, + height: u32, + tx_out_cache: &'a mut SimpleLru, + processor: &StorageProcessor<'a, 'db, 'tx>, + operations: &'a mut HashMap>, + ) -> crate::Result<()> { + let mut sat_ranges_written = 0; + let mut outputs_in_block = 0; + + let index_inscriptions = true; + + let fetching_outputs_count = AtomicUsize::new(0); + let total_outputs_count = AtomicUsize::new(0); + let cache_outputs_count = AtomicUsize::new(0); + let miss_outputs_count = AtomicUsize::new(0); + let meet_outputs_count = AtomicUsize::new(0); + if index_inscriptions { + // Send all missing input outpoints to be fetched right away + let txids = block + .txdata + .iter() + .map(|(_, txid)| txid) + .collect::>(); + use rayon::prelude::*; + let tx_outs = block + .txdata + .par_iter() + .flat_map(|(tx, _)| tx.input.par_iter()) + .filter_map(|input| { + total_outputs_count.fetch_add(1, Ordering::Relaxed); + let prev_output = input.previous_output; + // We don't need coinbase input value + if prev_output.is_null() { + None + } else if txids.contains(&prev_output.txid) { + meet_outputs_count.fetch_add(1, Ordering::Relaxed); + None + } else if tx_out_cache.contains(&prev_output) { + cache_outputs_count.fetch_add(1, Ordering::Relaxed); + None + } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output).unwrap() { + miss_outputs_count.fetch_add(1, Ordering::Relaxed); + Some((prev_output, Some(txout))) + } else { + fetching_outputs_count.fetch_add(1, Ordering::Relaxed); + Some((prev_output, None)) + } + }) + .collect::>(); + for (out_point, value) in tx_outs.into_iter() { + if let Some(tx_out) = value { + tx_out_cache.insert(out_point, tx_out); + } else { + let tx = processor.get_transaction(&out_point.txid)?.unwrap(); + let out = tx.output[out_point.vout as usize].clone(); + let tx_out = TxOut { + value: out.value, + script_pubkey: out.script_pubkey.clone(), + }; + tx_out_cache.insert(out_point, tx_out); } + } + } - let mut lost_sats = processor.get_lost_sats()?; - let cursed_inscription_count = processor.get_cursed_inscription_count()?; - let blessed_inscription_count = processor.get_blessed_inscription_count()?; - let unbound_inscriptions = processor.get_unbound_inscriptions()?; - let next_sequence_number = processor.next_sequence_number()?; - - let mut inscription_updater = PendingUpdater::new( - operations, - blessed_inscription_count, - self.internal_index.internal.options.chain(), - cursed_inscription_count, - height, - self.internal_index.internal.index_transactions, - next_sequence_number, - lost_sats, - block.header.time, - unbound_inscriptions, - tx_out_cache, - processor.clone(), + let mut lost_sats = processor.get_lost_sats()?; + let cursed_inscription_count = processor.get_cursed_inscription_count()?; + let blessed_inscription_count = processor.get_blessed_inscription_count()?; + let unbound_inscriptions = processor.get_unbound_inscriptions()?; + let next_sequence_number = processor.next_sequence_number()?; + + let mut inscription_updater = PendingUpdater::new( + operations, + blessed_inscription_count, + self.internal_index.internal.options.chain(), + cursed_inscription_count, + height, + self.internal_index.internal.index_transactions, + next_sequence_number, + lost_sats, + block.header.time, + unbound_inscriptions, + tx_out_cache, + processor.clone(), + )?; + + let index_sats = true; + if index_sats { + let mut coinbase_inputs = VecDeque::new(); + + let h = Height(height); + if h.subsidy() > 0 { + let start = h.starting_sat(); + coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); + } + + for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { + log::trace!("Indexing transaction {tx_offset}…"); + + let mut input_sat_ranges = VecDeque::new(); + + self.index_transaction_sats( + tx, + *txid, + &mut input_sat_ranges, + &mut sat_ranges_written, + &mut outputs_in_block, + &mut inscription_updater, + index_inscriptions, )?; - let index_sats = true; - if index_sats { - let mut coinbase_inputs = VecDeque::new(); - - let h = Height(height); - if h.subsidy() > 0 { - let start = h.starting_sat(); - coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n())); - } - - for (tx_offset, (tx, txid)) in block.txdata.iter().enumerate().skip(1) { - log::trace!("Indexing transaction {tx_offset}…"); - - let mut input_sat_ranges = VecDeque::new(); - - self.index_transaction_sats( - tx, - *txid, - &mut input_sat_ranges, - &mut sat_ranges_written, - &mut outputs_in_block, - &mut inscription_updater, - index_inscriptions, - )?; - - coinbase_inputs.extend(input_sat_ranges); - } - - if let Some((tx, txid)) = block.txdata.first() { - self.index_transaction_sats( - tx, - *txid, - &mut coinbase_inputs, - &mut sat_ranges_written, - &mut outputs_in_block, - &mut inscription_updater, - index_inscriptions, - )?; - } + coinbase_inputs.extend(input_sat_ranges); + } + + if let Some((tx, txid)) = block.txdata.first() { + self.index_transaction_sats( + tx, + *txid, + &mut coinbase_inputs, + &mut sat_ranges_written, + &mut outputs_in_block, + &mut inscription_updater, + index_inscriptions, + )?; + } + + if !coinbase_inputs.is_empty() { + let mut lost_sat_ranges = processor + .outpoint_to_sat_ranges_remove(&OutPoint::null().store())? + .map(|ranges| ranges.to_vec()) + .unwrap_or_default(); + + for (start, end) in coinbase_inputs { + if !Sat(start).common() { + processor.sat_to_satpoint_insert( + &start, + &SatPoint { + outpoint: OutPoint::null(), + offset: lost_sats, + } + .store(), + )?; + } + + lost_sat_ranges.extend_from_slice(&(start, end).store()); + + lost_sats += end - start; + } + processor + .outpoint_to_sat_ranges_insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; + } + } else if index_inscriptions { + for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { + inscription_updater.index_envelopes(tx, *txid, None)?; + } + } + inscription_updater.flush_cache()?; + + let mut context = processor.create_context()?; + let config = ProtocolConfig::new_with_options(&self.internal_index.internal.options); + ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; + + Ok(()) + } + + fn index_transaction_sats( + &mut self, + tx: &Transaction, + txid: Txid, + input_sat_ranges: &mut VecDeque<(u64, u64)>, + sat_ranges_written: &mut u64, + outputs_traversed: &mut u64, + inscription_updater: &mut PendingUpdater, + index_inscriptions: bool, + ) -> crate::Result { + if index_inscriptions { + inscription_updater.index_envelopes(tx, txid, Some(input_sat_ranges))?; + } - if !coinbase_inputs.is_empty() { - let mut lost_sat_ranges = processor.outpoint_to_sat_ranges_remove(&OutPoint::null().store())?.map(|ranges| ranges.to_vec()) - .unwrap_or_default(); - - for (start, end) in coinbase_inputs { - if !Sat(start).common() { - processor.sat_to_satpoint_insert( - &start, - &SatPoint { - outpoint: OutPoint::null(), - offset: lost_sats, - } - .store(), - )?; - } - - lost_sat_ranges.extend_from_slice(&(start, end).store()); - - lost_sats += end - start; - } - processor.outpoint_to_sat_ranges_insert(&OutPoint::null().store(), lost_sat_ranges.as_slice())?; - } - } else if index_inscriptions { - for (tx, txid) in block.txdata.iter().skip(1).chain(block.txdata.first()) { - inscription_updater.index_envelopes(tx, *txid, None)?; + for (vout, output) in tx.output.iter().enumerate() { + let outpoint = OutPoint { + vout: vout.try_into().unwrap(), + txid, + }; + let mut sats = Vec::new(); + + let mut remaining = output.value; + while remaining > 0 { + let range = input_sat_ranges + .pop_front() + .ok_or_else(|| anyhow!("insufficient inputs for transaction outputs"))?; + + if !Sat(range.0).common() { + inscription_updater.processor.sat_to_satpoint_insert( + &range.0, + &SatPoint { + outpoint, + offset: 0, } + .store(), + )?; } - inscription_updater.flush_cache()?; - let mut context = processor.create_context()?; - let config = ProtocolConfig::new_with_options(&self.internal_index.internal.options); - ProtocolManager::new(config).index_block(&mut context, &block, operations.clone())?; + let count = range.1 - range.0; - Ok(()) - } + let assigned = if count > remaining { + let middle = range.0 + remaining; + input_sat_ranges.push_front((middle, range.1)); + (range.0, middle) + } else { + range + }; - fn index_transaction_sats( - &mut self, - tx: &Transaction, - txid: Txid, - input_sat_ranges: &mut VecDeque<(u64, u64)>, - sat_ranges_written: &mut u64, - outputs_traversed: &mut u64, - inscription_updater: &mut PendingUpdater, - index_inscriptions: bool, - ) -> crate::Result { - if index_inscriptions { - inscription_updater.index_envelopes(tx, txid, Some(input_sat_ranges))?; - } + sats.extend_from_slice(&assigned.store()); - for (vout, output) in tx.output.iter().enumerate() { - let outpoint = OutPoint { - vout: vout.try_into().unwrap(), - txid, - }; - let mut sats = Vec::new(); - - let mut remaining = output.value; - while remaining > 0 { - let range = input_sat_ranges - .pop_front() - .ok_or_else(|| anyhow!("insufficient inputs for transaction outputs"))?; - - if !Sat(range.0).common() { - inscription_updater.processor.sat_to_satpoint_insert( - &range.0, - &SatPoint { - outpoint, - offset: 0, - } - .store(), - )?; - } - - let count = range.1 - range.0; - - let assigned = if count > remaining { - let middle = range.0 + remaining; - input_sat_ranges.push_front((middle, range.1)); - (range.0, middle) - } else { - range - }; - - sats.extend_from_slice(&assigned.store()); - - remaining -= assigned.1 - assigned.0; - - *sat_ranges_written += 1; - } + remaining -= assigned.1 - assigned.0; - *outputs_traversed += 1; - } + *sat_ranges_written += 1; + } - Ok(()) + *outputs_traversed += 1; } + + Ok(()) + } } pub fn start_simulator(ops: Options, internal: Arc) -> Option { - if !ops.simulate_enable { - return None; - } - - let zmq_url = ops.simulate_zmq_url.clone().unwrap(); - let sim_rpc = ops.simulate_bitcoin_rpc_url.clone().unwrap(); - let sim_user = ops.simulate_bitcoin_rpc_user.clone().unwrap(); - let sim_pass = ops.simulate_bitcoin_rpc_pass.clone().unwrap(); - - let config = IndexerConfiguration { - mq: ZMQConfiguration { zmq_url, zmq_topic: vec!["sequence".to_string(), "rawblock".to_string()] }, - net: NetConfiguration { - url: sim_rpc, - username: sim_user, - password: sim_pass, - }, - ..Default::default() - }; - let rt = Runtime::new().unwrap(); - let client = sync_create_and_start_processor(config.clone()); - let (tx, rx) = watch::channel(()); - let server = SimulatorServer::new(ops.simulate_index.unwrap(), internal.clone(), client).unwrap(); - let start_server = server.clone(); - thread::spawn(move || { - rt.block_on(async { - let handler = start_server.start(rx.clone()).await; - wait_exit_signal().await.unwrap(); - tx.send(()).unwrap(); - handler.await.unwrap(); - }); + if !ops.simulate_enable { + return None; + } + + let zmq_url = ops.simulate_zmq_url.clone().unwrap(); + let sim_rpc = ops.simulate_bitcoin_rpc_url.clone().unwrap(); + let sim_user = ops.simulate_bitcoin_rpc_user.clone().unwrap(); + let sim_pass = ops.simulate_bitcoin_rpc_pass.clone().unwrap(); + + let config = IndexerConfiguration { + mq: ZMQConfiguration { + zmq_url, + zmq_topic: vec!["sequence".to_string(), "rawblock".to_string()], + }, + net: NetConfiguration { + url: sim_rpc, + username: sim_user, + password: sim_pass, + }, + ..Default::default() + }; + let rt = Runtime::new().unwrap(); + let client = sync_create_and_start_processor(config.clone()); + let (tx, rx) = watch::channel(()); + let server = SimulatorServer::new(ops.simulate_index.unwrap(), internal.clone(), client).unwrap(); + let start_server = server.clone(); + thread::spawn(move || { + rt.block_on(async { + let handler = start_server.start(rx.clone()).await; + wait_exit_signal().await.unwrap(); + tx.send(()).unwrap(); + handler.await.unwrap(); }); - Some(server) + }); + Some(server) } #[cfg(test)] mod tests { - use std::str::FromStr; - use bitcoincore_rpc::RpcApi; - use indexer_sdk::factory::common::new_client_for_test; - use log::LevelFilter; - use super::*; - - #[ignore] - #[test] - pub fn test_simulate_tx() { - env_logger::builder() - .filter_level(LevelFilter::Debug) - .format_target(false) - .init(); - let opt = create_options(); - let internal = Arc::new(Index::open(&opt).unwrap()); - let client = new_client_for_test("http://localhost:18443".to_string(), "bitcoinrpc".to_string(), "bitcoinrpc".to_string()); - let simulate_server = SimulatorServer::new("./simulate", internal.clone(), client.clone()).unwrap(); - - let client = client.clone().get_btc_client(); - let tx = client.get_raw_transaction(&Txid::from_str("0484a97b4c2134aa02c96731534256e25407fb9592bcc02a5a692796bcf59605").unwrap(), None).unwrap(); - println!("{:?}", tx); - simulate_server.execute_tx(&tx, true).unwrap(); - simulate_server.remove_tx_traces(&tx.txid()).unwrap(); - } - - fn create_options() -> Options { - let opt = crate::options::Options { - log_level: Default::default(), - log_dir: None, - bitcoin_data_dir: None, - bitcoin_rpc_pass: Some("bitcoinrpc".to_string()), - bitcoin_rpc_user: Some("bitcoinrpc".to_string()), - chain_argument: Default::default(), - config: None, - config_dir: None, - cookie_file: None, - data_dir: Default::default(), - db_cache_size: None, - lru_size: 0, - first_inscription_height: None, - height_limit: None, - index: Some(PathBuf::from("./internal")), - index_runes: false, - index_sats: true, - index_transactions: true, - no_index_inscriptions: false, - regtest: true, - rpc_url: None, - signet: false, - testnet: false, - enable_save_ord_receipts: true, - enable_index_bitmap: true, - enable_index_brc20: true, - first_brc20_height: Some(0), - simulate_enable: true, - simulate_zmq_url: Some("tcp://0.0.0.0:28332".to_string()), - simulate_bitcoin_rpc_url: Some("http://localhost:18443".to_string()), - simulate_bitcoin_rpc_pass: Some("bitcoinrpc".to_string()), - simulate_bitcoin_rpc_user: Some("bitcoinrpc".to_string()), - simulate_index: Some("./simulate".to_string().into()), - }; - opt - } + use super::*; + use bitcoincore_rpc::RpcApi; + use indexer_sdk::factory::common::new_client_for_test; + use log::LevelFilter; + use std::str::FromStr; + + #[ignore] + #[test] + pub fn test_simulate_tx() { + env_logger::builder() + .filter_level(LevelFilter::Debug) + .format_target(false) + .init(); + let opt = create_options(); + let internal = Arc::new(Index::open(&opt).unwrap()); + let client = new_client_for_test( + "http://localhost:18443".to_string(), + "bitcoinrpc".to_string(), + "bitcoinrpc".to_string(), + ); + let simulate_server = + SimulatorServer::new("./simulate", internal.clone(), client.clone()).unwrap(); + + let client = client.clone().get_btc_client(); + let tx = client + .get_raw_transaction( + &Txid::from_str("0484a97b4c2134aa02c96731534256e25407fb9592bcc02a5a692796bcf59605") + .unwrap(), + None, + ) + .unwrap(); + println!("{:?}", tx); + simulate_server.execute_tx(&tx, true).unwrap(); + simulate_server.remove_tx_traces(&tx.txid()).unwrap(); + } + + fn create_options() -> Options { + let opt = crate::options::Options { + log_level: Default::default(), + log_dir: None, + bitcoin_data_dir: None, + bitcoin_rpc_pass: Some("bitcoinrpc".to_string()), + bitcoin_rpc_user: Some("bitcoinrpc".to_string()), + chain_argument: Default::default(), + config: None, + config_dir: None, + cookie_file: None, + data_dir: Default::default(), + db_cache_size: None, + lru_size: 0, + first_inscription_height: None, + height_limit: None, + index: Some(PathBuf::from("./internal")), + index_runes: false, + index_sats: true, + index_transactions: true, + no_index_inscriptions: false, + regtest: true, + rpc_url: None, + signet: false, + testnet: false, + enable_save_ord_receipts: true, + enable_index_bitmap: true, + enable_index_brc20: true, + first_brc20_height: Some(0), + simulate_enable: true, + simulate_zmq_url: Some("tcp://0.0.0.0:28332".to_string()), + simulate_bitcoin_rpc_url: Some("http://localhost:18443".to_string()), + simulate_bitcoin_rpc_pass: Some("bitcoinrpc".to_string()), + simulate_bitcoin_rpc_user: Some("bitcoinrpc".to_string()), + simulate_index: Some("./simulate".to_string().into()), + }; + opt + } } diff --git a/src/index/updater.rs b/src/index/updater.rs index f9fe147e74..eb2deea9b5 100644 --- a/src/index/updater.rs +++ b/src/index/updater.rs @@ -11,9 +11,8 @@ use { pub(crate) mod inscription_updater; use crate::okx::lru::SimpleLru; -mod rune_updater; pub mod pending_updater; - +mod rune_updater; #[derive(Clone)] pub(crate) struct BlockData { diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index f00a264ae7..f0d829c09a 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -1,596 +1,610 @@ -use { - super::*, - crate::okx::datastore::ord::operation::{Action, InscriptionOp}, -}; use crate::index::simulator::processor::StorageProcessor; use crate::index::updater::inscription_updater::{Flotsam, Origin}; - +use { + super::*, + crate::okx::datastore::ord::operation::{Action, InscriptionOp}, +}; pub struct PendingUpdater<'a, 'db, 'tx> { - pub processor: StorageProcessor<'a, 'db, 'tx>, - pub(super) operations: &'a mut HashMap>, - pub(super) blessed_inscription_count: u64, - pub(super) chain: Chain, - pub(super) cursed_inscription_count: u64, - pub(super) flotsam: Vec, - pub(super) height: u32, - pub(super) home_inscription_count: u64, - pub(super) index_transactions: bool, - pub(super) next_sequence_number: u32, - pub(super) lost_sats: u64, - pub(super) reward: u64, - pub(super) transaction_buffer: Vec, - pub(super) timestamp: u32, - pub(super) unbound_inscriptions: u64, - pub(super) tx_out_cache: &'a mut SimpleLru, - pub(super) new_outpoints: Vec, + pub processor: StorageProcessor<'a, 'db, 'tx>, + pub(super) operations: &'a mut HashMap>, + pub(super) blessed_inscription_count: u64, + pub(super) chain: Chain, + pub(super) cursed_inscription_count: u64, + pub(super) flotsam: Vec, + pub(super) height: u32, + pub(super) home_inscription_count: u64, + pub(super) index_transactions: bool, + pub(super) next_sequence_number: u32, + pub(super) lost_sats: u64, + pub(super) reward: u64, + pub(super) transaction_buffer: Vec, + pub(super) timestamp: u32, + pub(super) unbound_inscriptions: u64, + pub(super) tx_out_cache: &'a mut SimpleLru, + pub(super) new_outpoints: Vec, } impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { - pub fn new( - operations: &'a mut HashMap>, - blessed_inscription_count: u64, - chain: Chain, - cursed_inscription_count: u64, - height: u32, - index_transactions: bool, - next_sequence_number: u32, - lost_sats: u64, - timestamp: u32, - unbound_inscriptions: u64, - tx_out_cache: &'a mut SimpleLru, - processor: StorageProcessor<'a, 'db, 'tx>, - ) -> Result { - let home_inscriptions_len = processor.home_inscriptions_len(); - Ok(Self { - processor, - operations, - blessed_inscription_count, - chain, - cursed_inscription_count, - flotsam: vec![], - height, - home_inscription_count: home_inscriptions_len, - index_transactions, - next_sequence_number, - lost_sats, - reward: Height(height).subsidy(), - transaction_buffer: vec![], - timestamp, - unbound_inscriptions, - tx_out_cache, - new_outpoints: vec![], - }) - } - pub fn index_envelopes( - &mut self, - tx: &Transaction, - txid: Txid, - input_sat_ranges: Option<&VecDeque<(u64, u64)>>, - ) -> Result { - let mut floating_inscriptions = Vec::new(); - let mut id_counter = 0; - let mut inscribed_offsets = BTreeMap::new(); - let jubilant = self.height >= self.chain.jubilee_height(); - let mut total_input_value = 0; - let total_output_value = tx.output.iter().map(|txout| txout.value).sum::(); - - let envelopes = ParsedEnvelope::from_transaction(tx); - let inscriptions = !envelopes.is_empty(); - let mut envelopes = envelopes.into_iter().peekable(); - - for (input_index, tx_in) in tx.input.iter().enumerate() { - // skip subsidy since no inscriptions possible - if tx_in.previous_output.is_null() { - total_input_value += Height(self.height).subsidy(); - continue; - } + pub fn new( + operations: &'a mut HashMap>, + blessed_inscription_count: u64, + chain: Chain, + cursed_inscription_count: u64, + height: u32, + index_transactions: bool, + next_sequence_number: u32, + lost_sats: u64, + timestamp: u32, + unbound_inscriptions: u64, + tx_out_cache: &'a mut SimpleLru, + processor: StorageProcessor<'a, 'db, 'tx>, + ) -> Result { + let home_inscriptions_len = processor.home_inscriptions_len(); + Ok(Self { + processor, + operations, + blessed_inscription_count, + chain, + cursed_inscription_count, + flotsam: vec![], + height, + home_inscription_count: home_inscriptions_len, + index_transactions, + next_sequence_number, + lost_sats, + reward: Height(height).subsidy(), + transaction_buffer: vec![], + timestamp, + unbound_inscriptions, + tx_out_cache, + new_outpoints: vec![], + }) + } + pub fn index_envelopes( + &mut self, + tx: &Transaction, + txid: Txid, + input_sat_ranges: Option<&VecDeque<(u64, u64)>>, + ) -> Result { + let mut floating_inscriptions = Vec::new(); + let mut id_counter = 0; + let mut inscribed_offsets = BTreeMap::new(); + let jubilant = self.height >= self.chain.jubilee_height(); + let mut total_input_value = 0; + let total_output_value = tx.output.iter().map(|txout| txout.value).sum::(); + + let envelopes = ParsedEnvelope::from_transaction(tx); + let inscriptions = !envelopes.is_empty(); + let mut envelopes = envelopes.into_iter().peekable(); + + for (input_index, tx_in) in tx.input.iter().enumerate() { + // skip subsidy since no inscriptions possible + if tx_in.previous_output.is_null() { + total_input_value += Height(self.height).subsidy(); + continue; + } + + // find existing inscriptions on input (transfers of inscriptions) + for (old_satpoint, inscription_id) in self + .processor + .inscriptions_on_output(&tx_in.previous_output)? + { + let offset = total_input_value + old_satpoint.offset; + floating_inscriptions.push(Flotsam { + txid, + offset, + inscription_id, + old_satpoint, + origin: Origin::Old, + }); + + inscribed_offsets + .entry(offset) + .or_insert((inscription_id, 0)) + .1 += 1; + } + + let offset = total_input_value; + + // multi-level cache for UTXO set to get to the input amount + let current_input_value = if let Some(tx_out) = self.tx_out_cache.get(&tx_in.previous_output) + { + tx_out.value + } else { + panic!("tx_out_cache should have tx_out for input"); + }; + + total_input_value += current_input_value; + + // go through all inscriptions in this input + while let Some(inscription) = envelopes.peek() { + if inscription.input != u32::try_from(input_index).unwrap() { + break; + } + let inscription_id = InscriptionId { + txid, + index: id_counter, + }; - // find existing inscriptions on input (transfers of inscriptions) - for (old_satpoint, inscription_id) in self.processor.inscriptions_on_output(&tx_in.previous_output)? { - let offset = total_input_value + old_satpoint.offset; - floating_inscriptions.push(Flotsam { - txid, - offset, - inscription_id, - old_satpoint, - origin: Origin::Old, - }); - - inscribed_offsets - .entry(offset) - .or_insert((inscription_id, 0)) - .1 += 1; - } + let curse = if inscription.payload.unrecognized_even_field { + Some(crate::index::updater::inscription_updater::Curse::UnrecognizedEvenField) + } else if inscription.payload.duplicate_field { + Some(crate::index::updater::inscription_updater::Curse::DuplicateField) + } else if inscription.payload.incomplete_field { + Some(crate::index::updater::inscription_updater::Curse::IncompleteField) + } else if inscription.input != 0 { + Some(crate::index::updater::inscription_updater::Curse::NotInFirstInput) + } else if inscription.offset != 0 { + Some(crate::index::updater::inscription_updater::Curse::NotAtOffsetZero) + } else if inscription.payload.pointer.is_some() { + Some(crate::index::updater::inscription_updater::Curse::Pointer) + } else if inscription.pushnum { + Some(crate::index::updater::inscription_updater::Curse::Pushnum) + } else if inscription.stutter { + Some(crate::index::updater::inscription_updater::Curse::Stutter) + } else if let Some((id, count)) = inscribed_offsets.get(&offset) { + if *count > 1 { + Some(crate::index::updater::inscription_updater::Curse::Reinscription) + } else { + let initial_inscription_sequence_number = self + .processor + .id_to_sequence_number_get(&id.store())? + .unwrap(); + + let entry = InscriptionEntry::load( + self + .processor + .sequence_number_to_entry_get(initial_inscription_sequence_number)? + .unwrap(), + ); - let offset = total_input_value; + let initial_inscription_was_cursed_or_vindicated = + entry.inscription_number < 0 || Charm::Vindicated.is_set(entry.charms); - // multi-level cache for UTXO set to get to the input amount - let current_input_value = if let Some(tx_out) = self.tx_out_cache.get(&tx_in.previous_output) - { - tx_out.value + if initial_inscription_was_cursed_or_vindicated { + None } else { - panic!("tx_out_cache should have tx_out for input"); - }; - - total_input_value += current_input_value; - - // go through all inscriptions in this input - while let Some(inscription) = envelopes.peek() { - if inscription.input != u32::try_from(input_index).unwrap() { - break; - } - - let inscription_id = InscriptionId { - txid, - index: id_counter, - }; - - let curse = if inscription.payload.unrecognized_even_field { - Some(crate::index::updater::inscription_updater::Curse::UnrecognizedEvenField) - } else if inscription.payload.duplicate_field { - Some(crate::index::updater::inscription_updater::Curse::DuplicateField) - } else if inscription.payload.incomplete_field { - Some(crate::index::updater::inscription_updater::Curse::IncompleteField) - } else if inscription.input != 0 { - Some(crate::index::updater::inscription_updater::Curse::NotInFirstInput) - } else if inscription.offset != 0 { - Some(crate::index::updater::inscription_updater::Curse::NotAtOffsetZero) - } else if inscription.payload.pointer.is_some() { - Some(crate::index::updater::inscription_updater::Curse::Pointer) - } else if inscription.pushnum { - Some(crate::index::updater::inscription_updater::Curse::Pushnum) - } else if inscription.stutter { - Some(crate::index::updater::inscription_updater::Curse::Stutter) - } else if let Some((id, count)) = inscribed_offsets.get(&offset) { - if *count > 1 { - Some(crate::index::updater::inscription_updater::Curse::Reinscription) - } else { - let initial_inscription_sequence_number = - self.processor.id_to_sequence_number_get(&id.store())?.unwrap(); - - - let entry = InscriptionEntry::load(self.processor.sequence_number_to_entry_get(initial_inscription_sequence_number)?.unwrap()); - - let initial_inscription_was_cursed_or_vindicated = - entry.inscription_number < 0 || Charm::Vindicated.is_set(entry.charms); - - if initial_inscription_was_cursed_or_vindicated { - None - } else { - Some(crate::index::updater::inscription_updater::Curse::Reinscription) - } - } - } else { - None - }; - - let unbound = current_input_value == 0 - || curse == Some(crate::index::updater::inscription_updater::Curse::UnrecognizedEvenField) - || inscription.payload.unrecognized_even_field; - - let offset = inscription - .payload - .pointer() - .filter(|&pointer| pointer < total_output_value) - .unwrap_or(offset); - - floating_inscriptions.push(Flotsam { - txid, - inscription_id, - offset, - old_satpoint: SatPoint { - outpoint: tx_in.previous_output, - offset: 0, - }, - origin: Origin::New { - cursed: curse.is_some() && !jubilant, - fee: 0, - hidden: inscription.payload.hidden(), - parent: inscription.payload.parent(), - pointer: inscription.payload.pointer(), - reinscription: inscribed_offsets.get(&offset).is_some(), - unbound, - inscription: inscription.payload.clone(), - vindicated: curse.is_some() && jubilant, - }, - }); - - inscribed_offsets - .entry(offset) - .or_insert((inscription_id, 0)) - .1 += 1; - - envelopes.next(); - id_counter += 1; + Some(crate::index::updater::inscription_updater::Curse::Reinscription) } - } + } + } else { + None + }; + let unbound = current_input_value == 0 + || curse + == Some(crate::index::updater::inscription_updater::Curse::UnrecognizedEvenField) + || inscription.payload.unrecognized_even_field; + + let offset = inscription + .payload + .pointer() + .filter(|&pointer| pointer < total_output_value) + .unwrap_or(offset); + + floating_inscriptions.push(Flotsam { + txid, + inscription_id, + offset, + old_satpoint: SatPoint { + outpoint: tx_in.previous_output, + offset: 0, + }, + origin: Origin::New { + cursed: curse.is_some() && !jubilant, + fee: 0, + hidden: inscription.payload.hidden(), + parent: inscription.payload.parent(), + pointer: inscription.payload.pointer(), + reinscription: inscribed_offsets.get(&offset).is_some(), + unbound, + inscription: inscription.payload.clone(), + vindicated: curse.is_some() && jubilant, + }, + }); + + inscribed_offsets + .entry(offset) + .or_insert((inscription_id, 0)) + .1 += 1; + + envelopes.next(); + id_counter += 1; + } + } - if self.index_transactions && inscriptions { - tx.consensus_encode(&mut self.transaction_buffer) - .expect("in-memory writers don't error"); - self.processor.transaction_id_to_transaction_insert(&txid.store(), self.transaction_buffer.as_slice())?; + if self.index_transactions && inscriptions { + tx.consensus_encode(&mut self.transaction_buffer) + .expect("in-memory writers don't error"); + self + .processor + .transaction_id_to_transaction_insert(&txid.store(), self.transaction_buffer.as_slice())?; - self.transaction_buffer.clear(); - } + self.transaction_buffer.clear(); + } - let potential_parents = floating_inscriptions - .iter() - .map(|flotsam| flotsam.inscription_id) - .collect::>(); - - for flotsam in &mut floating_inscriptions { - if let Flotsam { - origin: Origin::New { parent, .. }, - .. - } = flotsam - { - if let Some(purported_parent) = parent { - if !potential_parents.contains(purported_parent) { - *parent = None; - } - } - } + let potential_parents = floating_inscriptions + .iter() + .map(|flotsam| flotsam.inscription_id) + .collect::>(); + + for flotsam in &mut floating_inscriptions { + if let Flotsam { + origin: Origin::New { parent, .. }, + .. + } = flotsam + { + if let Some(purported_parent) = parent { + if !potential_parents.contains(purported_parent) { + *parent = None; + } } + } + } - // still have to normalize over inscription size - for flotsam in &mut floating_inscriptions { - if let Flotsam { - origin: Origin::New { ref mut fee, .. }, - .. - } = flotsam - { - *fee = (total_input_value - total_output_value) / u64::from(id_counter); - } - } + // still have to normalize over inscription size + for flotsam in &mut floating_inscriptions { + if let Flotsam { + origin: Origin::New { ref mut fee, .. }, + .. + } = flotsam + { + *fee = (total_input_value - total_output_value) / u64::from(id_counter); + } + } - let is_coinbase = tx - .input - .first() - .map(|tx_in| tx_in.previous_output.is_null()) - .unwrap_or_default(); + let is_coinbase = tx + .input + .first() + .map(|tx_in| tx_in.previous_output.is_null()) + .unwrap_or_default(); - if is_coinbase { - floating_inscriptions.append(&mut self.flotsam); - } + if is_coinbase { + floating_inscriptions.append(&mut self.flotsam); + } - floating_inscriptions.sort_by_key(|flotsam| flotsam.offset); - let mut inscriptions = floating_inscriptions.into_iter().peekable(); - - let mut range_to_vout = BTreeMap::new(); - let mut new_locations = Vec::new(); - let mut output_value = 0; - for (vout, tx_out) in tx.output.iter().enumerate() { - let end = output_value + tx_out.value; - - while let Some(flotsam) = inscriptions.peek() { - if flotsam.offset >= end { - break; - } - - let new_satpoint = SatPoint { - outpoint: OutPoint { - txid, - vout: vout.try_into().unwrap(), - }, - offset: flotsam.offset - output_value, - }; - - new_locations.push((new_satpoint, inscriptions.next().unwrap())); - } + floating_inscriptions.sort_by_key(|flotsam| flotsam.offset); + let mut inscriptions = floating_inscriptions.into_iter().peekable(); - range_to_vout.insert((output_value, end), vout.try_into().unwrap()); - - output_value = end; - - #[cfg(not(feature = "cache"))] - self.new_outpoints.push(OutPoint { - vout: vout.try_into().unwrap(), - txid, - }); - self.tx_out_cache.insert( - OutPoint { - vout: vout.try_into().unwrap(), - txid, - }, - tx_out.clone(), - ); - } + let mut range_to_vout = BTreeMap::new(); + let mut new_locations = Vec::new(); + let mut output_value = 0; + for (vout, tx_out) in tx.output.iter().enumerate() { + let end = output_value + tx_out.value; - for (new_satpoint, mut flotsam) in new_locations.into_iter() { - let new_satpoint = match flotsam.origin { - Origin::New { - pointer: Some(pointer), - .. - } if pointer < output_value => { - match range_to_vout.iter().find_map(|((start, end), vout)| { - (pointer >= *start && pointer < *end).then(|| (vout, pointer - start)) - }) { - Some((vout, offset)) => { - flotsam.offset = pointer; - SatPoint { - outpoint: OutPoint { txid, vout: *vout }, - offset, - } - } - _ => new_satpoint, - } - } - _ => new_satpoint, - }; - - self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; + while let Some(flotsam) = inscriptions.peek() { + if flotsam.offset >= end { + break; } - if is_coinbase { - for flotsam in inscriptions { - let new_satpoint = SatPoint { - outpoint: OutPoint::null(), - offset: self.lost_sats + flotsam.offset - output_value, - }; - self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; + let new_satpoint = SatPoint { + outpoint: OutPoint { + txid, + vout: vout.try_into().unwrap(), + }, + offset: flotsam.offset - output_value, + }; + + new_locations.push((new_satpoint, inscriptions.next().unwrap())); + } + + range_to_vout.insert((output_value, end), vout.try_into().unwrap()); + + output_value = end; + + #[cfg(not(feature = "cache"))] + self.new_outpoints.push(OutPoint { + vout: vout.try_into().unwrap(), + txid, + }); + self.tx_out_cache.insert( + OutPoint { + vout: vout.try_into().unwrap(), + txid, + }, + tx_out.clone(), + ); + } + + for (new_satpoint, mut flotsam) in new_locations.into_iter() { + let new_satpoint = match flotsam.origin { + Origin::New { + pointer: Some(pointer), + .. + } if pointer < output_value => { + match range_to_vout.iter().find_map(|((start, end), vout)| { + (pointer >= *start && pointer < *end).then(|| (vout, pointer - start)) + }) { + Some((vout, offset)) => { + flotsam.offset = pointer; + SatPoint { + outpoint: OutPoint { txid, vout: *vout }, + offset, + } } - self.lost_sats += self.reward - output_value; - Ok(()) - } else { - self.flotsam.extend(inscriptions.map(|flotsam| Flotsam { - offset: self.reward + flotsam.offset - output_value, - ..flotsam - })); - self.reward += total_input_value - output_value; - Ok(()) + _ => new_satpoint, + } } + _ => new_satpoint, + }; + + self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; } - // write tx_out to outpoint_to_entry table - pub fn flush_cache(self) -> Result { - let start = Instant::now(); - let persist = self.new_outpoints.len(); - let mut entry = Vec::new(); - for outpoint in self.new_outpoints.into_iter() { - let tx_out = self.tx_out_cache.get(&outpoint).unwrap(); - tx_out.consensus_encode(&mut entry)?; - self.processor.outpoint_to_entry_insert(&outpoint.store(), entry.as_slice())?; - entry.clear(); - } - log::info!( + if is_coinbase { + for flotsam in inscriptions { + let new_satpoint = SatPoint { + outpoint: OutPoint::null(), + offset: self.lost_sats + flotsam.offset - output_value, + }; + self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; + } + self.lost_sats += self.reward - output_value; + Ok(()) + } else { + self.flotsam.extend(inscriptions.map(|flotsam| Flotsam { + offset: self.reward + flotsam.offset - output_value, + ..flotsam + })); + self.reward += total_input_value - output_value; + Ok(()) + } + } + + // write tx_out to outpoint_to_entry table + pub fn flush_cache(self) -> Result { + let start = Instant::now(); + let persist = self.new_outpoints.len(); + let mut entry = Vec::new(); + for outpoint in self.new_outpoints.into_iter() { + let tx_out = self.tx_out_cache.get(&outpoint).unwrap(); + tx_out.consensus_encode(&mut entry)?; + self + .processor + .outpoint_to_entry_insert(&outpoint.store(), entry.as_slice())?; + entry.clear(); + } + log::info!( "flush cache, persist:{}, global:{} cost: {}ms", persist, self.tx_out_cache.len(), start.elapsed().as_millis() ); - Ok(()) + Ok(()) + } + + fn calculate_sat( + input_sat_ranges: Option<&VecDeque<(u64, u64)>>, + input_offset: u64, + ) -> Option { + let input_sat_ranges = input_sat_ranges?; + + let mut offset = 0; + for (start, end) in input_sat_ranges { + let size = end - start; + if offset + size > input_offset { + let n = start + input_offset - offset; + return Some(Sat(n)); + } + offset += size; } - fn calculate_sat( - input_sat_ranges: Option<&VecDeque<(u64, u64)>>, - input_offset: u64, - ) -> Option { - let input_sat_ranges = input_sat_ranges?; - - let mut offset = 0; - for (start, end) in input_sat_ranges { - let size = end - start; - if offset + size > input_offset { - let n = start + input_offset - offset; - return Some(Sat(n)); - } - offset += size; - } - - unreachable!() - } + unreachable!() + } + + fn update_inscription_location( + &mut self, + input_sat_ranges: Option<&VecDeque<(u64, u64)>>, + flotsam: Flotsam, + new_satpoint: SatPoint, + ) -> Result { + let inscription_id = flotsam.inscription_id; + let (unbound, sequence_number) = match flotsam.origin { + Origin::Old => { + self + .processor + .satpoint_to_sequence_number_remove_all(&flotsam.old_satpoint.store())?; + + ( + false, + self + .processor + .id_to_sequence_number_get(&inscription_id.store())? + .unwrap(), + ) + } + Origin::New { + cursed, + fee, + hidden, + parent, + pointer: _, + reinscription, + unbound, + inscription: _, + vindicated, + } => { + let inscription_number = if cursed { + let number: i32 = self.cursed_inscription_count.try_into().unwrap(); + self.cursed_inscription_count += 1; + + // because cursed numbers start at -1 + -(number + 1) + } else { + let number: i32 = self.blessed_inscription_count.try_into().unwrap(); + self.blessed_inscription_count += 1; - fn update_inscription_location( - &mut self, - input_sat_ranges: Option<&VecDeque<(u64, u64)>>, - flotsam: Flotsam, - new_satpoint: SatPoint, - ) -> Result { - let inscription_id = flotsam.inscription_id; - let (unbound, sequence_number) = match flotsam.origin { - Origin::Old => { - self - .processor.satpoint_to_sequence_number_remove_all(&flotsam.old_satpoint.store())?; - - ( - false, - self - .processor.id_to_sequence_number_get( - &inscription_id.store())? - .unwrap() - ) - } - Origin::New { - cursed, - fee, - hidden, - parent, - pointer: _, - reinscription, - unbound, - inscription: _, - vindicated, - } => { - let inscription_number = if cursed { - let number: i32 = self.cursed_inscription_count.try_into().unwrap(); - self.cursed_inscription_count += 1; - - // because cursed numbers start at -1 - -(number + 1) - } else { - let number: i32 = self.blessed_inscription_count.try_into().unwrap(); - self.blessed_inscription_count += 1; - - number - }; - - let sequence_number = self.next_sequence_number; - self.next_sequence_number += 1; - - self - .processor.inscription_number_to_sequence_number_insert( - inscription_number, sequence_number)?; - - let sat = if unbound { - None - } else { - Self::calculate_sat(input_sat_ranges, flotsam.offset) - }; - - let mut charms = 0; - - if cursed { - Charm::Cursed.set(&mut charms); - } - - if reinscription { - Charm::Reinscription.set(&mut charms); - } - - if let Some(sat) = sat { - if sat.nineball() { - Charm::Nineball.set(&mut charms); - } - - if sat.coin() { - Charm::Coin.set(&mut charms); - } - - match sat.rarity() { - Rarity::Common | Rarity::Mythic => {} - Rarity::Uncommon => Charm::Uncommon.set(&mut charms), - Rarity::Rare => Charm::Rare.set(&mut charms), - Rarity::Epic => Charm::Epic.set(&mut charms), - Rarity::Legendary => Charm::Legendary.set(&mut charms), - } - } - - if new_satpoint.outpoint == OutPoint::null() { - Charm::Lost.set(&mut charms); - } - - if unbound { - Charm::Unbound.set(&mut charms); - } - - if vindicated { - Charm::Vindicated.set(&mut charms); - } - - if let Some(Sat(n)) = sat { - self.processor.sat_to_sequence_number_insert(&n, &sequence_number)?; - } - - let parent = match parent { - Some(parent_id) => { - let parent_sequence_number = self - .processor.id_to_sequence_number_get( - &parent_id.store())? - .unwrap(); - self - .processor.sequence_number_to_children_insert( - parent_sequence_number, sequence_number)?; - - Some(parent_sequence_number) - } - None => None, - }; - - self.processor.sequence_number_to_entry_insert( - sequence_number, - &InscriptionEntry { - charms, - fee, - height: self.height, - id: inscription_id, - inscription_number, - parent, - sat, - sequence_number, - timestamp: self.timestamp, - } - .store(), - )?; - - self - .processor.id_to_sequence_number_insert( - &inscription_id.store(), sequence_number)?; - - if !hidden { - self - .processor.home_inscriptions_insert( - &sequence_number, inscription_id.store())?; - - if self.home_inscription_count == 100 { - self.processor.home_inscriptions_pop_first()?; - } else { - self.home_inscription_count += 1; - } - } - - (unbound, sequence_number) - } + number }; - let satpoint = if unbound { - let new_unbound_satpoint = SatPoint { - outpoint: unbound_outpoint(), - offset: self.unbound_inscriptions, - }; - self.unbound_inscriptions += 1; - new_unbound_satpoint.store() + let sequence_number = self.next_sequence_number; + self.next_sequence_number += 1; + + self + .processor + .inscription_number_to_sequence_number_insert(inscription_number, sequence_number)?; + + let sat = if unbound { + None } else { - new_satpoint.store() + Self::calculate_sat(input_sat_ranges, flotsam.offset) }; - self - .operations - .entry(flotsam.txid) - .or_default() - .push(InscriptionOp { - txid: flotsam.txid, - sequence_number, - inscription_number: self - .processor.sequence_number_to_entry_get( - sequence_number)? - .map(|entry| InscriptionEntry::load(entry).inscription_number), - inscription_id: flotsam.inscription_id, - action: match flotsam.origin { - Origin::Old => Action::Transfer, - Origin::New { - cursed, - fee: _, - hidden: _, - parent: _, - pointer: _, - reinscription: _, - unbound, - inscription, - vindicated, - } => Action::New { - cursed, - unbound, - vindicated, - inscription, - }, - }, - old_satpoint: flotsam.old_satpoint, - new_satpoint: Some(Entry::load(satpoint)), - }); + let mut charms = 0; + + if cursed { + Charm::Cursed.set(&mut charms); + } + + if reinscription { + Charm::Reinscription.set(&mut charms); + } + + if let Some(sat) = sat { + if sat.nineball() { + Charm::Nineball.set(&mut charms); + } + + if sat.coin() { + Charm::Coin.set(&mut charms); + } + + match sat.rarity() { + Rarity::Common | Rarity::Mythic => {} + Rarity::Uncommon => Charm::Uncommon.set(&mut charms), + Rarity::Rare => Charm::Rare.set(&mut charms), + Rarity::Epic => Charm::Epic.set(&mut charms), + Rarity::Legendary => Charm::Legendary.set(&mut charms), + } + } + + if new_satpoint.outpoint == OutPoint::null() { + Charm::Lost.set(&mut charms); + } + + if unbound { + Charm::Unbound.set(&mut charms); + } + + if vindicated { + Charm::Vindicated.set(&mut charms); + } + + if let Some(Sat(n)) = sat { + self + .processor + .sat_to_sequence_number_insert(&n, &sequence_number)?; + } + + let parent = match parent { + Some(parent_id) => { + let parent_sequence_number = self + .processor + .id_to_sequence_number_get(&parent_id.store())? + .unwrap(); + self + .processor + .sequence_number_to_children_insert(parent_sequence_number, sequence_number)?; + + Some(parent_sequence_number) + } + None => None, + }; + + self.processor.sequence_number_to_entry_insert( + sequence_number, + &InscriptionEntry { + charms, + fee, + height: self.height, + id: inscription_id, + inscription_number, + parent, + sat, + sequence_number, + timestamp: self.timestamp, + } + .store(), + )?; self - .processor.satpoint_to_sequence_number_insert( - &satpoint, sequence_number)?; - self - .processor.sequence_number_to_satpoint_insert( - sequence_number, &satpoint)?; + .processor + .id_to_sequence_number_insert(&inscription_id.store(), sequence_number)?; + + if !hidden { + self + .processor + .home_inscriptions_insert(&sequence_number, inscription_id.store())?; + + if self.home_inscription_count == 100 { + self.processor.home_inscriptions_pop_first()?; + } else { + self.home_inscription_count += 1; + } + } - Ok(()) - } + (unbound, sequence_number) + } + }; + + let satpoint = if unbound { + let new_unbound_satpoint = SatPoint { + outpoint: unbound_outpoint(), + offset: self.unbound_inscriptions, + }; + self.unbound_inscriptions += 1; + new_unbound_satpoint.store() + } else { + new_satpoint.store() + }; + + self + .operations + .entry(flotsam.txid) + .or_default() + .push(InscriptionOp { + txid: flotsam.txid, + sequence_number, + inscription_number: self + .processor + .sequence_number_to_entry_get(sequence_number)? + .map(|entry| InscriptionEntry::load(entry).inscription_number), + inscription_id: flotsam.inscription_id, + action: match flotsam.origin { + Origin::Old => Action::Transfer, + Origin::New { + cursed, + fee: _, + hidden: _, + parent: _, + pointer: _, + reinscription: _, + unbound, + inscription, + vindicated, + } => Action::New { + cursed, + unbound, + vindicated, + inscription, + }, + }, + old_satpoint: flotsam.old_satpoint, + new_satpoint: Some(Entry::load(satpoint)), + }); + + self + .processor + .satpoint_to_sequence_number_insert(&satpoint, sequence_number)?; + self + .processor + .sequence_number_to_satpoint_insert(sequence_number, &satpoint)?; + + Ok(()) + } } #[test] -pub fn test_asd() {} \ No newline at end of file +pub fn test_asd() {} diff --git a/src/lib.rs b/src/lib.rs index 5067a786c3..18a615efb0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,6 @@ clippy::cast_sign_loss )] - use { self::{ arguments::Arguments, diff --git a/src/okx/datastore/brc20/redb/mod.rs b/src/okx/datastore/brc20/redb/mod.rs index dca4d5a863..6b612bded0 100644 --- a/src/okx/datastore/brc20/redb/mod.rs +++ b/src/okx/datastore/brc20/redb/mod.rs @@ -3,7 +3,11 @@ pub mod table; use super::{LowerTick, ScriptKey, Tick}; use crate::inscriptions::InscriptionId; -pub fn script_tick_id_key(script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> String { +pub fn script_tick_id_key( + script: &ScriptKey, + tick: &Tick, + inscription_id: &InscriptionId, +) -> String { format!( "{}_{}_{}", script, diff --git a/src/okx/datastore/brc20/tick.rs b/src/okx/datastore/brc20/tick.rs index 11643835b1..b38680943a 100644 --- a/src/okx/datastore/brc20/tick.rs +++ b/src/okx/datastore/brc20/tick.rs @@ -4,7 +4,7 @@ use std::{fmt::Formatter, str::FromStr}; pub const TICK_BYTE_COUNT: usize = 4; -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord,Hash)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Tick([u8; TICK_BYTE_COUNT]); impl FromStr for Tick { diff --git a/src/okx/datastore/cache.rs b/src/okx/datastore/cache.rs index 72c026be38..969897ac0a 100644 --- a/src/okx/datastore/cache.rs +++ b/src/okx/datastore/cache.rs @@ -3,22 +3,22 @@ use serde::{Deserialize, Serialize}; #[allow(non_camel_case_types)] #[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] pub enum CacheTableIndex { - TXID_TO_INSCRIPTION_RECEIPTS, + TXID_TO_INSCRIPTION_RECEIPTS, - SEQUENCE_NUMBER_TO_SATPOINT, - SAT_TO_SEQUENCE_NUMBER, - HOME_INSCRIPTIONS, - INSCRIPTION_ID_TO_SEQUENCE_NUMBER, - SEQUENCE_NUMBER_TO_CHILDREN, - SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, - INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, - OUTPOINT_TO_ENTRY, - BRC20_BALANCES, - BRC20_TOKEN, - BRC20_EVENTS, - BRC20_TRANSFERABLELOG, - BRC20_INSCRIBE_TRANSFER, - ORD_TX_TO_OPERATIONS, - COLLECTIONS_KEY_TO_INSCRIPTION_ID, - COLLECTIONS_INSCRIPTION_ID_TO_KINDS, -} \ No newline at end of file + SEQUENCE_NUMBER_TO_SATPOINT, + SAT_TO_SEQUENCE_NUMBER, + HOME_INSCRIPTIONS, + INSCRIPTION_ID_TO_SEQUENCE_NUMBER, + SEQUENCE_NUMBER_TO_CHILDREN, + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, + INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER, + OUTPOINT_TO_ENTRY, + BRC20_BALANCES, + BRC20_TOKEN, + BRC20_EVENTS, + BRC20_TRANSFERABLELOG, + BRC20_INSCRIBE_TRANSFER, + ORD_TX_TO_OPERATIONS, + COLLECTIONS_KEY_TO_INSCRIPTION_ID, + COLLECTIONS_INSCRIPTION_ID_TO_KINDS, +} diff --git a/src/okx/datastore/mod.rs b/src/okx/datastore/mod.rs index 1ea7104fef..8badc6d812 100644 --- a/src/okx/datastore/mod.rs +++ b/src/okx/datastore/mod.rs @@ -1,6 +1,6 @@ pub mod brc20; +pub mod cache; pub mod ord; mod script_key; -pub mod cache; pub use self::script_key::ScriptKey; diff --git a/src/okx/protocol/brc20/msg_executor.rs b/src/okx/protocol/brc20/msg_executor.rs index 4a70c782bf..487588f241 100644 --- a/src/okx/protocol/brc20/msg_executor.rs +++ b/src/okx/protocol/brc20/msg_executor.rs @@ -1,444 +1,437 @@ use super::{ - params::{BIGDECIMAL_TEN, MAXIMUM_SUPPLY, MAX_DECIMAL_WIDTH}, - *, + params::{BIGDECIMAL_TEN, MAXIMUM_SUPPLY, MAX_DECIMAL_WIDTH}, + *, }; +use crate::okx::protocol::ContextTrait; use crate::{ - okx::{ - datastore::brc20::{ - BRC20Error, Balance, DeployEvent, Event, InscripbeTransferEvent, MintEvent, Receipt, Tick, - TokenInfo, TransferEvent, TransferInfo, TransferableLog, - }, - protocol::brc20::{Message, Mint, Operation}, + okx::{ + datastore::brc20::{ + BRC20Error, Balance, DeployEvent, Event, InscripbeTransferEvent, MintEvent, Receipt, Tick, + TokenInfo, TransferEvent, TransferInfo, TransferableLog, }, - Result, + protocol::brc20::{Message, Mint, Operation}, + }, + Result, }; use anyhow::anyhow; use bigdecimal::num_bigint::Sign; use bitcoin::Network; use std::str::FromStr; -use crate::okx::protocol::ContextTrait; #[derive(Debug, Clone, PartialEq)] pub struct ExecutionMessage { - pub(self) txid: Txid, - pub(self) inscription_id: InscriptionId, - pub(self) inscription_number: i32, - pub(self) old_satpoint: SatPoint, - pub(self) new_satpoint: SatPoint, - pub(self) from: ScriptKey, - pub(self) to: Option, - pub(self) op: Operation, + pub(self) txid: Txid, + pub(self) inscription_id: InscriptionId, + pub(self) inscription_number: i32, + pub(self) old_satpoint: SatPoint, + pub(self) new_satpoint: SatPoint, + pub(self) from: ScriptKey, + pub(self) to: Option, + pub(self) op: Operation, } impl ExecutionMessage { - pub fn from_message(context: &mut T, msg: &Message, network: Network) -> Result { - Ok(Self { - txid: msg.txid, - inscription_id: msg.inscription_id, - inscription_number: context.get_inscription_number_by_sequence_number(msg.sequence_number).map_err(|e|{ - anyhow!("failed to get inscription number from state! error: {e}") - })?, - old_satpoint: msg.old_satpoint, - new_satpoint: msg - .new_satpoint - .ok_or(anyhow!("new satpoint cannot be None"))?, - from: context.get_script_key_on_satpoint(&msg.old_satpoint, network).map_err(|e|{ - anyhow!("failed to get script key from state! error: {e}") - })?, - to: if msg.sat_in_outputs { - Some(context.get_script_key_on_satpoint(msg.new_satpoint.as_ref().unwrap(), network).map_err(|e|{ - anyhow!("failed to get script key from state! error: {e}") - })?) - } else { - None - }, - op: msg.op.clone(), - }) - } -} - -pub fn execute(context: &mut T, msg: &ExecutionMessage) -> Result { - log::debug!("BRC20 execute message: {:?}", msg); - let event = match &msg.op { - Operation::Deploy(deploy) => process_deploy(context, msg, deploy.clone()), - Operation::Mint(mint) => process_mint(context, msg, mint.clone()), - Operation::InscribeTransfer(transfer) => { - process_inscribe_transfer(context, msg, transfer.clone()) - } - Operation::Transfer(_) => process_transfer(context, msg), - }; - - let receipt = Receipt { - inscription_id: msg.inscription_id, - inscription_number: msg.inscription_number, - old_satpoint: msg.old_satpoint, - new_satpoint: msg.new_satpoint, - from: msg.from.clone(), - // redirect receiver to sender if transfer to conibase. - to: msg.to.clone().map_or(msg.from.clone(), |v| v), - op: msg.op.op_type(), - result: match event { - Ok(event) => Ok(event), - Err(Error::BRC20Error(e)) => Err(e), - Err(e) => return Err(anyhow!("BRC20 execute exception: {e}")), - }, - }; - - log::debug!("BRC20 message receipt: {:?}", receipt); - Ok(receipt) -} - -fn process_deploy( + pub fn from_message( context: &mut T, - msg: &ExecutionMessage, - deploy: Deploy, -) -> Result { - // ignore inscribe inscription to coinbase. - let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; - - let tick = deploy.tick.parse::()?; - - if let Some(stored_tick_info) = context.get_token_info(&tick).map_err(|e|{ - Error::LedgerError(anyhow!("failed to get token info from database: {}", e)) - })? { - return Err(Error::BRC20Error(BRC20Error::DuplicateTick( - stored_tick_info.tick.to_string(), - ))); - } - - let dec = Num::from_str(&deploy.decimals.map_or(MAX_DECIMAL_WIDTH.to_string(), |v| v))? - .checked_to_u8()?; - if dec > MAX_DECIMAL_WIDTH { - return Err(Error::BRC20Error(BRC20Error::DecimalsTooLarge(dec))); - } - let base = BIGDECIMAL_TEN.checked_powu(u64::from(dec))?; - - let supply = Num::from_str(&deploy.max_supply)?; - - if supply.sign() == Sign::NoSign - || supply > MAXIMUM_SUPPLY.to_owned() - || supply.scale() > i64::from(dec) - { - return Err(Error::BRC20Error(BRC20Error::InvalidSupply( - supply.to_string(), - ))); - } - - let limit = Num::from_str(&deploy.mint_limit.map_or(deploy.max_supply, |v| v))?; - - if limit.sign() == Sign::NoSign - || limit > MAXIMUM_SUPPLY.to_owned() - || limit.scale() > i64::from(dec) - { - return Err(Error::BRC20Error(BRC20Error::MintLimitOutOfRange( - tick.to_lowercase().to_string(), - limit.to_string(), - ))); - } - - let supply = supply.checked_mul(&base)?.checked_to_u128()?; - let limit = limit.checked_mul(&base)?.checked_to_u128()?; - - let new_info = TokenInfo { - inscription_id: msg.inscription_id, - inscription_number: msg.inscription_number, - tick: tick.clone(), - decimal: dec, - supply, - limit_per_mint: limit, - minted: 0u128, - deploy_by: to_script_key, - deployed_number: context.block_height(), - latest_mint_number: context.block_height(), - deployed_timestamp: context.block_time(), - }; - context - .insert_token_info(&tick, &new_info) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to insert token info to database: {}", e)) - })?; - - Ok(Event::Deploy(DeployEvent { - supply, - limit_per_mint: limit, - decimal: dec, - tick: new_info.tick, - })) + msg: &Message, + network: Network, + ) -> Result { + Ok(Self { + txid: msg.txid, + inscription_id: msg.inscription_id, + inscription_number: context + .get_inscription_number_by_sequence_number(msg.sequence_number) + .map_err(|e| anyhow!("failed to get inscription number from state! error: {e}"))?, + old_satpoint: msg.old_satpoint, + new_satpoint: msg + .new_satpoint + .ok_or(anyhow!("new satpoint cannot be None"))?, + from: context + .get_script_key_on_satpoint(&msg.old_satpoint, network) + .map_err(|e| anyhow!("failed to get script key from state! error: {e}"))?, + to: if msg.sat_in_outputs { + Some( + context + .get_script_key_on_satpoint(msg.new_satpoint.as_ref().unwrap(), network) + .map_err(|e| anyhow!("failed to get script key from state! error: {e}"))?, + ) + } else { + None + }, + op: msg.op.clone(), + }) + } } -fn process_mint(context: &mut T, msg: &ExecutionMessage, mint: Mint) -> Result { - // ignore inscribe inscription to coinbase. - let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; - - let tick = mint.tick.parse::()?; - - let token_info = context - .get_token_info(&tick) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to get token info from database: {}", e)) - })? - .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; - - let base = BIGDECIMAL_TEN.checked_powu(u64::from(token_info.decimal))?; - - let mut amt = Num::from_str(&mint.amount)?; - - if amt.scale() > i64::from(token_info.decimal) { - return Err(Error::BRC20Error(BRC20Error::AmountOverflow( - amt.to_string(), - ))); - } - - amt = amt.checked_mul(&base)?; - if amt.sign() == Sign::NoSign { - return Err(Error::BRC20Error(BRC20Error::InvalidZeroAmount)); - } - if amt > Into::::into(token_info.limit_per_mint) { - return Err(Error::BRC20Error(BRC20Error::AmountExceedLimit( - amt.to_string(), - ))); - } - let minted = Into::::into(token_info.minted); - let supply = Into::::into(token_info.supply); - - if minted >= supply { - return Err(Error::BRC20Error(BRC20Error::TickMinted( - token_info.tick.to_string(), - ))); +pub fn execute(context: &mut T, msg: &ExecutionMessage) -> Result { + log::debug!("BRC20 execute message: {:?}", msg); + let event = match &msg.op { + Operation::Deploy(deploy) => process_deploy(context, msg, deploy.clone()), + Operation::Mint(mint) => process_mint(context, msg, mint.clone()), + Operation::InscribeTransfer(transfer) => { + process_inscribe_transfer(context, msg, transfer.clone()) } + Operation::Transfer(_) => process_transfer(context, msg), + }; + + let receipt = Receipt { + inscription_id: msg.inscription_id, + inscription_number: msg.inscription_number, + old_satpoint: msg.old_satpoint, + new_satpoint: msg.new_satpoint, + from: msg.from.clone(), + // redirect receiver to sender if transfer to conibase. + to: msg.to.clone().map_or(msg.from.clone(), |v| v), + op: msg.op.op_type(), + result: match event { + Ok(event) => Ok(event), + Err(Error::BRC20Error(e)) => Err(e), + Err(e) => return Err(anyhow!("BRC20 execute exception: {e}")), + }, + }; - // cut off any excess. - let mut out_msg = None; - amt = if amt.checked_add(&minted)? > supply { - let new = supply.checked_sub(&minted)?; - out_msg = Some(format!( - "amt has been cut off to fit the supply! origin: {}, now: {}", - amt, new - )); - new - } else { - amt - }; - - // get or initialize user balance. - let mut balance = context - .get_balance(&to_script_key, &tick) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to get balance from database: {}", e)) - })? - .map_or(Balance::new(&tick), |v| v); - - // add amount to available balance. - balance.overall_balance = Into::::into(balance.overall_balance) - .checked_add(&amt)? - .checked_to_u128()?; - - // store to database. - context - .update_token_balance(&to_script_key, balance) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to update balance to database: {}", e)) - })?; - - // update token minted. - let minted = minted.checked_add(&amt)?.checked_to_u128()?; - context - .update_mint_token_info(&tick, minted, context.block_height()) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to update minted to database: {}", e)) - })?; - - Ok(Event::Mint(MintEvent { - tick: token_info.tick, - amount: amt.checked_to_u128()?, - msg: out_msg, - })) + log::debug!("BRC20 message receipt: {:?}", receipt); + Ok(receipt) } -fn process_inscribe_transfer( - context: &mut T, - msg: &ExecutionMessage, - transfer: Transfer, +fn process_deploy( + context: &mut T, + msg: &ExecutionMessage, + deploy: Deploy, ) -> Result { - // ignore inscribe inscription to coinbase. - let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; - - let tick = transfer.tick.parse::()?; - - let token_info = context - .get_token_info(&tick) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to get token info from database: {}", e)) - })? - .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; - - let base = BIGDECIMAL_TEN.checked_powu(u64::from(token_info.decimal))?; - - let mut amt = Num::from_str(&transfer.amount)?; - - if amt.scale() > i64::from(token_info.decimal) { - return Err(Error::BRC20Error(BRC20Error::AmountOverflow( - amt.to_string(), - ))); - } - - amt = amt.checked_mul(&base)?; - if amt.sign() == Sign::NoSign || amt > Into::::into(token_info.supply) { - return Err(Error::BRC20Error(BRC20Error::AmountOverflow( - amt.to_string(), - ))); - } - - let mut balance = context - .get_balance(&to_script_key, &tick) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to get balance from database: {}", e)) - })? - .map_or(Balance::new(&tick), |v| v); - - let overall = Into::::into(balance.overall_balance); - let transferable = Into::::into(balance.transferable_balance); - let available = overall.checked_sub(&transferable)?; - if available < amt { - return Err(Error::BRC20Error(BRC20Error::InsufficientBalance( - available.to_string(), - amt.to_string(), - ))); - } - - balance.transferable_balance = transferable.checked_add(&amt)?.checked_to_u128()?; - - let amt = amt.checked_to_u128()?; - context - .update_token_balance(&to_script_key, balance) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to update balance to database: {}", e)) - })?; - - let inscription = TransferableLog { - inscription_id: msg.inscription_id, - inscription_number: msg.inscription_number, - amount: amt, - tick: token_info.tick.clone(), - owner: to_script_key, - }; - - context - .insert_transferable(&inscription.owner, &tick, &inscription) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to insert transferable to database: {}", e)) - })?; - - context - .insert_inscribe_transfer_inscription( - &msg.inscription_id, - TransferInfo { - tick: token_info.tick, - amt, - }, - ) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to insert inscribe transfer inscription to database: {}", e)) - })?; - - Ok(Event::InscribeTransfer(InscripbeTransferEvent { - tick: inscription.tick, - amount: amt, - })) + // ignore inscribe inscription to coinbase. + let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; + + let tick = deploy.tick.parse::()?; + + if let Some(stored_tick_info) = context + .get_token_info(&tick) + .map_err(|e| Error::LedgerError(anyhow!("failed to get token info from database: {}", e)))? + { + return Err(Error::BRC20Error(BRC20Error::DuplicateTick( + stored_tick_info.tick.to_string(), + ))); + } + + let dec = Num::from_str(&deploy.decimals.map_or(MAX_DECIMAL_WIDTH.to_string(), |v| v))? + .checked_to_u8()?; + if dec > MAX_DECIMAL_WIDTH { + return Err(Error::BRC20Error(BRC20Error::DecimalsTooLarge(dec))); + } + let base = BIGDECIMAL_TEN.checked_powu(u64::from(dec))?; + + let supply = Num::from_str(&deploy.max_supply)?; + + if supply.sign() == Sign::NoSign + || supply > MAXIMUM_SUPPLY.to_owned() + || supply.scale() > i64::from(dec) + { + return Err(Error::BRC20Error(BRC20Error::InvalidSupply( + supply.to_string(), + ))); + } + + let limit = Num::from_str(&deploy.mint_limit.map_or(deploy.max_supply, |v| v))?; + + if limit.sign() == Sign::NoSign + || limit > MAXIMUM_SUPPLY.to_owned() + || limit.scale() > i64::from(dec) + { + return Err(Error::BRC20Error(BRC20Error::MintLimitOutOfRange( + tick.to_lowercase().to_string(), + limit.to_string(), + ))); + } + + let supply = supply.checked_mul(&base)?.checked_to_u128()?; + let limit = limit.checked_mul(&base)?.checked_to_u128()?; + + let new_info = TokenInfo { + inscription_id: msg.inscription_id, + inscription_number: msg.inscription_number, + tick: tick.clone(), + decimal: dec, + supply, + limit_per_mint: limit, + minted: 0u128, + deploy_by: to_script_key, + deployed_number: context.block_height(), + latest_mint_number: context.block_height(), + deployed_timestamp: context.block_time(), + }; + context + .insert_token_info(&tick, &new_info) + .map_err(|e| Error::LedgerError(anyhow!("failed to insert token info to database: {}", e)))?; + + Ok(Event::Deploy(DeployEvent { + supply, + limit_per_mint: limit, + decimal: dec, + tick: new_info.tick, + })) } -fn process_transfer(context: &mut T, msg: &ExecutionMessage) -> Result { - let transferable = context - .get_transferable_by_id(&msg.from, &msg.inscription_id) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to get transferable from database: {}", e)) - })? - .ok_or(BRC20Error::TransferableNotFound(msg.inscription_id))?; - - let amt = Into::::into(transferable.amount); - - if transferable.owner != msg.from { - return Err(Error::BRC20Error(BRC20Error::TransferableOwnerNotMatch( - msg.inscription_id, - ))); - } - - let tick = transferable.tick; - - let token_info = context - .get_token_info(&tick) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to get token info from database: {}", e)) - })? - .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; - - // update from key balance. - let mut from_balance = context - .get_balance(&msg.from, &tick) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to get balance from database: {}", e)) - })? - .map_or(Balance::new(&tick), |v| v); - - let from_overall = Into::::into(from_balance.overall_balance); - let from_transferable = Into::::into(from_balance.transferable_balance); - - let from_overall = from_overall.checked_sub(&amt)?.checked_to_u128()?; - let from_transferable = from_transferable.checked_sub(&amt)?.checked_to_u128()?; - - from_balance.overall_balance = from_overall; - from_balance.transferable_balance = from_transferable; - - context - .update_token_balance(&msg.from, from_balance) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to update balance to database: {}", e)) - })?; +fn process_mint( + context: &mut T, + msg: &ExecutionMessage, + mint: Mint, +) -> Result { + // ignore inscribe inscription to coinbase. + let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; + + let tick = mint.tick.parse::()?; + + let token_info = context + .get_token_info(&tick) + .map_err(|e| Error::LedgerError(anyhow!("failed to get token info from database: {}", e)))? + .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; + + let base = BIGDECIMAL_TEN.checked_powu(u64::from(token_info.decimal))?; + + let mut amt = Num::from_str(&mint.amount)?; + + if amt.scale() > i64::from(token_info.decimal) { + return Err(Error::BRC20Error(BRC20Error::AmountOverflow( + amt.to_string(), + ))); + } + + amt = amt.checked_mul(&base)?; + if amt.sign() == Sign::NoSign { + return Err(Error::BRC20Error(BRC20Error::InvalidZeroAmount)); + } + if amt > Into::::into(token_info.limit_per_mint) { + return Err(Error::BRC20Error(BRC20Error::AmountExceedLimit( + amt.to_string(), + ))); + } + let minted = Into::::into(token_info.minted); + let supply = Into::::into(token_info.supply); + + if minted >= supply { + return Err(Error::BRC20Error(BRC20Error::TickMinted( + token_info.tick.to_string(), + ))); + } + + // cut off any excess. + let mut out_msg = None; + amt = if amt.checked_add(&minted)? > supply { + let new = supply.checked_sub(&minted)?; + out_msg = Some(format!( + "amt has been cut off to fit the supply! origin: {}, now: {}", + amt, new + )); + new + } else { + amt + }; + + // get or initialize user balance. + let mut balance = context + .get_balance(&to_script_key, &tick) + .map_err(|e| Error::LedgerError(anyhow!("failed to get balance from database: {}", e)))? + .map_or(Balance::new(&tick), |v| v); + + // add amount to available balance. + balance.overall_balance = Into::::into(balance.overall_balance) + .checked_add(&amt)? + .checked_to_u128()?; + + // store to database. + context + .update_token_balance(&to_script_key, balance) + .map_err(|e| Error::LedgerError(anyhow!("failed to update balance to database: {}", e)))?; + + // update token minted. + let minted = minted.checked_add(&amt)?.checked_to_u128()?; + context + .update_mint_token_info(&tick, minted, context.block_height()) + .map_err(|e| Error::LedgerError(anyhow!("failed to update minted to database: {}", e)))?; + + Ok(Event::Mint(MintEvent { + tick: token_info.tick, + amount: amt.checked_to_u128()?, + msg: out_msg, + })) +} - // redirect receiver to sender if transfer to conibase. - let mut out_msg = None; - - let to_script_key = if msg.to.clone().is_none() { - out_msg = - Some("redirect receiver to sender, reason: transfer inscription to coinbase".to_string()); - msg.from.clone() - } else { - msg.to.clone().unwrap() - }; - - // update to key balance. - let mut to_balance = context - .get_balance(&to_script_key, &tick) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to get balance from database: {}", e)) - })? - .map_or(Balance::new(&tick), |v| v); - - let to_overall = Into::::into(to_balance.overall_balance); - to_balance.overall_balance = to_overall.checked_add(&amt)?.checked_to_u128()?; - - context - .update_token_balance(&to_script_key, to_balance) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to update balance to database: {}", e)) - })?; - - context - .remove_transferable(&msg.from, &tick, &msg.inscription_id) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to remove transferable from database: {}", e)) - })?; - - context - .remove_inscribe_transfer_inscription(&msg.inscription_id) - .map_err(|e|{ - Error::LedgerError(anyhow!("failed to remove inscribe transfer inscription from database: {}", e)) - })?; - - Ok(Event::Transfer(TransferEvent { - msg: out_msg, +fn process_inscribe_transfer( + context: &mut T, + msg: &ExecutionMessage, + transfer: Transfer, +) -> Result { + // ignore inscribe inscription to coinbase. + let to_script_key = msg.to.clone().ok_or(BRC20Error::InscribeToCoinbase)?; + + let tick = transfer.tick.parse::()?; + + let token_info = context + .get_token_info(&tick) + .map_err(|e| Error::LedgerError(anyhow!("failed to get token info from database: {}", e)))? + .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; + + let base = BIGDECIMAL_TEN.checked_powu(u64::from(token_info.decimal))?; + + let mut amt = Num::from_str(&transfer.amount)?; + + if amt.scale() > i64::from(token_info.decimal) { + return Err(Error::BRC20Error(BRC20Error::AmountOverflow( + amt.to_string(), + ))); + } + + amt = amt.checked_mul(&base)?; + if amt.sign() == Sign::NoSign || amt > Into::::into(token_info.supply) { + return Err(Error::BRC20Error(BRC20Error::AmountOverflow( + amt.to_string(), + ))); + } + + let mut balance = context + .get_balance(&to_script_key, &tick) + .map_err(|e| Error::LedgerError(anyhow!("failed to get balance from database: {}", e)))? + .map_or(Balance::new(&tick), |v| v); + + let overall = Into::::into(balance.overall_balance); + let transferable = Into::::into(balance.transferable_balance); + let available = overall.checked_sub(&transferable)?; + if available < amt { + return Err(Error::BRC20Error(BRC20Error::InsufficientBalance( + available.to_string(), + amt.to_string(), + ))); + } + + balance.transferable_balance = transferable.checked_add(&amt)?.checked_to_u128()?; + + let amt = amt.checked_to_u128()?; + context + .update_token_balance(&to_script_key, balance) + .map_err(|e| Error::LedgerError(anyhow!("failed to update balance to database: {}", e)))?; + + let inscription = TransferableLog { + inscription_id: msg.inscription_id, + inscription_number: msg.inscription_number, + amount: amt, + tick: token_info.tick.clone(), + owner: to_script_key, + }; + + context + .insert_transferable(&inscription.owner, &tick, &inscription) + .map_err(|e| Error::LedgerError(anyhow!("failed to insert transferable to database: {}", e)))?; + + context + .insert_inscribe_transfer_inscription( + &msg.inscription_id, + TransferInfo { tick: token_info.tick, - amount: amt.checked_to_u128()?, - })) + amt, + }, + ) + .map_err(|e| { + Error::LedgerError(anyhow!( + "failed to insert inscribe transfer inscription to database: {}", + e + )) + })?; + + Ok(Event::InscribeTransfer(InscripbeTransferEvent { + tick: inscription.tick, + amount: amt, + })) +} + +fn process_transfer( + context: &mut T, + msg: &ExecutionMessage, +) -> Result { + let transferable = context + .get_transferable_by_id(&msg.from, &msg.inscription_id) + .map_err(|e| Error::LedgerError(anyhow!("failed to get transferable from database: {}", e)))? + .ok_or(BRC20Error::TransferableNotFound(msg.inscription_id))?; + + let amt = Into::::into(transferable.amount); + + if transferable.owner != msg.from { + return Err(Error::BRC20Error(BRC20Error::TransferableOwnerNotMatch( + msg.inscription_id, + ))); + } + + let tick = transferable.tick; + + let token_info = context + .get_token_info(&tick) + .map_err(|e| Error::LedgerError(anyhow!("failed to get token info from database: {}", e)))? + .ok_or(BRC20Error::TickNotFound(tick.to_string()))?; + + // update from key balance. + let mut from_balance = context + .get_balance(&msg.from, &tick) + .map_err(|e| Error::LedgerError(anyhow!("failed to get balance from database: {}", e)))? + .map_or(Balance::new(&tick), |v| v); + + let from_overall = Into::::into(from_balance.overall_balance); + let from_transferable = Into::::into(from_balance.transferable_balance); + + let from_overall = from_overall.checked_sub(&amt)?.checked_to_u128()?; + let from_transferable = from_transferable.checked_sub(&amt)?.checked_to_u128()?; + + from_balance.overall_balance = from_overall; + from_balance.transferable_balance = from_transferable; + + context + .update_token_balance(&msg.from, from_balance) + .map_err(|e| Error::LedgerError(anyhow!("failed to update balance to database: {}", e)))?; + + // redirect receiver to sender if transfer to conibase. + let mut out_msg = None; + + let to_script_key = if msg.to.clone().is_none() { + out_msg = + Some("redirect receiver to sender, reason: transfer inscription to coinbase".to_string()); + msg.from.clone() + } else { + msg.to.clone().unwrap() + }; + + // update to key balance. + let mut to_balance = context + .get_balance(&to_script_key, &tick) + .map_err(|e| Error::LedgerError(anyhow!("failed to get balance from database: {}", e)))? + .map_or(Balance::new(&tick), |v| v); + + let to_overall = Into::::into(to_balance.overall_balance); + to_balance.overall_balance = to_overall.checked_add(&amt)?.checked_to_u128()?; + + context + .update_token_balance(&to_script_key, to_balance) + .map_err(|e| Error::LedgerError(anyhow!("failed to update balance to database: {}", e)))?; + + context + .remove_transferable(&msg.from, &tick, &msg.inscription_id) + .map_err(|e| { + Error::LedgerError(anyhow!( + "failed to remove transferable from database: {}", + e + )) + })?; + + context + .remove_inscribe_transfer_inscription(&msg.inscription_id) + .map_err(|e| { + Error::LedgerError(anyhow!( + "failed to remove inscribe transfer inscription from database: {}", + e + )) + })?; + + Ok(Event::Transfer(TransferEvent { + msg: out_msg, + tick: token_info.tick, + amount: amt.checked_to_u128()?, + })) } diff --git a/src/okx/protocol/brc20/msg_resolver.rs b/src/okx/protocol/brc20/msg_resolver.rs index 5dc84c0ee1..03694b7f7b 100644 --- a/src/okx/protocol/brc20/msg_resolver.rs +++ b/src/okx/protocol/brc20/msg_resolver.rs @@ -1,4 +1,5 @@ use super::*; +use crate::okx::datastore::brc20::Brc20ReaderWriter; use crate::{ inscriptions::Inscription, okx::{ @@ -8,7 +9,6 @@ use crate::{ Result, }; use anyhow::anyhow; -use crate::okx::datastore::brc20::Brc20ReaderWriter; impl Message { pub(crate) fn resolve( @@ -78,16 +78,20 @@ impl Message { #[cfg(test)] mod tests { use super::*; - use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, ORD_TX_TO_OPERATIONS, OUTPOINT_TO_ENTRY, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY}; + use crate::index::{ + BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, + COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, ORD_TX_TO_OPERATIONS, + OUTPOINT_TO_ENTRY, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, + }; use crate::okx::datastore::brc20::redb::table::insert_inscribe_transfer_inscription; use crate::okx::datastore::brc20::{Tick, TransferInfo}; + use crate::okx::lru::SimpleLru; + use crate::okx::protocol::context::Context; + use crate::okx::protocol::BlockContext; use bitcoin::{Network, OutPoint}; use redb::{Database, WriteTransaction}; use std::str::FromStr; use tempfile::NamedTempFile; - use crate::okx::lru::SimpleLru; - use crate::okx::protocol::BlockContext; - use crate::okx::protocol::context::Context; fn create_inscription(str: &str) -> Inscription { Inscription::new( @@ -157,26 +161,30 @@ mod tests { } } - #[test] fn test_invalid_protocol() { let db_file = NamedTempFile::new().unwrap(); let db = Database::create(db_file.path()).unwrap(); let wtx = db.begin_write().unwrap(); - let context= Context { + let context = Context { chain: BlockContext { network: Network::Regtest, blockheight: 0, blocktime: 0, }, - tx_out_cache:&mut SimpleLru::new(10), + tx_out_cache: &mut SimpleLru::new(10), hit: 0, miss: 0, ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS).unwrap(), - COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID).unwrap(), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx + .open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID) + .unwrap(), COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx - .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS).unwrap(), - SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(), + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS) + .unwrap(), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx + .open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY) + .unwrap(), OUTPOINT_TO_ENTRY: &mut wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(), BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES).unwrap(), BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN).unwrap(), @@ -195,20 +203,25 @@ mod tests { let db_file = NamedTempFile::new().unwrap(); let db = Database::create(db_file.path()).unwrap(); let wtx = db.begin_write().unwrap(); - let context= Context { + let context = Context { chain: BlockContext { network: Network::Regtest, blockheight: 0, blocktime: 0, }, - tx_out_cache:&mut SimpleLru::new(10), + tx_out_cache: &mut SimpleLru::new(10), hit: 0, miss: 0, ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS).unwrap(), - COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID).unwrap(), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx + .open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID) + .unwrap(), COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx - .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS).unwrap(), - SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(), + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS) + .unwrap(), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx + .open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY) + .unwrap(), OUTPOINT_TO_ENTRY: &mut wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(), BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES).unwrap(), BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN).unwrap(), @@ -258,20 +271,25 @@ mod tests { let db_file = NamedTempFile::new().unwrap(); let db = Database::create(db_file.path()).unwrap(); let wtx = db.begin_write().unwrap(); - let context= Context { + let context = Context { chain: BlockContext { network: Network::Regtest, blockheight: 0, blocktime: 0, }, - tx_out_cache:&mut SimpleLru::new(10), + tx_out_cache: &mut SimpleLru::new(10), hit: 0, miss: 0, ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS).unwrap(), - COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID).unwrap(), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx + .open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID) + .unwrap(), COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx - .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS).unwrap(), - SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(), + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS) + .unwrap(), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx + .open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY) + .unwrap(), OUTPOINT_TO_ENTRY: &mut wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(), BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES).unwrap(), BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN).unwrap(), @@ -308,20 +326,25 @@ mod tests { let db_file = NamedTempFile::new().unwrap(); let db = Database::create(db_file.path()).unwrap(); let wtx = db.begin_write().unwrap(); - let context= Context { + let context = Context { chain: BlockContext { network: Network::Regtest, blockheight: 0, blocktime: 0, }, - tx_out_cache:&mut SimpleLru::new(10), + tx_out_cache: &mut SimpleLru::new(10), hit: 0, miss: 0, ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS).unwrap(), - COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID).unwrap(), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx + .open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID) + .unwrap(), COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx - .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS).unwrap(), - SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(), + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS) + .unwrap(), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx + .open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY) + .unwrap(), OUTPOINT_TO_ENTRY: &mut wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(), BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES).unwrap(), BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN).unwrap(), @@ -381,20 +404,25 @@ mod tests { sat_in_outputs: true, }; - let context= Context { + let context = Context { chain: BlockContext { network: Network::Regtest, blockheight: 0, blocktime: 0, }, - tx_out_cache:&mut SimpleLru::new(10), + tx_out_cache: &mut SimpleLru::new(10), hit: 0, miss: 0, ORD_TX_TO_OPERATIONS: &mut wtx.open_table(ORD_TX_TO_OPERATIONS).unwrap(), - COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx.open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID).unwrap(), + COLLECTIONS_KEY_TO_INSCRIPTION_ID: &mut wtx + .open_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID) + .unwrap(), COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &mut wtx - .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS).unwrap(), - SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY).unwrap(), + .open_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS) + .unwrap(), + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &mut wtx + .open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY) + .unwrap(), OUTPOINT_TO_ENTRY: &mut wtx.open_table(OUTPOINT_TO_ENTRY).unwrap(), BRC20_BALANCES: &mut wtx.open_table(BRC20_BALANCES).unwrap(), BRC20_TOKEN: &mut wtx.open_table(BRC20_TOKEN).unwrap(), diff --git a/src/okx/protocol/context.rs b/src/okx/protocol/context.rs index f5c7c8a690..e4b9ace114 100644 --- a/src/okx/protocol/context.rs +++ b/src/okx/protocol/context.rs @@ -1,22 +1,22 @@ use crate::index::{InscriptionEntryValue, InscriptionIdValue, OutPointValue, TxidValue}; use crate::inscriptions::InscriptionId; use crate::okx::datastore::brc20::redb::table::{ - get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, - get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick, - insert_inscribe_transfer_inscription, insert_token_info, insert_transferable, - remove_inscribe_transfer_inscription, remove_transferable, save_transaction_receipts, - update_mint_token_info, update_token_balance, + get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, + get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick, + insert_inscribe_transfer_inscription, insert_token_info, insert_transferable, + remove_inscribe_transfer_inscription, remove_transferable, save_transaction_receipts, + update_mint_token_info, update_token_balance, }; use crate::okx::datastore::brc20::{ - Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferInfo, TransferableLog, + Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferInfo, TransferableLog, }; use crate::okx::datastore::ord::collections::CollectionKind; use crate::okx::datastore::ord::redb::table::{ - get_collection_inscription_id, get_collections_of_inscription, get_transaction_operations, - get_txout_by_outpoint, set_inscription_attributes, set_inscription_by_collection_key, + get_collection_inscription_id, get_collections_of_inscription, get_transaction_operations, + get_txout_by_outpoint, set_inscription_attributes, set_inscription_by_collection_key, }; use crate::okx::datastore::ord::redb::table::{ - get_inscription_number_by_sequence_number, save_transaction_operations, + get_inscription_number_by_sequence_number, save_transaction_operations, }; use crate::okx::datastore::ord::{InscriptionOp, OrdReader, OrdReaderWriter}; use crate::okx::datastore::ScriptKey; @@ -30,261 +30,263 @@ use redb::Table; #[allow(non_snake_case)] pub struct Context<'a, 'db, 'txn> { - pub(crate) chain: BlockContext, - pub(crate) tx_out_cache: &'a mut SimpleLru, - pub(crate) hit: u64, - pub(crate) miss: u64, - - // ord tables - pub(crate) ORD_TX_TO_OPERATIONS: &'a mut Table<'db, 'txn, &'static TxidValue, &'static [u8]>, - pub(crate) COLLECTIONS_KEY_TO_INSCRIPTION_ID: + pub(crate) chain: BlockContext, + pub(crate) tx_out_cache: &'a mut SimpleLru, + pub(crate) hit: u64, + pub(crate) miss: u64, + + // ord tables + pub(crate) ORD_TX_TO_OPERATIONS: &'a mut Table<'db, 'txn, &'static TxidValue, &'static [u8]>, + pub(crate) COLLECTIONS_KEY_TO_INSCRIPTION_ID: &'a mut Table<'db, 'txn, &'static str, InscriptionIdValue>, - pub(crate) COLLECTIONS_INSCRIPTION_ID_TO_KINDS: + pub(crate) COLLECTIONS_INSCRIPTION_ID_TO_KINDS: &'a mut Table<'db, 'txn, InscriptionIdValue, &'static [u8]>, - pub(crate) SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: + pub(crate) SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: &'a mut Table<'db, 'txn, u32, InscriptionEntryValue>, - pub(crate) OUTPOINT_TO_ENTRY: &'a mut Table<'db, 'txn, &'static OutPointValue, &'static [u8]>, - - // BRC20 tables - pub(crate) BRC20_BALANCES: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, - pub(crate) BRC20_TOKEN: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, - pub(crate) BRC20_EVENTS: &'a mut Table<'db, 'txn, &'static TxidValue, &'static [u8]>, - pub(crate) BRC20_TRANSFERABLELOG: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, - pub(crate) BRC20_INSCRIBE_TRANSFER: &'a mut Table<'db, 'txn, InscriptionIdValue, &'static [u8]>, + pub(crate) OUTPOINT_TO_ENTRY: &'a mut Table<'db, 'txn, &'static OutPointValue, &'static [u8]>, + + // BRC20 tables + pub(crate) BRC20_BALANCES: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, + pub(crate) BRC20_TOKEN: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, + pub(crate) BRC20_EVENTS: &'a mut Table<'db, 'txn, &'static TxidValue, &'static [u8]>, + pub(crate) BRC20_TRANSFERABLELOG: &'a mut Table<'db, 'txn, &'static str, &'static [u8]>, + pub(crate) BRC20_INSCRIBE_TRANSFER: &'a mut Table<'db, 'txn, InscriptionIdValue, &'static [u8]>, } impl<'a, 'db, 'txn> OrdReader for Context<'a, 'db, 'txn> { - type Error = anyhow::Error; - - fn get_inscription_number_by_sequence_number( - &self, - sequence_number: u32, - ) -> crate::Result { - get_inscription_number_by_sequence_number( - self.SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, - sequence_number, - ) - .map_err(|e| anyhow!("failed to get inscription number from state! error: {e}"))? - .ok_or(anyhow!( + type Error = anyhow::Error; + + fn get_inscription_number_by_sequence_number( + &self, + sequence_number: u32, + ) -> crate::Result { + get_inscription_number_by_sequence_number( + self.SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, + sequence_number, + ) + .map_err(|e| anyhow!("failed to get inscription number from state! error: {e}"))? + .ok_or(anyhow!( "failed to get inscription number! error: sequence number {} not found", sequence_number )) - } - - fn get_script_key_on_satpoint( - &mut self, - satpoint: &SatPoint, - network: Network, - ) -> crate::Result { - if let Some(tx_out) = self.tx_out_cache.get(&satpoint.outpoint) { - self.hit += 1; - Ok(ScriptKey::from_script(&tx_out.script_pubkey, network)) - } else if let Some(tx_out) = get_txout_by_outpoint(self.OUTPOINT_TO_ENTRY, &satpoint.outpoint)? - { - self.miss += 1; - Ok(ScriptKey::from_script(&tx_out.script_pubkey, network)) - } else { - Err(anyhow!( + } + + fn get_script_key_on_satpoint( + &mut self, + satpoint: &SatPoint, + network: Network, + ) -> crate::Result { + if let Some(tx_out) = self.tx_out_cache.get(&satpoint.outpoint) { + self.hit += 1; + Ok(ScriptKey::from_script(&tx_out.script_pubkey, network)) + } else if let Some(tx_out) = get_txout_by_outpoint(self.OUTPOINT_TO_ENTRY, &satpoint.outpoint)? + { + self.miss += 1; + Ok(ScriptKey::from_script(&tx_out.script_pubkey, network)) + } else { + Err(anyhow!( "failed to get tx out! error: outpoint {} not found", &satpoint.outpoint )) - } - } - - fn get_transaction_operations( - &self, - txid: &Txid, - ) -> crate::Result, Self::Error> { - get_transaction_operations(self.ORD_TX_TO_OPERATIONS, txid) - } - - fn get_collections_of_inscription( - &self, - inscription_id: &InscriptionId, - ) -> crate::Result>, Self::Error> { - get_collections_of_inscription(self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS, inscription_id) - } - - fn get_collection_inscription_id( - &self, - collection_key: &str, - ) -> crate::Result, Self::Error> { - get_collection_inscription_id(self.COLLECTIONS_KEY_TO_INSCRIPTION_ID, collection_key) } + } + + fn get_transaction_operations( + &self, + txid: &Txid, + ) -> crate::Result, Self::Error> { + get_transaction_operations(self.ORD_TX_TO_OPERATIONS, txid) + } + + fn get_collections_of_inscription( + &self, + inscription_id: &InscriptionId, + ) -> crate::Result>, Self::Error> { + get_collections_of_inscription(self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS, inscription_id) + } + + fn get_collection_inscription_id( + &self, + collection_key: &str, + ) -> crate::Result, Self::Error> { + get_collection_inscription_id(self.COLLECTIONS_KEY_TO_INSCRIPTION_ID, collection_key) + } } impl<'a, 'db, 'txn> OrdReaderWriter for Context<'a, 'db, 'txn> { - fn save_transaction_operations( - &mut self, - txid: &Txid, - operations: &[InscriptionOp], - ) -> crate::Result<(), Self::Error> { - save_transaction_operations(self.ORD_TX_TO_OPERATIONS, txid, operations) - } - - fn set_inscription_by_collection_key( - &mut self, - key: &str, - inscription_id: &InscriptionId, - ) -> crate::Result<(), Self::Error> { - set_inscription_by_collection_key(self.COLLECTIONS_KEY_TO_INSCRIPTION_ID, key, inscription_id) - } - - fn set_inscription_attributes( - &mut self, - inscription_id: &InscriptionId, - kind: &[CollectionKind], - ) -> crate::Result<(), Self::Error> { - set_inscription_attributes( - self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS, - inscription_id, - kind, - ) - } + fn save_transaction_operations( + &mut self, + txid: &Txid, + operations: &[InscriptionOp], + ) -> crate::Result<(), Self::Error> { + save_transaction_operations(self.ORD_TX_TO_OPERATIONS, txid, operations) + } + + fn set_inscription_by_collection_key( + &mut self, + key: &str, + inscription_id: &InscriptionId, + ) -> crate::Result<(), Self::Error> { + set_inscription_by_collection_key(self.COLLECTIONS_KEY_TO_INSCRIPTION_ID, key, inscription_id) + } + + fn set_inscription_attributes( + &mut self, + inscription_id: &InscriptionId, + kind: &[CollectionKind], + ) -> crate::Result<(), Self::Error> { + set_inscription_attributes( + self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS, + inscription_id, + kind, + ) + } } impl<'a, 'db, 'txn> Brc20Reader for Context<'a, 'db, 'txn> { - type Error = anyhow::Error; - - fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { - get_balances(self.BRC20_BALANCES, script_key) - } - - fn get_balance( - &self, - script_key: &ScriptKey, - tick: &Tick, - ) -> crate::Result, Self::Error> { - get_balance(self.BRC20_BALANCES, script_key, tick) - } - - fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { - get_token_info(self.BRC20_TOKEN, tick) - } - - fn get_tokens_info(&self) -> crate::Result, Self::Error> { - get_tokens_info(self.BRC20_TOKEN) - } - - fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { - get_transaction_receipts(self.BRC20_EVENTS, txid) - } - - fn get_transferable( - &self, - script: &ScriptKey, - ) -> crate::Result, Self::Error> { - get_transferable(self.BRC20_TRANSFERABLELOG, script) - } - - fn get_transferable_by_tick( - &self, - script: &ScriptKey, - tick: &Tick, - ) -> crate::Result, Self::Error> { - get_transferable_by_tick(self.BRC20_TRANSFERABLELOG, script, tick) - } - - fn get_transferable_by_id( - &self, - script: &ScriptKey, - inscription_id: &InscriptionId, - ) -> crate::Result, Self::Error> { - get_transferable_by_id(self.BRC20_TRANSFERABLELOG, script, inscription_id) - } - - fn get_inscribe_transfer_inscription( - &self, - inscription_id: &InscriptionId, - ) -> crate::Result, Self::Error> { - get_inscribe_transfer_inscription(self.BRC20_INSCRIBE_TRANSFER, inscription_id) - } + type Error = anyhow::Error; + + fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { + get_balances(self.BRC20_BALANCES, script_key) + } + + fn get_balance( + &self, + script_key: &ScriptKey, + tick: &Tick, + ) -> crate::Result, Self::Error> { + get_balance(self.BRC20_BALANCES, script_key, tick) + } + + fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { + get_token_info(self.BRC20_TOKEN, tick) + } + + fn get_tokens_info(&self) -> crate::Result, Self::Error> { + get_tokens_info(self.BRC20_TOKEN) + } + + fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { + get_transaction_receipts(self.BRC20_EVENTS, txid) + } + + fn get_transferable( + &self, + script: &ScriptKey, + ) -> crate::Result, Self::Error> { + get_transferable(self.BRC20_TRANSFERABLELOG, script) + } + + fn get_transferable_by_tick( + &self, + script: &ScriptKey, + tick: &Tick, + ) -> crate::Result, Self::Error> { + get_transferable_by_tick(self.BRC20_TRANSFERABLELOG, script, tick) + } + + fn get_transferable_by_id( + &self, + script: &ScriptKey, + inscription_id: &InscriptionId, + ) -> crate::Result, Self::Error> { + get_transferable_by_id(self.BRC20_TRANSFERABLELOG, script, inscription_id) + } + + fn get_inscribe_transfer_inscription( + &self, + inscription_id: &InscriptionId, + ) -> crate::Result, Self::Error> { + get_inscribe_transfer_inscription(self.BRC20_INSCRIBE_TRANSFER, inscription_id) + } } impl<'a, 'db, 'txn> Brc20ReaderWriter for Context<'a, 'db, 'txn> { - fn update_token_balance( - &mut self, - script_key: &ScriptKey, - new_balance: Balance, - ) -> crate::Result<(), Self::Error> { - update_token_balance(self.BRC20_BALANCES, script_key, new_balance) - } - - fn insert_token_info( - &mut self, - tick: &Tick, - new_info: &TokenInfo, - ) -> crate::Result<(), Self::Error> { - insert_token_info(self.BRC20_TOKEN, tick, new_info) - } - - fn update_mint_token_info( - &mut self, - tick: &Tick, - minted_amt: u128, - minted_block_number: u32, - ) -> crate::Result<(), Self::Error> { - update_mint_token_info(self.BRC20_TOKEN, tick, minted_amt, minted_block_number) - } - - fn save_transaction_receipts( - &mut self, - txid: &Txid, - receipt: &[Receipt], - ) -> crate::Result<(), Self::Error> { - info!("save transaction receipts: txid: {}, receipt: {:?}", txid, receipt); - save_transaction_receipts(self.BRC20_EVENTS, txid, receipt) - } - - fn insert_transferable( - &mut self, - script: &ScriptKey, - tick: &Tick, - inscription: &TransferableLog, - ) -> crate::Result<(), Self::Error> { - insert_transferable(self.BRC20_TRANSFERABLELOG, script, tick, inscription) - } - - fn remove_transferable( - &mut self, - script: &ScriptKey, - tick: &Tick, - inscription_id: &InscriptionId, - ) -> crate::Result<(), Self::Error> { - remove_transferable(self.BRC20_TRANSFERABLELOG, script, tick, inscription_id) - } - - fn insert_inscribe_transfer_inscription( - &mut self, - inscription_id: &InscriptionId, - transfer_info: TransferInfo, - ) -> crate::Result<(), Self::Error> { - insert_inscribe_transfer_inscription( - self.BRC20_INSCRIBE_TRANSFER, - inscription_id, - transfer_info, - ) - } - - fn remove_inscribe_transfer_inscription( - &mut self, - inscription_id: &InscriptionId, - ) -> crate::Result<(), Self::Error> { - remove_inscribe_transfer_inscription(self.BRC20_INSCRIBE_TRANSFER, inscription_id) - } + fn update_token_balance( + &mut self, + script_key: &ScriptKey, + new_balance: Balance, + ) -> crate::Result<(), Self::Error> { + update_token_balance(self.BRC20_BALANCES, script_key, new_balance) + } + + fn insert_token_info( + &mut self, + tick: &Tick, + new_info: &TokenInfo, + ) -> crate::Result<(), Self::Error> { + insert_token_info(self.BRC20_TOKEN, tick, new_info) + } + + fn update_mint_token_info( + &mut self, + tick: &Tick, + minted_amt: u128, + minted_block_number: u32, + ) -> crate::Result<(), Self::Error> { + update_mint_token_info(self.BRC20_TOKEN, tick, minted_amt, minted_block_number) + } + + fn save_transaction_receipts( + &mut self, + txid: &Txid, + receipt: &[Receipt], + ) -> crate::Result<(), Self::Error> { + info!( + "save transaction receipts: txid: {}, receipt: {:?}", + txid, receipt + ); + save_transaction_receipts(self.BRC20_EVENTS, txid, receipt) + } + + fn insert_transferable( + &mut self, + script: &ScriptKey, + tick: &Tick, + inscription: &TransferableLog, + ) -> crate::Result<(), Self::Error> { + insert_transferable(self.BRC20_TRANSFERABLELOG, script, tick, inscription) + } + + fn remove_transferable( + &mut self, + script: &ScriptKey, + tick: &Tick, + inscription_id: &InscriptionId, + ) -> crate::Result<(), Self::Error> { + remove_transferable(self.BRC20_TRANSFERABLELOG, script, tick, inscription_id) + } + + fn insert_inscribe_transfer_inscription( + &mut self, + inscription_id: &InscriptionId, + transfer_info: TransferInfo, + ) -> crate::Result<(), Self::Error> { + insert_inscribe_transfer_inscription( + self.BRC20_INSCRIBE_TRANSFER, + inscription_id, + transfer_info, + ) + } + + fn remove_inscribe_transfer_inscription( + &mut self, + inscription_id: &InscriptionId, + ) -> crate::Result<(), Self::Error> { + remove_inscribe_transfer_inscription(self.BRC20_INSCRIBE_TRANSFER, inscription_id) + } } - impl<'a, 'db, 'txn> ContextTrait for Context<'a, 'db, 'txn> { - fn block_height(&self) -> u32 { - self.chain.blockheight - } + fn block_height(&self) -> u32 { + self.chain.blockheight + } - fn network(&self) -> Network { - self.chain.network.clone() - } + fn network(&self) -> Network { + self.chain.network.clone() + } - fn block_time(&self) -> u32 { - self.chain.blocktime - } -} \ No newline at end of file + fn block_time(&self) -> u32 { + self.chain.blocktime + } +} diff --git a/src/okx/protocol/execute_manager.rs b/src/okx/protocol/execute_manager.rs index b800267a02..d9ba27d0c9 100644 --- a/src/okx/protocol/execute_manager.rs +++ b/src/okx/protocol/execute_manager.rs @@ -12,7 +12,12 @@ impl CallManager { Self {} } - pub fn execute_message(&self, context: &mut T, txid: &Txid, msgs: &[Message]) -> Result { + pub fn execute_message( + &self, + context: &mut T, + txid: &Txid, + msgs: &[Message], + ) -> Result { let mut receipts = vec![]; // execute message for msg in msgs { diff --git a/src/okx/protocol/mod.rs b/src/okx/protocol/mod.rs index b829c97117..3f42cc2a96 100644 --- a/src/okx/protocol/mod.rs +++ b/src/okx/protocol/mod.rs @@ -10,47 +10,46 @@ pub mod trace; pub use self::protocol_manager::ProtocolManager; +use crate::okx::datastore::brc20::Brc20ReaderWriter; +use crate::okx::datastore::ord::OrdReaderWriter; use { - self::{execute_manager::CallManager, message::Message, resolve_manager::MsgResolveManager}, - crate::Options, - bitcoin::Network, + self::{execute_manager::CallManager, message::Message, resolve_manager::MsgResolveManager}, + crate::Options, + bitcoin::Network, }; -use crate::okx::datastore::brc20::{Brc20ReaderWriter}; -use crate::okx::datastore::ord::OrdReaderWriter; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct BlockContext { - pub network: Network, - pub blockheight: u32, - pub blocktime: u32, + pub network: Network, + pub blockheight: u32, + pub blocktime: u32, } #[derive(Debug, Clone, Copy)] pub struct ProtocolConfig { - first_inscription_height: u32, - first_brc20_height: Option, - enable_ord_receipts: bool, - enable_index_bitmap: bool, + first_inscription_height: u32, + first_brc20_height: Option, + enable_ord_receipts: bool, + enable_index_bitmap: bool, } impl ProtocolConfig { - pub(crate) fn new_with_options(options: &Options) -> Self { - Self { - first_inscription_height: options.first_inscription_height(), - first_brc20_height: if options.enable_index_brc20 { - Some(options.first_brc20_height()) - } else { - None - }, - enable_ord_receipts: options.enable_save_ord_receipts, - enable_index_bitmap: options.enable_index_bitmap, - } + pub(crate) fn new_with_options(options: &Options) -> Self { + Self { + first_inscription_height: options.first_inscription_height(), + first_brc20_height: if options.enable_index_brc20 { + Some(options.first_brc20_height()) + } else { + None + }, + enable_ord_receipts: options.enable_save_ord_receipts, + enable_index_bitmap: options.enable_index_bitmap, } + } } - pub trait ContextTrait: Brc20ReaderWriter + OrdReaderWriter { - fn block_height(&self) -> u32; - fn network(&self) -> Network; - fn block_time(&self) -> u32; -} \ No newline at end of file + fn block_height(&self) -> u32; + fn network(&self) -> Network; + fn block_time(&self) -> u32; +} diff --git a/src/okx/protocol/ord/bitmap.rs b/src/okx/protocol/ord/bitmap.rs index b73123db3d..19d5c5db03 100644 --- a/src/okx/protocol/ord/bitmap.rs +++ b/src/okx/protocol/ord/bitmap.rs @@ -1,99 +1,103 @@ +use crate::okx::protocol::ContextTrait; use { - crate::{ - okx::datastore::ord::{ - bitmap::District, - collections::CollectionKind, - operation::{Action, InscriptionOp}, - }, - Inscription, InscriptionId, Result, + crate::{ + okx::datastore::ord::{ + bitmap::District, + collections::CollectionKind, + operation::{Action, InscriptionOp}, }, - anyhow::anyhow, - bitcoin::Txid, - std::collections::HashMap, + Inscription, InscriptionId, Result, + }, + anyhow::anyhow, + bitcoin::Txid, + std::collections::HashMap, }; -use crate::okx::protocol::ContextTrait; pub fn index_bitmap( - context: &mut T, - operations: &HashMap>, + context: &mut T, + operations: &HashMap>, ) -> Result { - let mut count = 0; + let mut count = 0; - // ignore transferred or cursed inscriptions. - let mut positive_inscriptions = operations - .values() - .flatten() - .cloned() - .filter(|op| { - !op.inscription_number.unwrap().is_negative() && matches!(op.action, Action::New { .. }) - }) - .collect::>(); + // ignore transferred or cursed inscriptions. + let mut positive_inscriptions = operations + .values() + .flatten() + .cloned() + .filter(|op| { + !op.inscription_number.unwrap().is_negative() && matches!(op.action, Action::New { .. }) + }) + .collect::>(); - // sort by inscription number. - positive_inscriptions.sort_by_key(|op| op.inscription_number.unwrap()); + // sort by inscription number. + positive_inscriptions.sort_by_key(|op| op.inscription_number.unwrap()); - for op in positive_inscriptions.into_iter() { - match op.action { - Action::New { - cursed: _, - unbound: _, - vindicated: _, - inscription, - } => { - if let Some((inscription_id, district)) = - index_district(context, inscription, op.inscription_id)? - { - let key = district.to_collection_key(); - context.set_inscription_by_collection_key(&key, &inscription_id).map_err(|e|{ + for op in positive_inscriptions.into_iter() { + match op.action { + Action::New { + cursed: _, + unbound: _, + vindicated: _, + inscription, + } => { + if let Some((inscription_id, district)) = + index_district(context, inscription, op.inscription_id)? + { + let key = district.to_collection_key(); + context.set_inscription_by_collection_key(&key, &inscription_id).map_err(|e|{ anyhow!("failed to set inscription by collection key! key: {key} inscription_id: {inscription_id} error: {e}") })?; - context.set_inscription_attributes(&inscription_id, &[CollectionKind::BitMap]).map_err(|e|{ - anyhow!("failed to set inscription attributes! inscription_id: {inscription_id} error: {e}") - })?; + context + .set_inscription_attributes(&inscription_id, &[CollectionKind::BitMap]) + .map_err(|e| { + anyhow!( + "failed to set inscription attributes! inscription_id: {inscription_id} error: {e}" + ) + })?; - count += 1; - } - } - _ => unreachable!(), + count += 1; } + } + _ => unreachable!(), } - Ok(count) + } + Ok(count) } fn index_district( - context: &mut T, - inscription: Inscription, - inscription_id: InscriptionId, + context: &mut T, + inscription: Inscription, + inscription_id: InscriptionId, ) -> Result> { - if let Some(content) = inscription.body() { - if let Ok(district) = District::parse(content) { - if district.number > context.block_height() { - return Ok(None); - } - let collection_key = district.to_collection_key(); + if let Some(content) = inscription.body() { + if let Ok(district) = District::parse(content) { + if district.number > context.block_height() { + return Ok(None); + } + let collection_key = district.to_collection_key(); - if context - .get_collection_inscription_id(&collection_key) - .map_err(|e| { - anyhow!("failed to get collection inscription! key: {collection_key} error: {e}") - })? - .is_none() - { - log::info!( + if context + .get_collection_inscription_id(&collection_key) + .map_err(|e| { + anyhow!("failed to get collection inscription! key: {collection_key} error: {e}") + })? + .is_none() + { + log::info!( "found valid district! number: {} content: {} inscription_id {}", district.number, std::str::from_utf8(content).unwrap(), inscription_id, ); - return Ok(Some((inscription_id, district))); - } - log::info!( + return Ok(Some((inscription_id, district))); + } + log::info!( "duplicate district! number: {} content: {} inscription_id {}", district.number, std::str::from_utf8(content).unwrap(), inscription_id, ); - } } - Ok(None) + } + Ok(None) } diff --git a/src/okx/protocol/protocol_manager.rs b/src/okx/protocol/protocol_manager.rs index ffed215196..7331895968 100644 --- a/src/okx/protocol/protocol_manager.rs +++ b/src/okx/protocol/protocol_manager.rs @@ -26,7 +26,7 @@ impl ProtocolManager { } } - pub(crate) fn index_block( + pub(crate) fn index_block( &self, context: &mut T, block: &BlockData, @@ -53,12 +53,12 @@ impl ProtocolManager { if let Some(tx_operations) = operations.get(txid) { // save all transaction operations to ord database. if self.config.enable_ord_receipts - && context.block_height()>= self.config.first_inscription_height + && context.block_height() >= self.config.first_inscription_height { let start = Instant::now(); - context.save_transaction_operations(txid, tx_operations).map_err(|e|{ - anyhow!("failed to save transaction operations! error: {}", e) - })?; + context + .save_transaction_operations(txid, tx_operations) + .map_err(|e| anyhow!("failed to save transaction operations! error: {}", e))?; inscriptions_size += tx_operations.len(); cost1 += start.elapsed().as_micros(); } diff --git a/src/okx/protocol/resolve_manager.rs b/src/okx/protocol/resolve_manager.rs index a6493b80f9..591b1a1593 100644 --- a/src/okx/protocol/resolve_manager.rs +++ b/src/okx/protocol/resolve_manager.rs @@ -1,73 +1,69 @@ use crate::inscriptions::ParsedEnvelope; use { - super::*, - crate::{ - okx::{datastore::ord::operation::InscriptionOp, protocol::Message}, - Inscription, Result, - }, - bitcoin::Transaction, + super::*, + crate::{ + okx::{datastore::ord::operation::InscriptionOp, protocol::Message}, + Inscription, Result, + }, + bitcoin::Transaction, }; pub struct MsgResolveManager { - config: ProtocolConfig, + config: ProtocolConfig, } impl MsgResolveManager { - pub fn new(config: ProtocolConfig) -> Self { - Self { config } - } + pub fn new(config: ProtocolConfig) -> Self { + Self { config } + } - pub fn resolve_message( - &self, - context: &T, - tx: &Transaction, - operations: &[InscriptionOp], - ) -> Result> { - log::debug!( + pub fn resolve_message( + &self, + context: &T, + tx: &Transaction, + operations: &[InscriptionOp], + ) -> Result> { + log::debug!( "Resolve Manager indexed transaction {}, operations size: {}, data: {:?}", tx.txid(), operations.len(), operations ); - let mut messages = Vec::new(); - let mut operation_iter = operations.iter().peekable(); - let new_inscriptions = ParsedEnvelope::from_transaction(tx) - .into_iter() - .map(|v| v.payload) - .collect::>(); + let mut messages = Vec::new(); + let mut operation_iter = operations.iter().peekable(); + let new_inscriptions = ParsedEnvelope::from_transaction(tx) + .into_iter() + .map(|v| v.payload) + .collect::>(); - for input in &tx.input { - // "operations" is a list of all the operations in the current block, and they are ordered. - // We just need to find the operation corresponding to the current transaction here. - while let Some(operation) = operation_iter.peek() { - if operation.old_satpoint.outpoint != input.previous_output { - break; - } - let operation = operation_iter.next().unwrap(); + for input in &tx.input { + // "operations" is a list of all the operations in the current block, and they are ordered. + // We just need to find the operation corresponding to the current transaction here. + while let Some(operation) = operation_iter.peek() { + if operation.old_satpoint.outpoint != input.previous_output { + break; + } + let operation = operation_iter.next().unwrap(); - // Parse BRC20 message through inscription operation. - if self - .config - .first_brc20_height - .map(|height| context.block_height() >= height) - .unwrap_or(false) - { - if let Some(msg) = brc20::Message::resolve( - context, - &new_inscriptions, - operation, - )? { - log::debug!( + // Parse BRC20 message through inscription operation. + if self + .config + .first_brc20_height + .map(|height| context.block_height() >= height) + .unwrap_or(false) + { + if let Some(msg) = brc20::Message::resolve(context, &new_inscriptions, operation)? { + log::debug!( "BRC20 resolved the message from {:?}, msg {:?}", operation, msg ); - messages.push(Message::BRC20(msg)); - continue; - } - } - } + messages.push(Message::BRC20(msg)); + continue; + } } - Ok(messages) + } } + Ok(messages) + } } diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index 3fe7d08d15..b8cac64aa7 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -1,443 +1,553 @@ -use std::cell::RefCell; -use std::collections::HashMap; -use std::marker::PhantomData; -use std::ops::{Deref, DerefMut}; -use std::rc::Rc; -use anyhow::anyhow; -use bitcoin::{Network, Txid}; -use redb::{ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition}; -use crate::{InscriptionId, SatPoint}; -use crate::index::{BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, InscriptionEntryValue, InscriptionIdValue, OUTPOINT_TO_ENTRY, OutPointValue, SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, TxidValue}; use crate::index::entry::Entry; use crate::index::simulator::processor::IndexWrapper; -use crate::okx::datastore::brc20::{Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferableLog, TransferInfo}; +use crate::index::{ + InscriptionEntryValue, InscriptionIdValue, OutPointValue, TxidValue, BRC20_BALANCES, + BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, BRC20_TOKEN, BRC20_TRANSFERABLELOG, + COLLECTIONS_INSCRIPTION_ID_TO_KINDS, COLLECTIONS_KEY_TO_INSCRIPTION_ID, OUTPOINT_TO_ENTRY, + SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, +}; +use crate::okx::datastore::brc20::redb::table::{ + get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, + get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick, + insert_inscribe_transfer_inscription, insert_token_info, insert_transferable, + remove_inscribe_transfer_inscription, remove_transferable, save_transaction_receipts, + update_token_balance, +}; use crate::okx::datastore::brc20::redb::{script_tick_id_key, script_tick_key}; -use crate::okx::datastore::brc20::redb::table::{get_balance, get_balances, get_inscribe_transfer_inscription, get_token_info, get_tokens_info, get_transaction_receipts, get_transferable, get_transferable_by_id, get_transferable_by_tick, insert_inscribe_transfer_inscription, insert_token_info, insert_transferable, remove_inscribe_transfer_inscription, remove_transferable, save_transaction_receipts, update_token_balance}; +use crate::okx::datastore::brc20::{ + Balance, Brc20Reader, Brc20ReaderWriter, Receipt, Tick, TokenInfo, TransferInfo, TransferableLog, +}; use crate::okx::datastore::cache::CacheTableIndex; -use crate::okx::datastore::ord::{InscriptionOp, OrdReader, OrdReaderWriter}; use crate::okx::datastore::ord::collections::CollectionKind; -use crate::okx::datastore::ord::redb::table::{get_collection_inscription_id, get_collections_of_inscription, get_inscription_number_by_sequence_number, get_transaction_operations, get_txout_by_outpoint, save_transaction_operations, set_inscription_attributes, set_inscription_by_collection_key}; +use crate::okx::datastore::ord::redb::table::{ + get_collection_inscription_id, get_collections_of_inscription, + get_inscription_number_by_sequence_number, get_transaction_operations, get_txout_by_outpoint, + save_transaction_operations, set_inscription_attributes, set_inscription_by_collection_key, +}; +use crate::okx::datastore::ord::{InscriptionOp, OrdReader, OrdReaderWriter}; use crate::okx::datastore::ScriptKey; -use crate::okx::protocol::ContextTrait; use crate::okx::protocol::trace::TraceNode; +use crate::okx::protocol::ContextTrait; +use crate::{InscriptionId, SatPoint}; +use anyhow::anyhow; +use bitcoin::{Network, Txid}; +use redb::{ReadOnlyTable, RedbKey, RedbValue, Table, TableDefinition}; +use std::cell::RefCell; +use std::collections::HashMap; +use std::marker::PhantomData; +use std::ops::{Deref, DerefMut}; +use std::rc::Rc; #[allow(non_snake_case)] #[derive(Clone)] pub struct SimulateContext<'a, 'db, 'txn> { - pub network: Network, - pub current_height: u32, - pub current_block_time: u32, - pub internal_index: IndexWrapper, - pub(crate) ORD_TX_TO_OPERATIONS: Rc>>, - pub(crate) COLLECTIONS_KEY_TO_INSCRIPTION_ID: + pub network: Network, + pub current_height: u32, + pub current_block_time: u32, + pub internal_index: IndexWrapper, + pub(crate) ORD_TX_TO_OPERATIONS: Rc>>, + pub(crate) COLLECTIONS_KEY_TO_INSCRIPTION_ID: Rc>>, - pub(crate) COLLECTIONS_INSCRIPTION_ID_TO_KINDS: + pub(crate) COLLECTIONS_INSCRIPTION_ID_TO_KINDS: Rc>>, - pub(crate) SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: + pub(crate) SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY: Rc>>, - pub(crate) OUTPOINT_TO_ENTRY: Rc>>, - - // BRC20 tables - pub(crate) BRC20_BALANCES: Rc>>, - pub(crate) BRC20_TOKEN: Rc>>, - pub(crate) BRC20_EVENTS: Rc>>, - pub(crate) BRC20_TRANSFERABLELOG: Rc>>, - pub(crate) BRC20_INSCRIBE_TRANSFER: Rc>>, - pub traces: Rc>>, - pub brc20_receipts: Rc>>, - pub _marker_a: PhantomData<&'a ()>, + pub(crate) OUTPOINT_TO_ENTRY: + Rc>>, + + // BRC20 tables + pub(crate) BRC20_BALANCES: Rc>>, + pub(crate) BRC20_TOKEN: Rc>>, + pub(crate) BRC20_EVENTS: Rc>>, + pub(crate) BRC20_TRANSFERABLELOG: Rc>>, + pub(crate) BRC20_INSCRIBE_TRANSFER: + Rc>>, + pub traces: Rc>>, + pub brc20_receipts: Rc>>, + pub _marker_a: PhantomData<&'a ()>, } impl<'a, 'db, 'txn> Brc20Reader for SimulateContext<'a, 'db, 'txn> { - type Error = anyhow::Error; - - fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { - let balances = self.BRC20_BALANCES.borrow(); - let table = balances.deref(); - let simulate = get_balances(table, script_key)?; - let internal = self.use_internal_table(BRC20_BALANCES, |v| { - get_balances(&v, script_key) - })?; - let mut simulate_balances: HashMap = simulate.into_iter() - .map(|v| { - (v.tick.clone(), v.clone()) - }).collect(); - for node in internal { - let v = simulate_balances.entry(node.tick.clone()).or_insert(node.clone()); - v.transferable_balance = v.transferable_balance + node.transferable_balance; - v.overall_balance = v.overall_balance + node.overall_balance; - } - let ret = simulate_balances - .into_iter() - .map(|(_, v)| { - v.clone() - }).collect(); - Ok(ret) + type Error = anyhow::Error; + + fn get_balances(&self, script_key: &ScriptKey) -> crate::Result, Self::Error> { + let balances = self.BRC20_BALANCES.borrow(); + let table = balances.deref(); + let simulate = get_balances(table, script_key)?; + let internal = self.use_internal_table(BRC20_BALANCES, |v| get_balances(&v, script_key))?; + let mut simulate_balances: HashMap = simulate + .into_iter() + .map(|v| (v.tick.clone(), v.clone())) + .collect(); + for node in internal { + let v = simulate_balances + .entry(node.tick.clone()) + .or_insert(node.clone()); + v.transferable_balance = v.transferable_balance + node.transferable_balance; + v.overall_balance = v.overall_balance + node.overall_balance; } - - fn get_balance(&self, script_key: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { - let table = self.BRC20_BALANCES.borrow(); - let table = table.deref(); - let ret = get_balance(table, script_key, tick)?; - if let Some(ret) = ret { - return Ok(Some(ret)); - } - self.use_internal_table(BRC20_BALANCES, |table| { - get_balance(&table, script_key, tick) - }) + let ret = simulate_balances + .into_iter() + .map(|(_, v)| v.clone()) + .collect(); + Ok(ret) + } + + fn get_balance( + &self, + script_key: &ScriptKey, + tick: &Tick, + ) -> crate::Result, Self::Error> { + let table = self.BRC20_BALANCES.borrow(); + let table = table.deref(); + let ret = get_balance(table, script_key, tick)?; + if let Some(ret) = ret { + return Ok(Some(ret)); } - - fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { - let table = self.BRC20_TOKEN.borrow(); - let table = table.deref(); - let ret = get_token_info(table, tick)?; - if let Some(ret) = ret { - return Ok(Some(ret)); - } - self.use_internal_table(BRC20_TOKEN, |table| { - get_token_info(&table, tick) - }) + self.use_internal_table(BRC20_BALANCES, |table| { + get_balance(&table, script_key, tick) + }) + } + + fn get_token_info(&self, tick: &Tick) -> crate::Result, Self::Error> { + let table = self.BRC20_TOKEN.borrow(); + let table = table.deref(); + let ret = get_token_info(table, tick)?; + if let Some(ret) = ret { + return Ok(Some(ret)); } - - fn get_tokens_info(&self) -> crate::Result, Self::Error> { - let binding = self.BRC20_TOKEN.borrow(); - let table = binding.deref(); - let ret = get_tokens_info(table)?; - let mut token_map = ret.into_iter().map(|v| { - (v.tick.clone(), v) - }).collect::>(); - let internal = self.use_internal_table(BRC20_TOKEN, |table| { - get_tokens_info(&table) - })?; - for node in internal { - if !token_map.contains_key(&node.tick) { - token_map.insert(node.tick.clone(), node.clone()); - } - } - let ret = token_map.into_iter().map(|(_, v)| { - v - }).collect(); - Ok(ret) + self.use_internal_table(BRC20_TOKEN, |table| get_token_info(&table, tick)) + } + + fn get_tokens_info(&self) -> crate::Result, Self::Error> { + let binding = self.BRC20_TOKEN.borrow(); + let table = binding.deref(); + let ret = get_tokens_info(table)?; + let mut token_map = ret + .into_iter() + .map(|v| (v.tick.clone(), v)) + .collect::>(); + let internal = self.use_internal_table(BRC20_TOKEN, |table| get_tokens_info(&table))?; + for node in internal { + if !token_map.contains_key(&node.tick) { + token_map.insert(node.tick.clone(), node.clone()); + } } - - fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { - let binding = self.BRC20_EVENTS.borrow(); - let table = binding.deref(); - let ret = get_transaction_receipts(table, txid)?; - let mut simulate_receipts = ret.into_iter().map(|v| { - (v.inscription_id.clone(), v) - }).collect::>(); - let internal = self.use_internal_table(BRC20_EVENTS, |table| { - get_transaction_receipts(&table, txid) - })?; - for node in internal { - if !simulate_receipts.contains_key(&node.inscription_id) { - simulate_receipts.insert(node.inscription_id.clone(), node.clone()); - } - } - let ret = simulate_receipts.into_iter().map(|(_, v)| { - v - }).collect(); - Ok(ret) + let ret = token_map.into_iter().map(|(_, v)| v).collect(); + Ok(ret) + } + + fn get_transaction_receipts(&self, txid: &Txid) -> crate::Result, Self::Error> { + let binding = self.BRC20_EVENTS.borrow(); + let table = binding.deref(); + let ret = get_transaction_receipts(table, txid)?; + let mut simulate_receipts = ret + .into_iter() + .map(|v| (v.inscription_id.clone(), v)) + .collect::>(); + let internal = + self.use_internal_table(BRC20_EVENTS, |table| get_transaction_receipts(&table, txid))?; + for node in internal { + if !simulate_receipts.contains_key(&node.inscription_id) { + simulate_receipts.insert(node.inscription_id.clone(), node.clone()); + } } - - fn get_transferable(&self, script: &ScriptKey) -> crate::Result, Self::Error> { - let binding = self.BRC20_TRANSFERABLELOG.borrow(); - let table = binding.deref(); - let ret = get_transferable(table, script)?; - let mut simulate_transferable = ret.into_iter().map(|v| { - (v.inscription_id.clone(), v) - }).collect::>(); - let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { - get_transferable(&table, script) - })?; - for node in internal { - if !simulate_transferable.contains_key(&node.inscription_id) { - simulate_transferable.insert(node.inscription_id.clone(), node.clone()); - } - } - let ret = simulate_transferable.into_iter().map(|(_, v)| { - v - }).collect(); - Ok(ret) + let ret = simulate_receipts.into_iter().map(|(_, v)| v).collect(); + Ok(ret) + } + + fn get_transferable( + &self, + script: &ScriptKey, + ) -> crate::Result, Self::Error> { + let binding = self.BRC20_TRANSFERABLELOG.borrow(); + let table = binding.deref(); + let ret = get_transferable(table, script)?; + let mut simulate_transferable = ret + .into_iter() + .map(|v| (v.inscription_id.clone(), v)) + .collect::>(); + let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable(&table, script) + })?; + for node in internal { + if !simulate_transferable.contains_key(&node.inscription_id) { + simulate_transferable.insert(node.inscription_id.clone(), node.clone()); + } } - - fn get_transferable_by_tick(&self, script: &ScriptKey, tick: &Tick) -> crate::Result, Self::Error> { - let binding = self.BRC20_TRANSFERABLELOG.borrow(); - let table = binding.deref(); - let ret = get_transferable_by_tick(table, script, tick)?; - let mut simulate_transferable = ret.into_iter().map(|v| { - (v.inscription_id.clone(), v) - }).collect::>(); - let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { - get_transferable_by_tick(&table, script, tick) - })?; - for node in internal { - if !simulate_transferable.contains_key(&node.inscription_id) { - simulate_transferable.insert(node.inscription_id.clone(), node.clone()); - } - } - let ret = simulate_transferable.into_iter().map(|(_, v)| { - v - }).collect(); - Ok(ret) + let ret = simulate_transferable.into_iter().map(|(_, v)| v).collect(); + Ok(ret) + } + + fn get_transferable_by_tick( + &self, + script: &ScriptKey, + tick: &Tick, + ) -> crate::Result, Self::Error> { + let binding = self.BRC20_TRANSFERABLELOG.borrow(); + let table = binding.deref(); + let ret = get_transferable_by_tick(table, script, tick)?; + let mut simulate_transferable = ret + .into_iter() + .map(|v| (v.inscription_id.clone(), v)) + .collect::>(); + let internal = self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable_by_tick(&table, script, tick) + })?; + for node in internal { + if !simulate_transferable.contains_key(&node.inscription_id) { + simulate_transferable.insert(node.inscription_id.clone(), node.clone()); + } } - - fn get_transferable_by_id(&self, script: &ScriptKey, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { - let binding = self.BRC20_TRANSFERABLELOG.borrow(); - let table = binding.deref(); - let ret = get_transferable_by_id(table, script, inscription_id)?; - if let Some(ret) = ret { - return Ok(Some(ret)); - } - self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { - get_transferable_by_id(&table, script, inscription_id) - }) + let ret = simulate_transferable.into_iter().map(|(_, v)| v).collect(); + Ok(ret) + } + + fn get_transferable_by_id( + &self, + script: &ScriptKey, + inscription_id: &InscriptionId, + ) -> crate::Result, Self::Error> { + let binding = self.BRC20_TRANSFERABLELOG.borrow(); + let table = binding.deref(); + let ret = get_transferable_by_id(table, script, inscription_id)?; + if let Some(ret) = ret { + return Ok(Some(ret)); } - - fn get_inscribe_transfer_inscription(&self, inscription_id: &InscriptionId) -> crate::Result, Self::Error> { - let binding = self.BRC20_INSCRIBE_TRANSFER.borrow(); - let table = binding.deref(); - let ret = get_inscribe_transfer_inscription(table, inscription_id)?; - if let Some(ret) = ret { - return Ok(Some(ret)); - } - self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { - get_inscribe_transfer_inscription(&table, inscription_id) - }) + self.use_internal_table(BRC20_TRANSFERABLELOG, |table| { + get_transferable_by_id(&table, script, inscription_id) + }) + } + + fn get_inscribe_transfer_inscription( + &self, + inscription_id: &InscriptionId, + ) -> crate::Result, Self::Error> { + let binding = self.BRC20_INSCRIBE_TRANSFER.borrow(); + let table = binding.deref(); + let ret = get_inscribe_transfer_inscription(table, inscription_id)?; + if let Some(ret) = ret { + return Ok(Some(ret)); } + self.use_internal_table(BRC20_INSCRIBE_TRANSFER, |table| { + get_inscribe_transfer_inscription(&table, inscription_id) + }) + } } impl<'a, 'db, 'txn> Brc20ReaderWriter for SimulateContext<'a, 'db, 'txn> { - fn update_token_balance(&mut self, script_key: &ScriptKey, new_balance: Balance) -> crate::Result<(), Self::Error> { - let mut traces = self.traces.borrow_mut(); - let binding = script_tick_key(script_key, &new_balance.tick); - let key = binding.as_str(); - let key = key.as_bytes().to_vec(); - traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_BALANCES, key }); - let mut table = self.BRC20_BALANCES.borrow_mut(); - update_token_balance(&mut table, script_key, new_balance) - } - - fn insert_token_info(&mut self, tick: &Tick, new_info: &TokenInfo) -> crate::Result<(), Self::Error> { - let mut traces = self.traces.borrow_mut(); - let binding = tick.to_lowercase().hex(); - let key = binding.as_str(); - let key = key.as_bytes().to_vec(); - traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_TOKEN, key }); - - let mut binding = self.BRC20_TOKEN.borrow_mut(); - let table = binding.deref_mut(); - insert_token_info(table, tick, new_info) - } - - fn update_mint_token_info(&mut self, tick: &Tick, minted_amt: u128, minted_block_number: u32) -> crate::Result<(), Self::Error> { - let info = self.get_token_info(tick)?; - if info.is_none() { - return Err(anyhow!(format!("token {:?} not exist", tick.to_lowercase().to_string()))); - } - let mut info = info.unwrap(); - let mut binding = self.BRC20_TOKEN.borrow_mut(); - let table = binding.deref_mut(); - info.minted = minted_amt; - info.latest_mint_number = minted_block_number; - insert_token_info(table, tick, &info) - } - - fn save_transaction_receipts(&mut self, txid: &Txid, receipt: &[Receipt]) -> crate::Result<(), Self::Error> { - let mut traces = self.traces.borrow_mut(); - let key = rmp_serde::to_vec(txid).unwrap(); - traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_EVENTS, key }); - let mut receipts = self.brc20_receipts.borrow_mut(); - receipts.extend_from_slice(receipt); - let mut table = self.BRC20_EVENTS.borrow_mut(); - save_transaction_receipts(&mut table, txid, receipt) - } - - fn insert_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription: &TransferableLog) -> crate::Result<(), Self::Error> { - let mut traces = self.traces.borrow_mut(); - let binding = script_tick_id_key(script, tick, &inscription.inscription_id); - let key = binding.as_str(); - let key = key.as_bytes().to_vec(); - traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, key }); - let mut table = self.BRC20_TRANSFERABLELOG.borrow_mut(); - insert_transferable(&mut table, script, tick, inscription) - } - - fn remove_transferable(&mut self, script: &ScriptKey, tick: &Tick, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - let mut table = self.BRC20_TRANSFERABLELOG.borrow_mut(); - remove_transferable(&mut table, script, tick, inscription_id) - } - - fn insert_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId, transfer_info: TransferInfo) -> crate::Result<(), Self::Error> { - let mut traces = self.traces.borrow_mut(); - let key = &inscription_id.store(); - let key = InscriptionIdValue::as_bytes(&key); - traces.push(TraceNode { trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, key }); - let mut table = self.BRC20_INSCRIBE_TRANSFER.borrow_mut(); - insert_inscribe_transfer_inscription(&mut table, inscription_id, transfer_info) - } - - fn remove_inscribe_transfer_inscription(&mut self, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - let mut table = self.BRC20_INSCRIBE_TRANSFER.borrow_mut(); - remove_inscribe_transfer_inscription(&mut table, inscription_id) + fn update_token_balance( + &mut self, + script_key: &ScriptKey, + new_balance: Balance, + ) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let binding = script_tick_key(script_key, &new_balance.tick); + let key = binding.as_str(); + let key = key.as_bytes().to_vec(); + traces.push(TraceNode { + trace_type: CacheTableIndex::BRC20_BALANCES, + key, + }); + let mut table = self.BRC20_BALANCES.borrow_mut(); + update_token_balance(&mut table, script_key, new_balance) + } + + fn insert_token_info( + &mut self, + tick: &Tick, + new_info: &TokenInfo, + ) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let binding = tick.to_lowercase().hex(); + let key = binding.as_str(); + let key = key.as_bytes().to_vec(); + traces.push(TraceNode { + trace_type: CacheTableIndex::BRC20_TOKEN, + key, + }); + + let mut binding = self.BRC20_TOKEN.borrow_mut(); + let table = binding.deref_mut(); + insert_token_info(table, tick, new_info) + } + + fn update_mint_token_info( + &mut self, + tick: &Tick, + minted_amt: u128, + minted_block_number: u32, + ) -> crate::Result<(), Self::Error> { + let info = self.get_token_info(tick)?; + if info.is_none() { + return Err(anyhow!(format!( + "token {:?} not exist", + tick.to_lowercase().to_string() + ))); } + let mut info = info.unwrap(); + let mut binding = self.BRC20_TOKEN.borrow_mut(); + let table = binding.deref_mut(); + info.minted = minted_amt; + info.latest_mint_number = minted_block_number; + insert_token_info(table, tick, &info) + } + + fn save_transaction_receipts( + &mut self, + txid: &Txid, + receipt: &[Receipt], + ) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let key = rmp_serde::to_vec(txid).unwrap(); + traces.push(TraceNode { + trace_type: CacheTableIndex::BRC20_EVENTS, + key, + }); + let mut receipts = self.brc20_receipts.borrow_mut(); + receipts.extend_from_slice(receipt); + let mut table = self.BRC20_EVENTS.borrow_mut(); + save_transaction_receipts(&mut table, txid, receipt) + } + + fn insert_transferable( + &mut self, + script: &ScriptKey, + tick: &Tick, + inscription: &TransferableLog, + ) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let binding = script_tick_id_key(script, tick, &inscription.inscription_id); + let key = binding.as_str(); + let key = key.as_bytes().to_vec(); + traces.push(TraceNode { + trace_type: CacheTableIndex::BRC20_TRANSFERABLELOG, + key, + }); + let mut table = self.BRC20_TRANSFERABLELOG.borrow_mut(); + insert_transferable(&mut table, script, tick, inscription) + } + + fn remove_transferable( + &mut self, + script: &ScriptKey, + tick: &Tick, + inscription_id: &InscriptionId, + ) -> crate::Result<(), Self::Error> { + let mut table = self.BRC20_TRANSFERABLELOG.borrow_mut(); + remove_transferable(&mut table, script, tick, inscription_id) + } + + fn insert_inscribe_transfer_inscription( + &mut self, + inscription_id: &InscriptionId, + transfer_info: TransferInfo, + ) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let key = &inscription_id.store(); + let key = InscriptionIdValue::as_bytes(&key); + traces.push(TraceNode { + trace_type: CacheTableIndex::BRC20_INSCRIBE_TRANSFER, + key, + }); + let mut table = self.BRC20_INSCRIBE_TRANSFER.borrow_mut(); + insert_inscribe_transfer_inscription(&mut table, inscription_id, transfer_info) + } + + fn remove_inscribe_transfer_inscription( + &mut self, + inscription_id: &InscriptionId, + ) -> crate::Result<(), Self::Error> { + let mut table = self.BRC20_INSCRIBE_TRANSFER.borrow_mut(); + remove_inscribe_transfer_inscription(&mut table, inscription_id) + } } impl<'a, 'db, 'txn> OrdReaderWriter for SimulateContext<'a, 'db, 'txn> { - fn save_transaction_operations(&mut self, txid: &Txid, operations: &[InscriptionOp]) -> crate::Result<(), Self::Error> { - let mut traces = self.traces.borrow_mut(); - let key = &txid.store(); - let key = TxidValue::as_slice(key).to_vec(); - traces.push(TraceNode { trace_type: CacheTableIndex::ORD_TX_TO_OPERATIONS, key }); - let mut table = self.ORD_TX_TO_OPERATIONS.borrow_mut(); - save_transaction_operations(&mut table, txid, operations) - } - - fn set_inscription_by_collection_key(&mut self, key: &str, inscription_id: &InscriptionId) -> crate::Result<(), Self::Error> { - let mut traces = self.traces.borrow_mut(); - let trace_key = key.as_bytes().to_vec(); - traces.push(TraceNode { trace_type: CacheTableIndex::COLLECTIONS_KEY_TO_INSCRIPTION_ID, key: trace_key }); - let mut table = self.COLLECTIONS_KEY_TO_INSCRIPTION_ID.borrow_mut(); - set_inscription_by_collection_key(&mut table, key, inscription_id) - } - - fn set_inscription_attributes(&mut self, inscription_id: &InscriptionId, kind: &[CollectionKind]) -> crate::Result<(), Self::Error> { - let mut traces = self.traces.borrow_mut(); - let key = inscription_id.store(); - let key = InscriptionIdValue::as_bytes(&key); - traces.push(TraceNode { trace_type: CacheTableIndex::COLLECTIONS_INSCRIPTION_ID_TO_KINDS, key }); - let mut table = self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS.borrow_mut(); - set_inscription_attributes( - &mut table, - inscription_id, - kind, - ) - } + fn save_transaction_operations( + &mut self, + txid: &Txid, + operations: &[InscriptionOp], + ) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let key = &txid.store(); + let key = TxidValue::as_slice(key).to_vec(); + traces.push(TraceNode { + trace_type: CacheTableIndex::ORD_TX_TO_OPERATIONS, + key, + }); + let mut table = self.ORD_TX_TO_OPERATIONS.borrow_mut(); + save_transaction_operations(&mut table, txid, operations) + } + + fn set_inscription_by_collection_key( + &mut self, + key: &str, + inscription_id: &InscriptionId, + ) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let trace_key = key.as_bytes().to_vec(); + traces.push(TraceNode { + trace_type: CacheTableIndex::COLLECTIONS_KEY_TO_INSCRIPTION_ID, + key: trace_key, + }); + let mut table = self.COLLECTIONS_KEY_TO_INSCRIPTION_ID.borrow_mut(); + set_inscription_by_collection_key(&mut table, key, inscription_id) + } + + fn set_inscription_attributes( + &mut self, + inscription_id: &InscriptionId, + kind: &[CollectionKind], + ) -> crate::Result<(), Self::Error> { + let mut traces = self.traces.borrow_mut(); + let key = inscription_id.store(); + let key = InscriptionIdValue::as_bytes(&key); + traces.push(TraceNode { + trace_type: CacheTableIndex::COLLECTIONS_INSCRIPTION_ID_TO_KINDS, + key, + }); + let mut table = self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS.borrow_mut(); + set_inscription_attributes(&mut table, inscription_id, kind) + } } impl<'a, 'db, 'txn> OrdReader for SimulateContext<'a, 'db, 'txn> { - type Error = anyhow::Error; - - fn get_inscription_number_by_sequence_number(&self, sequence_number: u32) -> crate::Result { - let binding = self.SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY.borrow(); - let table = binding.deref(); - let ret = get_inscription_number_by_sequence_number( - table, - sequence_number, - ) - .map_err(|e| anyhow!("failed to get inscription number from state! error: {e}"))?; - if let Some(ret) = ret { - return Ok(ret); - } - self.use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| { - get_inscription_number_by_sequence_number( - &table, - sequence_number, - ) - }).map_err(|e| anyhow!("failed to get inscription number from state! error: {e}"))?.ok_or(anyhow!( - "failed to get inscription number! error: sequence number {} not found", - sequence_number - )) + type Error = anyhow::Error; + + fn get_inscription_number_by_sequence_number( + &self, + sequence_number: u32, + ) -> crate::Result { + let binding = self.SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY.borrow(); + let table = binding.deref(); + let ret = get_inscription_number_by_sequence_number(table, sequence_number) + .map_err(|e| anyhow!("failed to get inscription number from state! error: {e}"))?; + if let Some(ret) = ret { + return Ok(ret); } - - fn get_script_key_on_satpoint(&mut self, satpoint: &SatPoint, network: Network) -> crate::Result { - let binding = self.OUTPOINT_TO_ENTRY.borrow(); - let table = binding.deref(); - if let Some(tx_out) = get_txout_by_outpoint(table, &satpoint.outpoint)? - { - return Ok(ScriptKey::from_script(&tx_out.script_pubkey, network)); - } else { - let ret = self.use_internal_table(OUTPOINT_TO_ENTRY, |table| { - get_txout_by_outpoint(&table, &satpoint.outpoint) - })?; - if let Some(ret) = ret { - return Ok(ScriptKey::from_script(&ret.script_pubkey, network)); - } - } - return Err(anyhow!("failed to get tx out! error: outpoint {} not found", - &satpoint.outpoint)); + self + .use_internal_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY, |table| { + get_inscription_number_by_sequence_number(&table, sequence_number) + }) + .map_err(|e| anyhow!("failed to get inscription number from state! error: {e}"))? + .ok_or(anyhow!( + "failed to get inscription number! error: sequence number {} not found", + sequence_number + )) + } + + fn get_script_key_on_satpoint( + &mut self, + satpoint: &SatPoint, + network: Network, + ) -> crate::Result { + let binding = self.OUTPOINT_TO_ENTRY.borrow(); + let table = binding.deref(); + if let Some(tx_out) = get_txout_by_outpoint(table, &satpoint.outpoint)? { + return Ok(ScriptKey::from_script(&tx_out.script_pubkey, network)); + } else { + let ret = self.use_internal_table(OUTPOINT_TO_ENTRY, |table| { + get_txout_by_outpoint(&table, &satpoint.outpoint) + })?; + if let Some(ret) = ret { + return Ok(ScriptKey::from_script(&ret.script_pubkey, network)); + } } - - fn get_transaction_operations(&self, txid: &Txid) -> crate::Result, Self::Error> { - let binding = self.ORD_TX_TO_OPERATIONS.borrow(); - let table = binding.deref(); - let simulate = get_transaction_operations(table, txid)?; - let mut simulate_operations: HashMap = simulate.into_iter() - .map(|v| { - (v.inscription_id.clone(), v.clone()) - }).collect(); - let internal = self.use_internal_table(BRC20_EVENTS, |table| { - get_transaction_operations(&table, txid) - })?; - for node in internal { - if simulate_operations.contains_key(&node.inscription_id) { - continue; - } - simulate_operations.insert(node.inscription_id.clone(), node.clone()); - } - let ret = simulate_operations.into_iter().map(|(_, v)| { - v - }).collect(); - Ok(ret) + return Err(anyhow!( + "failed to get tx out! error: outpoint {} not found", + &satpoint.outpoint + )); + } + + fn get_transaction_operations( + &self, + txid: &Txid, + ) -> crate::Result, Self::Error> { + let binding = self.ORD_TX_TO_OPERATIONS.borrow(); + let table = binding.deref(); + let simulate = get_transaction_operations(table, txid)?; + let mut simulate_operations: HashMap = simulate + .into_iter() + .map(|v| (v.inscription_id.clone(), v.clone())) + .collect(); + let internal = self.use_internal_table(BRC20_EVENTS, |table| { + get_transaction_operations(&table, txid) + })?; + for node in internal { + if simulate_operations.contains_key(&node.inscription_id) { + continue; + } + simulate_operations.insert(node.inscription_id.clone(), node.clone()); } - - fn get_collections_of_inscription(&self, inscription_id: &InscriptionId) -> crate::Result>, Self::Error> { - let binding = self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS.borrow(); - let table = binding.deref(); - let simulate = get_collections_of_inscription(table, inscription_id)?; - let mut simulate = if let Some(ret) = simulate { - ret - } else { - vec![] - }; - - let internal = self.use_internal_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS, |table| { - get_collections_of_inscription(&table, inscription_id) - })?; - if let Some(internal) = internal { - simulate.extend_from_slice(&internal); - } - if simulate.is_empty() { - return Ok(None); - } - return Ok(Some(simulate)); + let ret = simulate_operations.into_iter().map(|(_, v)| v).collect(); + Ok(ret) + } + + fn get_collections_of_inscription( + &self, + inscription_id: &InscriptionId, + ) -> crate::Result>, Self::Error> { + let binding = self.COLLECTIONS_INSCRIPTION_ID_TO_KINDS.borrow(); + let table = binding.deref(); + let simulate = get_collections_of_inscription(table, inscription_id)?; + let mut simulate = if let Some(ret) = simulate { + ret + } else { + vec![] + }; + + let internal = self.use_internal_table(COLLECTIONS_INSCRIPTION_ID_TO_KINDS, |table| { + get_collections_of_inscription(&table, inscription_id) + })?; + if let Some(internal) = internal { + simulate.extend_from_slice(&internal); } - - fn get_collection_inscription_id(&self, collection_key: &str) -> crate::Result, Self::Error> { - let binding = self.COLLECTIONS_KEY_TO_INSCRIPTION_ID.borrow(); - let table = binding.deref(); - let ret = get_collection_inscription_id(table, collection_key)?; - if let Some(ret) = ret { - return Ok(Some(ret)); - } - self.use_internal_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID, |table| { - get_collection_inscription_id(&table, collection_key) - }) + if simulate.is_empty() { + return Ok(None); + } + return Ok(Some(simulate)); + } + + fn get_collection_inscription_id( + &self, + collection_key: &str, + ) -> crate::Result, Self::Error> { + let binding = self.COLLECTIONS_KEY_TO_INSCRIPTION_ID.borrow(); + let table = binding.deref(); + let ret = get_collection_inscription_id(table, collection_key)?; + if let Some(ret) = ret { + return Ok(Some(ret)); } + self.use_internal_table(COLLECTIONS_KEY_TO_INSCRIPTION_ID, |table| { + get_collection_inscription_id(&table, collection_key) + }) + } } impl<'a, 'db, 'txn> ContextTrait for SimulateContext<'a, 'db, 'txn> { - fn block_height(&self) -> u32 { - self.current_height - } + fn block_height(&self) -> u32 { + self.current_height + } - fn network(&self) -> Network { - self.network.clone() - } + fn network(&self) -> Network { + self.network.clone() + } - fn block_time(&self) -> u32 { - self.current_block_time - } + fn block_time(&self) -> u32 { + self.current_block_time + } } impl<'a, 'db, 'txn> SimulateContext<'a, 'db, 'txn> { - fn use_internal_table(&self, - table_def: TableDefinition, - f: impl FnOnce(ReadOnlyTable) -> crate::Result) -> crate::Result { - let rtx = self.internal_index.internal.begin_read()?; - let table = rtx.0.open_table(table_def)?; - let ret = f(table); - ret - } -} \ No newline at end of file + fn use_internal_table( + &self, + table_def: TableDefinition, + f: impl FnOnce(ReadOnlyTable) -> crate::Result, + ) -> crate::Result { + let rtx = self.internal_index.internal.begin_read()?; + let table = rtx.0.open_table(table_def)?; + let ret = f(table); + ret + } +} diff --git a/src/okx/protocol/trace.rs b/src/okx/protocol/trace.rs index ed6f55292b..5c82ab4797 100644 --- a/src/okx/protocol/trace.rs +++ b/src/okx/protocol/trace.rs @@ -1,24 +1,24 @@ -use serde::{Deserialize, Serialize}; use crate::okx::datastore::cache::CacheTableIndex; +use serde::{Deserialize, Serialize}; #[derive(Clone, Default, Serialize, Deserialize)] pub struct BalanceDelta { - pub origin_overall_balance_delta: u128, - pub origin_transferable_balance_delta: u128, - pub new_overall_balance_delta: u128, - pub new_transferable_balance_delta: u128, + pub origin_overall_balance_delta: u128, + pub origin_transferable_balance_delta: u128, + pub new_overall_balance_delta: u128, + pub new_transferable_balance_delta: u128, } #[derive(Clone, Default, Serialize, Deserialize)] pub struct MintTokenInfoDelta { - pub origin_minted: u128, - pub new_minted: u128, - pub new_latest_mint_number: u32, + pub origin_minted: u128, + pub new_minted: u128, + pub new_latest_mint_number: u32, } -#[derive(Clone,Serialize,Deserialize)] +#[derive(Clone, Serialize, Deserialize)] pub struct TraceNode { - pub trace_type: CacheTableIndex, - // pub operation: TraceOperation, - pub key: Vec, + pub trace_type: CacheTableIndex, + // pub operation: TraceOperation, + pub key: Vec, } diff --git a/src/options.rs b/src/options.rs index f6b8cff7e0..db33efd95c 100644 --- a/src/options.rs +++ b/src/options.rs @@ -90,32 +90,19 @@ pub struct Options { )] pub(crate) first_brc20_height: Option, - #[arg( - long, - default_value = "true", - help = "Set lru cache to . By default 10000000" + long, + default_value = "true", + help = "Set lru cache to . By default 10000000" )] pub(crate) simulate_enable: bool, - #[arg( - long, - help = "bitcoin zmq url." - )] + #[arg(long, help = "bitcoin zmq url.")] pub(crate) simulate_zmq_url: Option, - #[arg( - long, - help = "bitcoin rpc url." - )] + #[arg(long, help = "bitcoin rpc url.")] pub(crate) simulate_bitcoin_rpc_url: Option, - #[arg( - long, - help = "bitcoin rpc password ." - )] + #[arg(long, help = "bitcoin rpc password .")] pub(crate) simulate_bitcoin_rpc_pass: Option, - #[arg( - long, - help = "bitcoin rpc user." - )] + #[arg(long, help = "bitcoin rpc user.")] pub(crate) simulate_bitcoin_rpc_user: Option, #[arg(long, help = "Simulate Use index at .")] pub(crate) simulate_index: Option, diff --git a/src/sat_point.rs b/src/sat_point.rs index 2065dd31db..52e34d653c 100644 --- a/src/sat_point.rs +++ b/src/sat_point.rs @@ -1,6 +1,6 @@ use super::*; -#[derive(Debug, PartialEq, Copy, Clone, Eq, PartialOrd, Ord, Default,Hash)] +#[derive(Debug, PartialEq, Copy, Clone, Eq, PartialOrd, Ord, Default, Hash)] pub struct SatPoint { pub outpoint: OutPoint, pub offset: u64, diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index ce8c8c8662..382b19b8f9 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -1,3 +1,5 @@ +use crate::index::simulator::simulate::{start_simulator, SimulatorServer}; +use crate::okx::datastore::brc20::Receipt; use bitcoincore_rpc::Auth; use { self::{ @@ -46,8 +48,6 @@ use { }, utoipa::OpenApi, }; -use crate::index::simulator::simulate::{SimulatorServer, start_simulator}; -use crate::okx::datastore::brc20::Receipt; mod accept_encoding; mod accept_json; @@ -203,16 +203,20 @@ impl Server { let sim_option = options.clone(); let sim_index = index.clone(); - let simulator_server = thread::spawn(move || { - start_simulator(sim_option,sim_index) - }).join().unwrap() ; - - let client = Arc::new(Client::new( - options.rpc_url.as_ref().unwrap().as_ref(), - Auth::UserPass(options.bitcoin_rpc_user.as_ref().unwrap().clone(), options.bitcoin_rpc_pass.as_ref().unwrap().clone()), - ).unwrap()); - + let simulator_server = thread::spawn(move || start_simulator(sim_option, sim_index)) + .join() + .unwrap(); + let client = Arc::new( + Client::new( + options.rpc_url.as_ref().unwrap().as_ref(), + Auth::UserPass( + options.bitcoin_rpc_user.as_ref().unwrap().clone(), + options.bitcoin_rpc_pass.as_ref().unwrap().clone(), + ), + ) + .unwrap(), + ); #[derive(OpenApi)] #[openapi( @@ -418,14 +422,17 @@ impl Server { .route("/static/*path", get(Self::static_asset)) .route("/status", get(Self::status)) .route("/tx/:txid", get(Self::transaction)) - .route("/tx/simulate/:txid", get(Self::simulate_tx)) - .route("/tx/multiple_receipt/:txid",get(Self::confirm_or_pending_receipt)) + .route("/tx/simulate/:txid", get(Self::simulate_tx)) + .route( + "/tx/multiple_receipt/:txid", + get(Self::confirm_or_pending_receipt), + ) .nest("/api", api_router) .layer(Extension(index)) .layer(Extension(server_config.clone())) .layer(Extension(config)) - .layer(Extension(client)) - .layer(Extension(simulator_server)) + .layer(Extension(client)) + .layer(Extension(simulator_server)) .layer(SetResponseHeaderLayer::if_not_present( header::CONTENT_SECURITY_POLICY, HeaderValue::from_static("default-src 'self'"), @@ -1688,10 +1695,13 @@ impl Server { Redirect::to(&destination) } - async fn simulate_tx(Extension(client): Extension>, Extension(simulator): Extension>,Path(tx_id): Path) -> ServerResult>> { + async fn simulate_tx( + Extension(client): Extension>, + Extension(simulator): Extension>, + Path(tx_id): Path, + ) -> ServerResult>> { if simulator.is_none() { - - return Err(ServerError::BadRequest("simulator not enabled".to_string())); + return Err(ServerError::BadRequest("simulator not enabled".to_string())); } let tx = client.get_raw_transaction(&tx_id, None); @@ -1699,20 +1709,24 @@ impl Server { return Err(ServerError::BadRequest("tx not found".to_string())); } - match simulator.unwrap().execute_tx(tx.as_ref().unwrap(), false) { - Ok(data) => { - Ok(Json(data)) - } - Err(err) => { - Err(ServerError::BadRequest(err.to_string())) - } + Ok(data) => Ok(Json(data)), + Err(err) => Err(ServerError::BadRequest(err.to_string())), } } - async fn confirm_or_pending_receipt(Extension(index): Extension>, Extension(simulator): Extension>, Path(tx_id): Path) -> ServerResult>{ - let pending_receipt = simulator.unwrap().get_receipt(tx_id.clone()).unwrap_or(Vec::new()); - let confirm_receipt = index.brc20_get_tx_events_by_txid(&tx_id).unwrap_or(Some(Vec::new())); + async fn confirm_or_pending_receipt( + Extension(index): Extension>, + Extension(simulator): Extension>, + Path(tx_id): Path, + ) -> ServerResult> { + let pending_receipt = simulator + .unwrap() + .get_receipt(tx_id.clone()) + .unwrap_or(Vec::new()); + let confirm_receipt = index + .brc20_get_tx_events_by_txid(&tx_id) + .unwrap_or(Some(Vec::new())); let receipt = MultipleReceipt { confirm: confirm_receipt, pending: Some(pending_receipt), From 875ff1ae1190dbe649ba6ab44e9a6b30c91065b8 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Wed, 17 Jan 2024 11:50:25 +0800 Subject: [PATCH 51/66] fmt --- src/okx/datastore/cache.rs | 1 - src/okx/protocol/trace.rs | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/src/okx/datastore/cache.rs b/src/okx/datastore/cache.rs index 969897ac0a..68331165ea 100644 --- a/src/okx/datastore/cache.rs +++ b/src/okx/datastore/cache.rs @@ -4,7 +4,6 @@ use serde::{Deserialize, Serialize}; #[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] pub enum CacheTableIndex { TXID_TO_INSCRIPTION_RECEIPTS, - SEQUENCE_NUMBER_TO_SATPOINT, SAT_TO_SEQUENCE_NUMBER, HOME_INSCRIPTIONS, diff --git a/src/okx/protocol/trace.rs b/src/okx/protocol/trace.rs index 5c82ab4797..3f84de9870 100644 --- a/src/okx/protocol/trace.rs +++ b/src/okx/protocol/trace.rs @@ -1,24 +1,8 @@ use crate::okx::datastore::cache::CacheTableIndex; use serde::{Deserialize, Serialize}; -#[derive(Clone, Default, Serialize, Deserialize)] -pub struct BalanceDelta { - pub origin_overall_balance_delta: u128, - pub origin_transferable_balance_delta: u128, - pub new_overall_balance_delta: u128, - pub new_transferable_balance_delta: u128, -} - -#[derive(Clone, Default, Serialize, Deserialize)] -pub struct MintTokenInfoDelta { - pub origin_minted: u128, - pub new_minted: u128, - pub new_latest_mint_number: u32, -} - #[derive(Clone, Serialize, Deserialize)] pub struct TraceNode { pub trace_type: CacheTableIndex, - // pub operation: TraceOperation, pub key: Vec, } From 710be203261b654ea2e7556bef0fe404fd7dd96f Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Wed, 17 Jan 2024 12:05:24 +0800 Subject: [PATCH 52/66] rue --- src/index/simulator/simulate.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index d5b8ff2065..4ff4098ef4 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -524,8 +524,7 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { processor.clone(), )?; - let index_sats = true; - if index_sats { + if processor.internal.internal.index_sats{ let mut coinbase_inputs = VecDeque::new(); let h = Height(height); From 870b1e47d072e5f76e2d70537cc0985e9b02e06d Mon Sep 17 00:00:00 2001 From: "fan.ke" Date: Wed, 17 Jan 2024 15:11:25 +0800 Subject: [PATCH 53/66] update simulate api --- src/subcommand/server.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 382b19b8f9..661c1ad778 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -48,6 +48,7 @@ use { }, utoipa::OpenApi, }; +use crate::subcommand::server::brc20::{BRC20Error, TxEvents}; mod accept_encoding; mod accept_json; @@ -1699,19 +1700,25 @@ impl Server { Extension(client): Extension>, Extension(simulator): Extension>, Path(tx_id): Path, - ) -> ServerResult>> { + ) -> ApiResult { if simulator.is_none() { - return Err(ServerError::BadRequest("simulator not enabled".to_string())); + + + return Err( ApiError::Internal("simulator not enabled".to_string())); } let tx = client.get_raw_transaction(&tx_id, None); if tx.is_err() { - return Err(ServerError::BadRequest("tx not found".to_string())); + return Err(ApiError::NotFound("tx not found".to_string())); } match simulator.unwrap().execute_tx(tx.as_ref().unwrap(), false) { - Ok(data) => Ok(Json(data)), - Err(err) => Err(ServerError::BadRequest(err.to_string())), + Ok(data) => { + Ok(Json(ApiResponse::ok(TxEvents { + txid: tx_id.to_string(), + events: data.iter().map(|e| e.into()).collect(), + }))) }, + Err(err) => Err(ApiError::Internal(err.to_string())), } } From 64655fdad51c2f7c5f418d0203d2a4a023ddfa0a Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Wed, 17 Jan 2024 15:16:49 +0800 Subject: [PATCH 54/66] change response --- src/index/simulator/mod.rs | 1 + src/index/simulator/simulate.rs | 29 +++++++++++++++++++++-------- src/index/simulator/types.rs | 9 +++++++++ src/okx/protocol/simulate.rs | 5 +++++ src/subcommand/server.rs | 4 ++-- 5 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/index/simulator/types.rs diff --git a/src/index/simulator/mod.rs b/src/index/simulator/mod.rs index a5e57cca69..b032e34c93 100644 --- a/src/index/simulator/mod.rs +++ b/src/index/simulator/mod.rs @@ -1,3 +1,4 @@ pub mod error; pub mod processor; pub mod simulate; +pub mod types; diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 4ff4098ef4..784433c6df 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -2,6 +2,7 @@ use crate::height::Height; use crate::index::entry::Entry; use crate::index::simulator::error::SimulateError; use crate::index::simulator::processor::{IndexWrapper, StorageProcessor}; +use crate::index::simulator::types::ExecuteTxResponse; use crate::index::updater::pending_updater::PendingUpdater; use crate::index::{ BlockData, InscriptionIdValue, BRC20_BALANCES, BRC20_EVENTS, BRC20_INSCRIBE_TRANSFER, @@ -15,7 +16,7 @@ use crate::index::{ use crate::okx::datastore::brc20::redb::table::get_transaction_receipts; use crate::okx::datastore::brc20::{Brc20Reader, Receipt}; use crate::okx::datastore::cache::CacheTableIndex; -use crate::okx::datastore::ord::InscriptionOp; +use crate::okx::datastore::ord::{InscriptionOp, OrdReader}; use crate::okx::lru::SimpleLru; use crate::okx::protocol::simulate::SimulateContext; use crate::okx::protocol::trace::TraceNode; @@ -215,7 +216,7 @@ impl SimulatorServer { &self, tx: &Transaction, commit: bool, - ) -> crate::Result, SimulateError> { + ) -> crate::Result { let wtx = self.simulate_index.begin_write()?; let traces = Rc::new(RefCell::new(vec![])); let ret = self.simulate_tx(tx, &wtx, traces)?; @@ -237,8 +238,10 @@ impl SimulatorServer { tx: &Transaction, wtx: &WriteTransaction, traces: Rc>>, - ) -> crate::Result, SimulateError> { + ) -> crate::Result { + let mut ret = ExecuteTxResponse::default(); let brc20_receipts = Rc::new(RefCell::new(vec![])); + let ord_operations = Rc::new(RefCell::new(vec![])); let height = self.get_current_height()?; let block = self .internal_index @@ -296,13 +299,17 @@ impl SimulatorServer { BRC20_INSCRIBE_TRANSFER: Rc::new(RefCell::new(wtx.open_table(BRC20_INSCRIBE_TRANSFER)?)), traces: traces.clone(), brc20_receipts: brc20_receipts.clone(), + ord_operations: ord_operations.clone(), _marker_a: Default::default(), }; let db_receipts = ctx.get_transaction_receipts(&tx.txid())?; - if db_receipts.len() > 0 { + let operations = ctx.get_transaction_operations(&tx.txid())?; + if db_receipts.len() > 0 || operations.len() > 0 { + ret.ord_operations = operations; + ret.brc20_receipts = db_receipts; info!("tx:{:?} already simulated", tx.txid()); - return Ok(db_receipts); + return Ok(ret); } let processor = StorageProcessor { @@ -331,8 +338,14 @@ impl SimulatorServer { }; self.loop_simulate_tx(h, &block, &processor, &tx)?; - let ret = brc20_receipts.borrow(); - let ret = ret.deref().clone(); + + let receipts = brc20_receipts.borrow(); + let receipts = receipts.deref().clone(); + let ord_operations = ord_operations.borrow(); + let ord_operations = ord_operations.deref().clone(); + ret.brc20_receipts = receipts; + ret.ord_operations = ord_operations; + Ok(ret) } pub fn loop_simulate_tx( @@ -524,7 +537,7 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { processor.clone(), )?; - if processor.internal.internal.index_sats{ + if processor.internal.internal.index_sats { let mut coinbase_inputs = VecDeque::new(); let h = Height(height); diff --git a/src/index/simulator/types.rs b/src/index/simulator/types.rs new file mode 100644 index 0000000000..ee7f2a90d9 --- /dev/null +++ b/src/index/simulator/types.rs @@ -0,0 +1,9 @@ +use crate::okx::datastore::brc20::Receipt; +use crate::okx::datastore::ord::InscriptionOp; +use serde::{Deserialize, Serialize}; + +#[derive(Default,Clone, Debug, Serialize, Deserialize)] +pub struct ExecuteTxResponse { + pub brc20_receipts: Vec, + pub ord_operations: Vec, +} diff --git a/src/okx/protocol/simulate.rs b/src/okx/protocol/simulate.rs index b8cac64aa7..43a1adc7ef 100644 --- a/src/okx/protocol/simulate.rs +++ b/src/okx/protocol/simulate.rs @@ -64,6 +64,7 @@ pub struct SimulateContext<'a, 'db, 'txn> { Rc>>, pub traces: Rc>>, pub brc20_receipts: Rc>>, + pub ord_operations: Rc>>, pub _marker_a: PhantomData<&'a ()>, } @@ -376,6 +377,10 @@ impl<'a, 'db, 'txn> OrdReaderWriter for SimulateContext<'a, 'db, 'txn> { trace_type: CacheTableIndex::ORD_TX_TO_OPERATIONS, key, }); + + let mut ord_traces = self.ord_operations.borrow_mut(); + ord_traces.extend_from_slice(operations); + let mut table = self.ORD_TX_TO_OPERATIONS.borrow_mut(); save_transaction_operations(&mut table, txid, operations) } diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 382b19b8f9..7e07eb95d9 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -1,5 +1,4 @@ use crate::index::simulator::simulate::{start_simulator, SimulatorServer}; -use crate::okx::datastore::brc20::Receipt; use bitcoincore_rpc::Auth; use { self::{ @@ -48,6 +47,7 @@ use { }, utoipa::OpenApi, }; +use crate::index::simulator::types::ExecuteTxResponse; mod accept_encoding; mod accept_json; @@ -1699,7 +1699,7 @@ impl Server { Extension(client): Extension>, Extension(simulator): Extension>, Path(tx_id): Path, - ) -> ServerResult>> { + ) -> ServerResult> { if simulator.is_none() { return Err(ServerError::BadRequest("simulator not enabled".to_string())); } From e32f3dde8a005449fe92b1ceafbff77c6b4075d8 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Wed, 17 Jan 2024 17:15:14 +0800 Subject: [PATCH 55/66] coinbase --- src/index/updater/pending_updater.rs | 47 +++++++++------------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index f0d829c09a..38bda0f546 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -255,16 +255,6 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { } } - let is_coinbase = tx - .input - .first() - .map(|tx_in| tx_in.previous_output.is_null()) - .unwrap_or_default(); - - if is_coinbase { - floating_inscriptions.append(&mut self.flotsam); - } - floating_inscriptions.sort_by_key(|flotsam| flotsam.offset); let mut inscriptions = floating_inscriptions.into_iter().peekable(); @@ -294,11 +284,6 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { output_value = end; - #[cfg(not(feature = "cache"))] - self.new_outpoints.push(OutPoint { - vout: vout.try_into().unwrap(), - txid, - }); self.tx_out_cache.insert( OutPoint { vout: vout.try_into().unwrap(), @@ -333,24 +318,15 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; } - if is_coinbase { - for flotsam in inscriptions { - let new_satpoint = SatPoint { - outpoint: OutPoint::null(), - offset: self.lost_sats + flotsam.offset - output_value, - }; - self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; - } - self.lost_sats += self.reward - output_value; - Ok(()) - } else { - self.flotsam.extend(inscriptions.map(|flotsam| Flotsam { - offset: self.reward + flotsam.offset - output_value, - ..flotsam - })); - self.reward += total_input_value - output_value; - Ok(()) + for flotsam in inscriptions { + let new_satpoint = SatPoint { + outpoint: OutPoint::null(), + offset: u64::MAX, + }; + self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?; } + self.lost_sats += self.reward - output_value; + Ok(()) } // write tx_out to outpoint_to_entry table @@ -559,6 +535,11 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { } else { new_satpoint.store() }; + let point=if new_satpoint.outpoint.is_null() && new_satpoint.offset == u64::MAX { + None + } else { + Some(new_satpoint) + }; self .operations @@ -592,7 +573,7 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { }, }, old_satpoint: flotsam.old_satpoint, - new_satpoint: Some(Entry::load(satpoint)), + new_satpoint: point, }); self From 967b6aca9925d02cf3343fda0ce35d3d09e89232 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Wed, 17 Jan 2024 17:37:08 +0800 Subject: [PATCH 56/66] add col --- src/index/simulator/simulate.rs | 1 + src/index/updater/inscription_updater.rs | 7 ++++++- src/index/updater/pending_updater.rs | 11 +++++------ src/okx/datastore/ord/operation.rs | 4 ++++ src/okx/datastore/ord/redb/table.rs | 1 + src/okx/protocol/brc20/msg_resolver.rs | 8 ++++++-- src/okx/protocol/brc20/operation/mod.rs | 9 ++++++--- src/okx/protocol/ord/bitmap.rs | 1 + 8 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 784433c6df..1a60549542 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -717,6 +717,7 @@ pub fn start_simulator(ops: Options, internal: Arc) -> Option InscriptionUpdater<'a, 'db, 'tx> { } else { new_satpoint.store() }; - + let transfer_to_coin_base=if new_satpoint.outpoint.txid==flotsam.txid{ + false + }else{ + true + }; self .operations .entry(flotsam.txid) @@ -666,6 +670,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { unbound, vindicated, inscription, + transfer_to_coin_base, }, }, old_satpoint: flotsam.old_satpoint, diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index 38bda0f546..f275a7105a 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -11,7 +11,6 @@ pub struct PendingUpdater<'a, 'db, 'tx> { pub(super) blessed_inscription_count: u64, pub(super) chain: Chain, pub(super) cursed_inscription_count: u64, - pub(super) flotsam: Vec, pub(super) height: u32, pub(super) home_inscription_count: u64, pub(super) index_transactions: bool, @@ -47,7 +46,6 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { blessed_inscription_count, chain, cursed_inscription_count, - flotsam: vec![], height, home_inscription_count: home_inscriptions_len, index_transactions, @@ -535,12 +533,15 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { } else { new_satpoint.store() }; + let mut is_transfer_to_coinbase=false; let point=if new_satpoint.outpoint.is_null() && new_satpoint.offset == u64::MAX { + is_transfer_to_coinbase=true; None } else { Some(new_satpoint) }; + self .operations .entry(flotsam.txid) @@ -570,6 +571,7 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { unbound, vindicated, inscription, + transfer_to_coin_base: is_transfer_to_coinbase, }, }, old_satpoint: flotsam.old_satpoint, @@ -585,7 +587,4 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { Ok(()) } -} - -#[test] -pub fn test_asd() {} +} \ No newline at end of file diff --git a/src/okx/datastore/ord/operation.rs b/src/okx/datastore/ord/operation.rs index 23eb74af89..7df47995c3 100644 --- a/src/okx/datastore/ord/operation.rs +++ b/src/okx/datastore/ord/operation.rs @@ -24,6 +24,8 @@ pub enum Action { unbound: bool, inscription: Inscription, #[serde(default)] + transfer_to_coin_base:bool, + #[serde(default)] vindicated: bool, }, Transfer, @@ -77,6 +79,7 @@ mod tests { unbound: true, vindicated: false, inscription: inscription("text/plain;charset=utf-8", "foobar"), + transfer_to_coin_base: false, } ); @@ -113,6 +116,7 @@ mod tests { unbound: true, vindicated: false, inscription: inscription("text/plain;charset=utf-8", "foobar"), + transfer_to_coin_base: false, }, sequence_number: 100, inscription_number: Some(100), diff --git a/src/okx/datastore/ord/redb/table.rs b/src/okx/datastore/ord/redb/table.rs index 6bd22d57a4..3b61182145 100644 --- a/src/okx/datastore/ord/redb/table.rs +++ b/src/okx/datastore/ord/redb/table.rs @@ -128,6 +128,7 @@ mod tests { unbound: false, vindicated: false, inscription: inscription("text/plain;charset=utf-8", "foobar"), + transfer_to_coin_base: false, }, sequence_number: 100, inscription_number: Some(100), diff --git a/src/okx/protocol/brc20/msg_resolver.rs b/src/okx/protocol/brc20/msg_resolver.rs index 03694b7f7b..dc7bb334c8 100644 --- a/src/okx/protocol/brc20/msg_resolver.rs +++ b/src/okx/protocol/brc20/msg_resolver.rs @@ -31,7 +31,7 @@ impl Message { cursed: false, unbound: false, vindicated: false, - inscription: _, + inscription: _, .. } if sat_in_outputs => { match deserialize_brc20_operation( new_inscriptions @@ -89,7 +89,7 @@ mod tests { use crate::okx::protocol::context::Context; use crate::okx::protocol::BlockContext; use bitcoin::{Network, OutPoint}; - use redb::{Database, WriteTransaction}; + use redb::{Database}; use std::str::FromStr; use tempfile::NamedTempFile; @@ -110,6 +110,7 @@ mod tests { cursed: false, unbound: false, inscription: inscriptions.get(0).unwrap().clone(), + transfer_to_coin_base: false, vindicated: false, }, sequence_number: 1, @@ -238,6 +239,7 @@ mod tests { cursed: true, unbound: false, inscription: inscriptions.get(0).unwrap().clone(), + transfer_to_coin_base: false, vindicated: false, }, ..op @@ -249,6 +251,7 @@ mod tests { cursed: false, unbound: true, inscription: inscriptions.get(0).unwrap().clone(), + transfer_to_coin_base: false, vindicated: false, }, ..op @@ -259,6 +262,7 @@ mod tests { cursed: true, unbound: true, inscription: inscriptions.get(0).unwrap().clone(), + transfer_to_coin_base: false, vindicated: false, }, ..op diff --git a/src/okx/protocol/brc20/operation/mod.rs b/src/okx/protocol/brc20/operation/mod.rs index da558eaf71..e27b4fa940 100644 --- a/src/okx/protocol/brc20/operation/mod.rs +++ b/src/okx/protocol/brc20/operation/mod.rs @@ -212,7 +212,8 @@ mod tests { cursed: false, unbound: false, vindicated: false, - inscription: inscription.clone() + inscription: inscription.clone(), + transfer_to_coin_base:false }, ) .unwrap(), @@ -235,7 +236,8 @@ mod tests { cursed: false, unbound: false, vindicated: false, - inscription: inscription.clone() + inscription: inscription.clone(), + transfer_to_coin_base: false, }, ) .unwrap(), @@ -256,7 +258,8 @@ mod tests { cursed: false, unbound: false, vindicated: false, - inscription: inscription.clone() + inscription: inscription.clone(), + transfer_to_coin_base: false, }, ) .unwrap(), diff --git a/src/okx/protocol/ord/bitmap.rs b/src/okx/protocol/ord/bitmap.rs index 19d5c5db03..e174e885f2 100644 --- a/src/okx/protocol/ord/bitmap.rs +++ b/src/okx/protocol/ord/bitmap.rs @@ -39,6 +39,7 @@ pub fn index_bitmap( unbound: _, vindicated: _, inscription, + transfer_to_coin_base: _, } => { if let Some((inscription_id, district)) = index_district(context, inscription, op.inscription_id)? From d4596dc63f395c1b3b3f8c1775d7daaaa1752d73 Mon Sep 17 00:00:00 2001 From: "fan.ke" Date: Wed, 17 Jan 2024 17:46:53 +0800 Subject: [PATCH 57/66] split --- src/subcommand/server.rs | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 9af8ee7b3b..42bd940bc1 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -48,6 +48,9 @@ use { utoipa::OpenApi, }; use crate::index::simulator::types::ExecuteTxResponse; +use crate::okx::datastore::brc20::Receipt; +use crate::okx::datastore::ord::InscriptionOp; +use crate::subcommand::server::ord::OrdInscription; mod accept_encoding; mod accept_json; @@ -422,7 +425,8 @@ impl Server { .route("/static/*path", get(Self::static_asset)) .route("/status", get(Self::status)) .route("/tx/:txid", get(Self::transaction)) - .route("/tx/simulate/:txid", get(Self::simulate_tx)) + .route("/tx/simulate_ord/:txid", get(Self::simulate_ord)) + .route("/tx/simulate_brc20/:txid", get(Self::simulate_brc20)) .route( "/tx/multiple_receipt/:txid", get(Self::confirm_or_pending_receipt), @@ -1695,11 +1699,11 @@ impl Server { Redirect::to(&destination) } - async fn simulate_tx( + async fn simulate_brc20( Extension(client): Extension>, Extension(simulator): Extension>, Path(tx_id): Path, - ) -> ApiResult { + ) -> ApiResult> { if simulator.is_none() { @@ -1713,7 +1717,30 @@ impl Server { match simulator.unwrap().execute_tx(tx.as_ref().unwrap(), false) { Ok(data) => { - Ok(Json(ApiResponse::ok(data))) }, + Ok(Json(ApiResponse::ok(data.brc20_receipts))) }, + Err(err) => Err(ApiError::Internal(err.to_string())), + } + } + + async fn simulate_ord( Extension(client): Extension>, + Extension(simulator): Extension>, + Path(tx_id): Path) -> ApiResult> { + if simulator.is_none() { + + + return Err( ApiError::Internal("simulator not enabled".to_string())); + } + + let tx = client.get_raw_transaction(&tx_id, None); + if tx.is_err() { + return Err(ApiError::NotFound("tx not found".to_string())); + } + + + + match simulator.unwrap().execute_tx(tx.as_ref().unwrap(), false) { + Ok(data) => { + Ok(Json(ApiResponse::ok(data.ord_operations))) }, Err(err) => Err(ApiError::Internal(err.to_string())), } } From dbd253a7a685037a1586f01c971ea3a9d3819e8a Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Fri, 19 Jan 2024 17:37:23 +0800 Subject: [PATCH 58/66] fix concurrent --- src/index/simulator/simulate.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 1a60549542..10684af699 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -476,31 +476,28 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { .map(|(_, txid)| txid) .collect::>(); use rayon::prelude::*; - let tx_outs = block - .txdata - .par_iter() - .flat_map(|(tx, _)| tx.input.par_iter()) - .filter_map(|input| { + let mut tx_outs = Vec::new(); + for (tx, _) in block.txdata.iter() { + for input in tx.input.iter() { total_outputs_count.fetch_add(1, Ordering::Relaxed); let prev_output = input.previous_output; - // We don't need coinbase input value if prev_output.is_null() { - None + continue; } else if txids.contains(&prev_output.txid) { meet_outputs_count.fetch_add(1, Ordering::Relaxed); - None + continue; } else if tx_out_cache.contains(&prev_output) { cache_outputs_count.fetch_add(1, Ordering::Relaxed); - None + continue; } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output).unwrap() { miss_outputs_count.fetch_add(1, Ordering::Relaxed); - Some((prev_output, Some(txout))) + tx_outs.push((prev_output, Some(txout))); } else { fetching_outputs_count.fetch_add(1, Ordering::Relaxed); - Some((prev_output, None)) + tx_outs.push((prev_output, None)); } - }) - .collect::>(); + } + } for (out_point, value) in tx_outs.into_iter() { if let Some(tx_out) = value { tx_out_cache.insert(out_point, tx_out); From a2037abeb47f413b4e26006961aae20b1368866f Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:08:32 +0800 Subject: [PATCH 59/66] fmt --- src/index/simulator/simulate.rs | 2 +- src/index/simulator/types.rs | 2 +- src/index/updater/inscription_updater.rs | 4 +-- src/index/updater/pending_updater.rs | 9 +++-- src/okx/datastore/ord/operation.rs | 2 +- src/okx/protocol/brc20/msg_resolver.rs | 5 +-- src/okx/protocol/brc20/operation/mod.rs | 2 +- src/subcommand/server.rs | 44 ++++++++++-------------- 8 files changed, 32 insertions(+), 38 deletions(-) diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 10684af699..13d387d918 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -714,11 +714,11 @@ pub fn start_simulator(ops: Options, internal: Arc) -> Option, pub ord_operations: Vec, diff --git a/src/index/updater/inscription_updater.rs b/src/index/updater/inscription_updater.rs index 7f3140b677..f3984cf0ce 100644 --- a/src/index/updater/inscription_updater.rs +++ b/src/index/updater/inscription_updater.rs @@ -636,9 +636,9 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { } else { new_satpoint.store() }; - let transfer_to_coin_base=if new_satpoint.outpoint.txid==flotsam.txid{ + let transfer_to_coin_base = if new_satpoint.outpoint.txid == flotsam.txid { false - }else{ + } else { true }; self diff --git a/src/index/updater/pending_updater.rs b/src/index/updater/pending_updater.rs index f275a7105a..9171274b80 100644 --- a/src/index/updater/pending_updater.rs +++ b/src/index/updater/pending_updater.rs @@ -533,15 +533,14 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { } else { new_satpoint.store() }; - let mut is_transfer_to_coinbase=false; - let point=if new_satpoint.outpoint.is_null() && new_satpoint.offset == u64::MAX { - is_transfer_to_coinbase=true; + let mut is_transfer_to_coinbase = false; + let point = if new_satpoint.outpoint.is_null() && new_satpoint.offset == u64::MAX { + is_transfer_to_coinbase = true; None } else { Some(new_satpoint) }; - self .operations .entry(flotsam.txid) @@ -587,4 +586,4 @@ impl<'a, 'db, 'tx> PendingUpdater<'a, 'db, 'tx> { Ok(()) } -} \ No newline at end of file +} diff --git a/src/okx/datastore/ord/operation.rs b/src/okx/datastore/ord/operation.rs index 7df47995c3..7a9088fb18 100644 --- a/src/okx/datastore/ord/operation.rs +++ b/src/okx/datastore/ord/operation.rs @@ -24,7 +24,7 @@ pub enum Action { unbound: bool, inscription: Inscription, #[serde(default)] - transfer_to_coin_base:bool, + transfer_to_coin_base: bool, #[serde(default)] vindicated: bool, }, diff --git a/src/okx/protocol/brc20/msg_resolver.rs b/src/okx/protocol/brc20/msg_resolver.rs index dc7bb334c8..79c437c8e6 100644 --- a/src/okx/protocol/brc20/msg_resolver.rs +++ b/src/okx/protocol/brc20/msg_resolver.rs @@ -31,7 +31,8 @@ impl Message { cursed: false, unbound: false, vindicated: false, - inscription: _, .. + inscription: _, + .. } if sat_in_outputs => { match deserialize_brc20_operation( new_inscriptions @@ -89,7 +90,7 @@ mod tests { use crate::okx::protocol::context::Context; use crate::okx::protocol::BlockContext; use bitcoin::{Network, OutPoint}; - use redb::{Database}; + use redb::Database; use std::str::FromStr; use tempfile::NamedTempFile; diff --git a/src/okx/protocol/brc20/operation/mod.rs b/src/okx/protocol/brc20/operation/mod.rs index e27b4fa940..47c98d6dba 100644 --- a/src/okx/protocol/brc20/operation/mod.rs +++ b/src/okx/protocol/brc20/operation/mod.rs @@ -213,7 +213,7 @@ mod tests { unbound: false, vindicated: false, inscription: inscription.clone(), - transfer_to_coin_base:false + transfer_to_coin_base: false }, ) .unwrap(), diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 42bd940bc1..d22a133a1e 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -1,4 +1,8 @@ use crate::index::simulator::simulate::{start_simulator, SimulatorServer}; +use crate::index::simulator::types::ExecuteTxResponse; +use crate::okx::datastore::brc20::Receipt; +use crate::okx::datastore::ord::InscriptionOp; +use crate::subcommand::server::ord::OrdInscription; use bitcoincore_rpc::Auth; use { self::{ @@ -47,10 +51,6 @@ use { }, utoipa::OpenApi, }; -use crate::index::simulator::types::ExecuteTxResponse; -use crate::okx::datastore::brc20::Receipt; -use crate::okx::datastore::ord::InscriptionOp; -use crate::subcommand::server::ord::OrdInscription; mod accept_encoding; mod accept_json; @@ -190,6 +190,12 @@ pub(crate) struct Server { impl Server { pub(crate) fn run(self, options: Options, index: Arc, handle: Handle) -> SubcommandResult { + let sim_option = options.clone(); + let sim_index = index.clone(); + let simulator_server = thread::spawn(move || start_simulator(sim_option, sim_index)) + .join() + .unwrap(); + Runtime::new()?.block_on(async { let index_clone = index.clone(); @@ -204,12 +210,6 @@ impl Server { }); INDEXER.lock().unwrap().replace(index_thread); - let sim_option = options.clone(); - let sim_index = index.clone(); - let simulator_server = thread::spawn(move || start_simulator(sim_option, sim_index)) - .join() - .unwrap(); - let client = Arc::new( Client::new( options.rpc_url.as_ref().unwrap().as_ref(), @@ -1705,9 +1705,7 @@ impl Server { Path(tx_id): Path, ) -> ApiResult> { if simulator.is_none() { - - - return Err( ApiError::Internal("simulator not enabled".to_string())); + return Err(ApiError::Internal("simulator not enabled".to_string())); } let tx = client.get_raw_transaction(&tx_id, None); @@ -1716,19 +1714,18 @@ impl Server { } match simulator.unwrap().execute_tx(tx.as_ref().unwrap(), false) { - Ok(data) => { - Ok(Json(ApiResponse::ok(data.brc20_receipts))) }, + Ok(data) => Ok(Json(ApiResponse::ok(data.brc20_receipts))), Err(err) => Err(ApiError::Internal(err.to_string())), } } - async fn simulate_ord( Extension(client): Extension>, - Extension(simulator): Extension>, - Path(tx_id): Path) -> ApiResult> { + async fn simulate_ord( + Extension(client): Extension>, + Extension(simulator): Extension>, + Path(tx_id): Path, + ) -> ApiResult> { if simulator.is_none() { - - - return Err( ApiError::Internal("simulator not enabled".to_string())); + return Err(ApiError::Internal("simulator not enabled".to_string())); } let tx = client.get_raw_transaction(&tx_id, None); @@ -1736,11 +1733,8 @@ impl Server { return Err(ApiError::NotFound("tx not found".to_string())); } - - match simulator.unwrap().execute_tx(tx.as_ref().unwrap(), false) { - Ok(data) => { - Ok(Json(ApiResponse::ok(data.ord_operations))) }, + Ok(data) => Ok(Json(ApiResponse::ok(data.ord_operations))), Err(err) => Err(ApiError::Internal(err.to_string())), } } From 96ac4e1a881ff5dda8c45c54a032a2904ce5a365 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Tue, 30 Jan 2024 14:00:36 +0800 Subject: [PATCH 60/66] merge pending3 --- Cargo.lock | 3 +- Cargo.toml | 3 +- src/index/simulator/simulate.rs | 74 ++++++++++++++++++++------------- src/lib.rs | 21 +++++++++- src/options.rs | 3 ++ src/subcommand/server.rs | 1 - 6 files changed, 73 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1799efbc72..ea46c94daf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1911,7 +1911,7 @@ dependencies = [ [[package]] name = "indexer-sdk" version = "0.1.0" -source = "git+https://github.com/ItsFunny/indexer-sdk.git#855079394cd5331996532f7fc06377ab55dc3a82" +source = "git+https://github.com/okx/indexer-sdk.git?rev=34e6e7bfc8c0d3db41e2867f71428859396407b0#34e6e7bfc8c0d3db41e2867f71428859396407b0" dependencies = [ "async-channel 1.9.0", "async-trait", @@ -2638,6 +2638,7 @@ name = "ord" version = "0.14.1" dependencies = [ "anyhow", + "async-channel 1.9.0", "async-trait", "axum", "axum-server", diff --git a/Cargo.toml b/Cargo.toml index c563977cef..319452d74d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,7 +74,8 @@ log4rs = { version = "1.2.0", features = ["gzip"] } once_cell = "1.19.0" rmp-serde = "1.1.2" rayon = "1.8.0" -indexer-sdk={git="https://github.com/ItsFunny/indexer-sdk.git"} +indexer-sdk={git="https://github.com/okx/indexer-sdk.git",rev = "34e6e7bfc8c0d3db41e2867f71428859396407b0"} +async-channel = "1.9.0" [dev-dependencies] criterion = "0.5.1" executable-path = "1.0.0" diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 13d387d918..5b1d2cccd9 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -26,9 +26,9 @@ use anyhow::anyhow; use bitcoin::{Block, OutPoint, Transaction, TxOut, Txid}; use indexer_sdk::client::drect::DirectClient; use indexer_sdk::client::event::ClientEvent; -use indexer_sdk::client::SyncClient; +use indexer_sdk::client::Client; use indexer_sdk::configuration::base::{IndexerConfiguration, NetConfiguration, ZMQConfiguration}; -use indexer_sdk::factory::common::sync_create_and_start_processor; +use indexer_sdk::factory::common::async_create_and_start_processor; use indexer_sdk::storage::db::memory::MemoryDB; use indexer_sdk::storage::db::thread_safe::ThreadSafeDB; use indexer_sdk::storage::kv::KVStorageProcessor; @@ -69,33 +69,33 @@ unsafe impl Send for SimulatorServer {} unsafe impl Sync for SimulatorServer {} impl SimulatorServer { - pub async fn start(&self, exit: watch::Receiver<()>) -> JoinHandle<()> { + pub async fn start(&self, rt: Arc, exit: watch::Receiver<()>) -> JoinHandle<()> { let internal = self.clone(); - tokio::spawn(async move { + rt.spawn(async move { internal.on_start(exit).await; }) } async fn on_start(self, mut exit: watch::Receiver<()>) { loop { tokio::select! { - event=self.get_client_event()=>{ - match event{ - Ok(event) => { - if let Err(e)= self.handle_event(&event).await{ - log::error!("handle event error: {:?}", e); - } - } - Err(e) => { - log::error!("receive event error: {:?}", e); - break; - } - } - }, - _ = exit.changed() => { - info!("simulator receive exit signal, exit."); - break; - } + event=self.get_client_event()=>{ + match event{ + Ok(event) => { + if let Err(e)= self.handle_event(&event).await{ + log::error!("handle event error: {:?}", e); + } + } + Err(e) => { + log::error!("receive event error: {:?}", e); + continue; + } + } + }, + _ = exit.changed() => { + log::info!("simulator receive exit signal"); + break; } + } } } @@ -115,7 +115,7 @@ impl SimulatorServer { } ClientEvent::GetHeight => { let height = self.get_current_height()?; - self.client.report_height(height)?; + self.client.report_height(height).await?; } ClientEvent::TxDroped(tx) => { let tx = tx.clone().into(); @@ -209,7 +209,7 @@ impl SimulatorServer { Ok(true) } async fn get_client_event(&self) -> crate::Result { - let ret = self.client.block_get_event()?; + let ret = self.client.block_get_event().await?; Ok(ret) } pub fn execute_tx( @@ -679,10 +679,19 @@ pub fn start_simulator(ops: Options, internal: Arc) -> Option) -> Option { + let rt = Arc::new(Runtime::new().unwrap()); let zmq_url = ops.simulate_zmq_url.clone().unwrap(); let sim_rpc = ops.simulate_bitcoin_rpc_url.clone().unwrap(); let sim_user = ops.simulate_bitcoin_rpc_user.clone().unwrap(); let sim_pass = ops.simulate_bitcoin_rpc_pass.clone().unwrap(); + let notify_rx = ops.rx.clone().unwrap(); let config = IndexerConfiguration { mq: ZMQConfiguration { @@ -696,22 +705,31 @@ pub fn start_simulator(ops: Options, internal: Arc) -> Option>, +) { + let (notify_tx, notify_rx) = tokio::sync::oneshot::channel(); + if enable_pending { + info!("pending enbale,begin to send exit signal to pending thread"); + let _ = tx.send_blocking(notify_tx); + let _ = notify_rx.blocking_recv(); + info!("pending thread shutdown successfully"); + } else { + info!("pending disable"); + } } diff --git a/src/options.rs b/src/options.rs index db33efd95c..149f0c58ae 100644 --- a/src/options.rs +++ b/src/options.rs @@ -106,6 +106,9 @@ pub struct Options { pub(crate) simulate_bitcoin_rpc_user: Option, #[arg(long, help = "Simulate Use index at .")] pub(crate) simulate_index: Option, + + #[clap(skip)] + pub rx: Option>>, } #[derive(Debug, Clone)] diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index d22a133a1e..6029ba3155 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -1,5 +1,4 @@ use crate::index::simulator::simulate::{start_simulator, SimulatorServer}; -use crate::index::simulator::types::ExecuteTxResponse; use crate::okx::datastore::brc20::Receipt; use crate::okx::datastore::ord::InscriptionOp; use crate::subcommand::server::ord::OrdInscription; From e2fa574ddd692d7aaa57641685813fc7e2eb0ed1 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Tue, 30 Jan 2024 14:17:47 +0800 Subject: [PATCH 61/66] merge pending3 --- src/index/simulator/error.rs | 3 +++ src/index/simulator/simulate.rs | 47 ++++++++++++++++++++------------- src/lib.rs | 4 ++- src/okx/protocol/context.rs | 5 ---- src/options.rs | 2 +- src/subcommand/server.rs | 1 - 6 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/index/simulator/error.rs b/src/index/simulator/error.rs index 630a26098a..f9fe30cc3b 100644 --- a/src/index/simulator/error.rs +++ b/src/index/simulator/error.rs @@ -21,4 +21,7 @@ pub enum SimulateError { #[error("transaction failed: {0}")] TransactionError(#[from] redb::TransactionError), + + #[error("over flow")] + StackOverFlow, } diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 5b1d2cccd9..146578e08c 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -248,30 +248,30 @@ impl SimulatorServer { .internal .get_block_by_height(height)? .unwrap(); - let home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS).unwrap(); + let home_inscriptions = wtx.open_table(HOME_INSCRIPTIONS)?; let inscription_id_to_sequence_number = - wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER).unwrap(); + wtx.open_table(INSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; let inscription_number_to_sequence_number = wtx .open_table(INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER) - .unwrap(); - let sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER).unwrap(); + ?; + let sat_to_sequence_number = wtx.open_multimap_table(SAT_TO_SEQUENCE_NUMBER)?; let satpoint_to_sequence_number = wtx .open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER) - .unwrap(); + ?; let sequence_number_to_children = wtx .open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN) - .unwrap(); + ?; let sequence_number_to_inscription_entry = Rc::new(RefCell::new( wtx .open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY) - .unwrap(), + ?, )); - let sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT).unwrap(); - let transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION).unwrap(); - let outpoint_to_entry = Rc::new(RefCell::new(wtx.open_table(OUTPOINT_TO_ENTRY).unwrap())); - let outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES).unwrap(); - let sat_to_point = wtx.open_table(SAT_TO_SATPOINT).unwrap(); - let statis_to_count = wtx.open_table(STATISTIC_TO_COUNT).unwrap(); + let sequence_number_to_satpoint = wtx.open_table(SEQUENCE_NUMBER_TO_SATPOINT)?; + let transaction_id_to_transaction = wtx.open_table(TRANSACTION_ID_TO_TRANSACTION)?; + let outpoint_to_entry = Rc::new(RefCell::new(wtx.open_table(OUTPOINT_TO_ENTRY)?)); + let outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES)?; + let sat_to_point = wtx.open_table(SAT_TO_SATPOINT)?; + let statis_to_count = wtx.open_table(STATISTIC_TO_COUNT)?; let traces_table = wtx.open_table(SIMULATE_TRACE_TABLE)?; let h = height; @@ -337,7 +337,8 @@ impl SimulatorServer { context: ctx, }; - self.loop_simulate_tx(h, &block, &processor, &tx)?; + let mut depth = 0; + self.loop_simulate_tx(h, &block, &processor, &tx, &mut depth)?; let receipts = brc20_receipts.borrow(); let receipts = receipts.deref().clone(); @@ -354,7 +355,13 @@ impl SimulatorServer { block: &Block, processor: &StorageProcessor, tx: &Transaction, + depth: &mut i32, ) -> crate::Result<(), SimulateError> { + if *depth >= 20 { + error!("simulate tx:{:?} depth:{:?} over 20", tx.txid(), depth); + return Err(SimulateError::StackOverFlow); + } + *depth = *depth + 1; let tx_id = tx.txid(); let mut need_handle_first = vec![]; for input in &tx.input { @@ -384,7 +391,7 @@ impl SimulatorServer { "parent tx :{:?},exist,but not in utxo data,child_hash:{:?},need to simulate parent tx", &parent, &tx_id ); - self.loop_simulate_tx(h, block, processor, &parent_tx)?; + self.loop_simulate_tx(h, block, processor, &parent_tx, depth)?; if index == need_handle_first.len() - 1 { info!( "all parent txs {:?} simulate done,start to simulate child_hash:{:?}", @@ -475,7 +482,6 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { .iter() .map(|(_, txid)| txid) .collect::>(); - use rayon::prelude::*; let mut tx_outs = Vec::new(); for (tx, _) in block.txdata.iter() { for input in tx.input.iter() { @@ -489,7 +495,7 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { } else if tx_out_cache.contains(&prev_output) { cache_outputs_count.fetch_add(1, Ordering::Relaxed); continue; - } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output).unwrap() { + } else if let Some(txout) = processor.get_txout_by_outpoint(&prev_output)? { miss_outputs_count.fetch_add(1, Ordering::Relaxed); tx_outs.push((prev_output, Some(txout))); } else { @@ -502,7 +508,11 @@ impl<'a, 'db, 'tx> Simulator<'a, 'db, 'tx> { if let Some(tx_out) = value { tx_out_cache.insert(out_point, tx_out); } else { - let tx = processor.get_transaction(&out_point.txid)?.unwrap(); + let tx = processor.get_transaction(&out_point.txid)?; + if tx.is_none() { + return Err(anyhow!("missing transaction {}", out_point.txid.clone())); + } + let tx = tx.unwrap(); let out = tx.output[out_point.vout as usize].clone(); let tx_out = TxOut { value: out.value, @@ -804,6 +814,7 @@ mod tests { simulate_bitcoin_rpc_pass: Some("bitcoinrpc".to_string()), simulate_bitcoin_rpc_user: Some("bitcoinrpc".to_string()), simulate_index: Some("./simulate".to_string().into()), + rx: None, }; opt } diff --git a/src/lib.rs b/src/lib.rs index eded368421..f5c2ad6b2a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -236,7 +236,9 @@ pub fn main() { }) .expect("Error setting handler"); - match Arguments::parse().run() { + let mut server = Arguments::parse(); + server.options.rx = Some(rx); + match server.run() { Err(err) => { eprintln!("error: {err}"); err diff --git a/src/okx/protocol/context.rs b/src/okx/protocol/context.rs index e4b9ace114..1f3109f6ce 100644 --- a/src/okx/protocol/context.rs +++ b/src/okx/protocol/context.rs @@ -25,7 +25,6 @@ use crate::okx::protocol::{BlockContext, ContextTrait}; use crate::SatPoint; use anyhow::anyhow; use bitcoin::{Network, OutPoint, TxOut, Txid}; -use log::info; use redb::Table; #[allow(non_snake_case)] @@ -232,10 +231,6 @@ impl<'a, 'db, 'txn> Brc20ReaderWriter for Context<'a, 'db, 'txn> { txid: &Txid, receipt: &[Receipt], ) -> crate::Result<(), Self::Error> { - info!( - "save transaction receipts: txid: {}, receipt: {:?}", - txid, receipt - ); save_transaction_receipts(self.BRC20_EVENTS, txid, receipt) } diff --git a/src/options.rs b/src/options.rs index 149f0c58ae..42da7cdd16 100644 --- a/src/options.rs +++ b/src/options.rs @@ -92,7 +92,7 @@ pub struct Options { #[arg( long, - default_value = "true", + default_value = "false", help = "Set lru cache to . By default 10000000" )] pub(crate) simulate_enable: bool, diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 6029ba3155..2ed78201df 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -1,7 +1,6 @@ use crate::index::simulator::simulate::{start_simulator, SimulatorServer}; use crate::okx::datastore::brc20::Receipt; use crate::okx::datastore::ord::InscriptionOp; -use crate::subcommand::server::ord::OrdInscription; use bitcoincore_rpc::Auth; use { self::{ From 198491218b92e0af6676992007ab6a318747038c Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sun, 18 Feb 2024 10:01:53 +0800 Subject: [PATCH 62/66] flag --- src/options.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options.rs b/src/options.rs index 54d72dcf7d..7ef0346acb 100644 --- a/src/options.rs +++ b/src/options.rs @@ -93,7 +93,7 @@ pub struct Options { #[arg( long, default_value = "false", - help = "Set lru cache to . By default 10000000" + help = "simulate tx flag, default is false" )] pub(crate) simulate_enable: bool, #[arg(long, help = "bitcoin zmq url.")] From 6918b06b34b8099315bbe2af31c153d38ddaf13a Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sun, 18 Feb 2024 10:05:59 +0800 Subject: [PATCH 63/66] allow --- src/index.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.rs b/src/index.rs index b600ccc0d8..bbf2bb5564 100644 --- a/src/index.rs +++ b/src/index.rs @@ -272,6 +272,7 @@ impl Index { let once = Once::new(); let progress_bar = Mutex::new(None); + #[allow(clippy::blocks_in_conditions)] let database = match Database::builder() .set_cache_size(db_cache_size) .set_repair_callback(move |progress: &mut RepairSession| { From ecc592e24217c6825c8d83ccdf474802a749ee7c Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sun, 18 Feb 2024 14:28:19 +0800 Subject: [PATCH 64/66] fix test --- src/subcommand/server.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 388d9ef36e..81a7b07178 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -208,16 +208,20 @@ impl Server { }); INDEXER.lock().unwrap().replace(index_thread); - let client = Arc::new( - Client::new( - options.rpc_url.as_ref().unwrap().as_ref(), - Auth::UserPass( - options.bitcoin_rpc_user.as_ref().unwrap().clone(), - options.bitcoin_rpc_pass.as_ref().unwrap().clone(), - ), - ) - .unwrap(), - ); + let client = if options.simulate_enable { + Some(Arc::new( + Client::new( + options.simulate_bitcoin_rpc_url.as_ref().unwrap().as_ref(), + Auth::UserPass( + options.simulate_bitcoin_rpc_user.as_ref().unwrap().clone(), + options.simulate_bitcoin_rpc_pass.as_ref().unwrap().clone(), + ), + ) + .unwrap(), + )) + } else { + None + }; #[derive(OpenApi)] #[openapi( @@ -1698,7 +1702,7 @@ impl Server { } async fn simulate_brc20( - Extension(client): Extension>, + Extension(client): Extension>>, Extension(simulator): Extension>, Path(tx_id): Path, ) -> ApiResult> { @@ -1706,7 +1710,7 @@ impl Server { return Err(ApiError::Internal("simulator not enabled".to_string())); } - let tx = client.get_raw_transaction(&tx_id, None); + let tx = client.unwrap().get_raw_transaction(&tx_id, None); if tx.is_err() { return Err(ApiError::NotFound("tx not found".to_string())); } From a21be2539890fd60c0c62a358d590f2a5d632f63 Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Sun, 18 Feb 2024 14:55:37 +0800 Subject: [PATCH 65/66] rm ut --- src/index/simulator/simulate.rs | 82 --------------------------------- 1 file changed, 82 deletions(-) diff --git a/src/index/simulator/simulate.rs b/src/index/simulator/simulate.rs index 7c5efa8237..a22099e81a 100644 --- a/src/index/simulator/simulate.rs +++ b/src/index/simulator/simulate.rs @@ -732,85 +732,3 @@ async fn do_start_simulator(ops: Options, internal: Arc) -> Option Options { - let opt = crate::options::Options { - log_level: Default::default(), - log_dir: None, - bitcoin_data_dir: None, - bitcoin_rpc_pass: Some("bitcoinrpc".to_string()), - bitcoin_rpc_user: Some("bitcoinrpc".to_string()), - chain_argument: Default::default(), - config: None, - config_dir: None, - cookie_file: None, - data_dir: Default::default(), - db_cache_size: None, - lru_size: 0, - first_inscription_height: None, - height_limit: None, - index: Some(PathBuf::from("./internal")), - index_runes: false, - index_sats: true, - index_transactions: true, - no_index_inscriptions: false, - regtest: true, - rpc_url: None, - signet: false, - testnet: false, - enable_save_ord_receipts: true, - enable_index_bitmap: true, - enable_index_brc20: true, - first_brc20_height: Some(0), - simulate_enable: true, - simulate_zmq_url: Some("tcp://0.0.0.0:28332".to_string()), - simulate_bitcoin_rpc_url: Some("http://localhost:18443".to_string()), - simulate_bitcoin_rpc_pass: Some("bitcoinrpc".to_string()), - simulate_bitcoin_rpc_user: Some("bitcoinrpc".to_string()), - simulate_index: Some("./simulate".to_string().into()), - rx: None, - commit_height_interval: 0, - commit_persist_interval: 0, - }; - opt - } -} From 9ca59ff0a4d7d365c884083e4f9dc3605cd34ccc Mon Sep 17 00:00:00 2001 From: ItsFunny <39111451+ItsFunny@users.noreply.github.com> Date: Thu, 7 Mar 2024 15:44:22 +0800 Subject: [PATCH 66/66] dep --- Cargo.lock | 35 +++++++++++++++++++++++++++++------ Cargo.toml | 2 +- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea46c94daf..aaba7763ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -183,7 +183,7 @@ checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" dependencies = [ "concurrent-queue", "event-listener 4.0.2", - "event-listener-strategy", + "event-listener-strategy 0.4.0", "futures-core", "pin-project-lite", ] @@ -251,7 +251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" dependencies = [ "event-listener 4.0.2", - "event-listener-strategy", + "event-listener-strategy 0.4.0", "pin-project-lite", ] @@ -1349,6 +1349,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "event-listener-strategy" version = "0.4.0" @@ -1359,6 +1370,16 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener-strategy" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +dependencies = [ + "event-listener 5.2.0", + "pin-project-lite", +] + [[package]] name = "executable-path" version = "1.0.0" @@ -1911,7 +1932,7 @@ dependencies = [ [[package]] name = "indexer-sdk" version = "0.1.0" -source = "git+https://github.com/okx/indexer-sdk.git?rev=34e6e7bfc8c0d3db41e2867f71428859396407b0#34e6e7bfc8c0d3db41e2867f71428859396407b0" +source = "git+https://github.com/okx/indexer-sdk.git?rev=ccb97b47a0b7d44a8fa9c3a939e5d8a1e242245a#ccb97b47a0b7d44a8fa9c3a939e5d8a1e242245a" dependencies = [ "async-channel 1.9.0", "async-trait", @@ -4456,11 +4477,13 @@ checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" [[package]] name = "wg" -version = "0.4.2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "232b936590098c53587078a25ed087d5cd3aa18ec65c85bb42c6ae335263e15b" +checksum = "58f8542ff1b4f572beb2fa9620c0c5fc9abf6b15cfb609bfd87886328cbff4ef" dependencies = [ - "atomic-waker", + "event-listener 5.2.0", + "event-listener-strategy 0.5.0", + "pin-project-lite", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 319452d74d..d3fea9ff5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,7 +74,7 @@ log4rs = { version = "1.2.0", features = ["gzip"] } once_cell = "1.19.0" rmp-serde = "1.1.2" rayon = "1.8.0" -indexer-sdk={git="https://github.com/okx/indexer-sdk.git",rev = "34e6e7bfc8c0d3db41e2867f71428859396407b0"} +indexer-sdk={git="https://github.com/okx/indexer-sdk.git",rev = "ccb97b47a0b7d44a8fa9c3a939e5d8a1e242245a"} async-channel = "1.9.0" [dev-dependencies] criterion = "0.5.1"