feat: extract additional data

This commit is contained in:
Ludo Galabru
2024-01-25 10:40:14 -05:00
parent 2db6f1fb44
commit 4141fd6cca
8 changed files with 128 additions and 18 deletions

42
Cargo.lock generated
View File

@@ -477,9 +477,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chainhook-sdk"
version = "0.12.1"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54209dae9bcea839b2b3fea2546eb52f84b0a4224049ed7f09ed116e2942a5ae"
checksum = "d960301b0bd0ed096d37ee17c0d4a67a773eb374089a9b912078bfd3ee218676"
dependencies = [
"base58 0.2.0",
"base64 0.21.5",
@@ -512,9 +512,9 @@ dependencies = [
[[package]]
name = "chainhook-types"
version = "1.3.1"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ebcb0d5e7c79a5b44a8ae0d31654605bf2756303c0cb91f73adfcd4e3bc52fc"
checksum = "66859c3478ca302202b5cc96fe19df6f5d67d48fd909a6bf86941477de465643"
dependencies = [
"hex",
"schemars 0.8.16",
@@ -538,6 +538,33 @@ dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "ciborium"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
[[package]]
name = "ciborium-ll"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"
dependencies = [
"ciborium-io",
"half",
]
[[package]]
name = "clang-sys"
version = "1.6.1"
@@ -1367,6 +1394,12 @@ dependencies = [
"tracing",
]
[[package]]
name = "half"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]]
name = "hashbrown"
version = "0.11.2"
@@ -2268,6 +2301,7 @@ dependencies = [
"anyhow",
"atty",
"chainhook-sdk",
"ciborium",
"crossbeam-channel",
"dashmap",
"flate2",

View File

@@ -10,7 +10,7 @@ serde_json = "1"
serde_derive = "1"
hex = "0.4.3"
rand = "0.8.5"
chainhook-sdk = { version = "=0.12.1", features = ["zeromq"] }
chainhook-sdk = { version = "=0.12.2", features = ["zeromq"] }
# chainhook-sdk = { version = "=0.12.1", path = "../../../chainhook/components/chainhook-sdk", features = ["zeromq"] }
hiro-system-kit = "0.3.1"
reqwest = { version = "0.11", default-features = false, features = [
@@ -43,6 +43,7 @@ rocksdb = { version = "0.21.0", default-features = false, features = [
pprof = { version = "0.13.0", features = ["flamegraph"], optional = true }
hyper = { version = "=0.14.27" }
lazy_static = { version = "1.4.0" }
ciborium = "0.2.1"
# [profile.release]
# debug = true

View File

@@ -7,6 +7,7 @@ use chainhook_sdk::types::{
OrdinalOperation,
};
use chainhook_sdk::utils::Context;
use serde_json::json;
use std::collections::BTreeMap;
use std::str::FromStr;
@@ -59,6 +60,17 @@ pub fn parse_inscriptions_from_witness(
let mut content_bytes = "0x".to_string();
content_bytes.push_str(&hex::encode(&inscription_content_bytes));
let parent = envelope.payload.parent().and_then(|i| Some(i.to_string()));
let delegate = envelope
.payload
.delegate()
.and_then(|i| Some(i.to_string()));
let metaprotocol = envelope
.payload
.metaprotocol()
.and_then(|p| Some(p.to_string()));
let metadata = envelope.payload.metadata().and_then(|m| Some(json!(m)));
let reveal_data = OrdinalInscriptionRevealData {
content_type: envelope
.payload
@@ -75,6 +87,10 @@ pub fn parse_inscriptions_from_witness(
inscription_fee: 0,
inscription_number: OrdinalInscriptionNumber::zero(),
inscriber_address: None,
parent,
delegate,
metaprotocol,
metadata,
ordinal_number: 0,
ordinal_block_height: 0,
ordinal_offset: 0,

View File

@@ -5,7 +5,7 @@ use std::{
};
use chainhook_sdk::{
bitcoincore_rpc_json::bitcoin::{Address, Network, ScriptBuf},
bitcoincore_rpc_json::bitcoin::Network,
types::{
BitcoinBlockData, BitcoinNetwork, BitcoinTransactionData, BlockIdentifier,
OrdinalInscriptionCurseType, OrdinalInscriptionNumber,
@@ -930,7 +930,6 @@ pub fn consolidate_block_with_pre_computed_ordinals_data(
let _ = augment_transaction_with_ordinals_transfers_data(
tx,
tx_index,
&block.block_identifier,
&network,
&coinbase_txid,
coinbase_subsidy,

View File

@@ -1,9 +1,8 @@
use chainhook_sdk::{
bitcoincore_rpc_json::bitcoin::{Address, Network, ScriptBuf},
types::{
BitcoinBlockData, BitcoinNetwork, BitcoinTransactionData, BlockIdentifier,
OrdinalInscriptionTransferData, OrdinalInscriptionTransferDestination, OrdinalOperation,
TransactionIdentifier,
BitcoinBlockData, BitcoinNetwork, BitcoinTransactionData, OrdinalInscriptionTransferData,
OrdinalInscriptionTransferDestination, OrdinalOperation, TransactionIdentifier,
},
utils::Context,
};
@@ -40,7 +39,6 @@ pub fn augment_block_with_ordinals_transfer_data(
let transfers = augment_transaction_with_ordinals_transfers_data(
tx,
tx_index,
&block.block_identifier,
&network,
&coinbase_txid,
coinbase_subsidy,
@@ -150,7 +148,6 @@ pub fn compute_satpoint_post_transfer(
pub fn augment_transaction_with_ordinals_transfers_data(
tx: &mut BitcoinTransactionData,
tx_index: usize,
block_identifier: &BlockIdentifier,
network: &Network,
coinbase_txid: &TransactionIdentifier,
coinbase_subsidy: u64,

View File

@@ -39,7 +39,13 @@ pub fn compute_satoshi_number(
{
Some(entry) => {
let tx = entry.value();
((tx.inputs[inscription_input_index].txin.clone(), tx.inputs[inscription_input_index].vout.into()), tx.inputs[inscription_input_index].block_height)
(
(
tx.inputs[inscription_input_index].txin.clone(),
tx.inputs[inscription_input_index].vout.into(),
),
tx.inputs[inscription_input_index].block_height,
)
}
None => loop {
match find_pinned_block_bytes_at_block_height(ordinal_block_number, 3, &blocks_db, &ctx)
@@ -51,7 +57,13 @@ pub fn compute_satoshi_number(
let cursor = BlockBytesCursor::new(&block_bytes.as_ref());
match cursor.find_and_serialize_transaction_with_txid(&txid) {
Some(tx) => {
break ((tx.inputs[inscription_input_index].txin.clone(), tx.inputs[inscription_input_index].vout.into()), tx.inputs[inscription_input_index].block_height);
break (
(
tx.inputs[inscription_input_index].txin.clone(),
tx.inputs[inscription_input_index].vout.into(),
),
tx.inputs[inscription_input_index].block_height,
);
}
None => return Err(format!("txid not in block #{ordinal_block_number}")),
}
@@ -199,7 +211,8 @@ pub fn compute_satoshi_number(
}
} else {
// isolate the target transaction
let tx_bytes_cursor = match block_cursor.find_and_serialize_transaction_with_txid(&txid) {
let tx_bytes_cursor = match block_cursor.find_and_serialize_transaction_with_txid(&txid)
{
Some(entry) => entry,
None => {
ctx.try_log(|logger| {
@@ -229,7 +242,8 @@ pub fn compute_satoshi_number(
if sats_out < sats_in {
back_track.push((ordinal_block_number, tx_cursor.0.clone(), tx_cursor.1));
traversals_cache.insert((ordinal_block_number, tx_cursor.0), tx_bytes_cursor.clone());
traversals_cache
.insert((ordinal_block_number, tx_cursor.0), tx_bytes_cursor.clone());
ordinal_offset = sats_out - (sats_in - input.txin_value);
ordinal_block_number = input.block_height;
tx_cursor = (input.txin.clone(), input.vout as usize);

View File

@@ -25,6 +25,7 @@ pub const PARENT_TAG: [u8; 1] = [3];
pub const METADATA_TAG: [u8; 1] = [5];
pub const METAPROTOCOL_TAG: [u8; 1] = [7];
pub const CONTENT_ENCODING_TAG: [u8; 1] = [9];
pub const DELEGATE_TAG: [u8; 1] = [11];
type Result<T> = std::result::Result<T, script::Error>;
pub type RawEnvelope = Envelope<Vec<Vec<u8>>>;
@@ -91,6 +92,7 @@ impl From<RawEnvelope> for ParsedEnvelope {
let content_encoding = remove_field(&mut fields, &CONTENT_ENCODING_TAG);
let content_type = remove_field(&mut fields, &CONTENT_TYPE_TAG);
let delegate = remove_field(&mut fields, &DELEGATE_TAG);
let metadata = remove_and_concatenate_field(&mut fields, &METADATA_TAG);
let metaprotocol = remove_field(&mut fields, &METAPROTOCOL_TAG);
let parent = remove_field(&mut fields, &PARENT_TAG);
@@ -109,13 +111,14 @@ impl From<RawEnvelope> for ParsedEnvelope {
.cloned()
.collect()
}),
metaprotocol,
parent,
delegate,
content_encoding,
content_type,
duplicate_field,
incomplete_field,
metadata,
metaprotocol,
parent,
pointer,
unrecognized_even_field,
},

View File

@@ -1,3 +1,5 @@
use std::io::Cursor;
use chainhook_sdk::bitcoin::{hashes::Hash, Txid};
use super::{inscription_id::InscriptionId, media::Media};
@@ -26,6 +28,7 @@ pub struct Inscription {
pub parent: Option<Vec<u8>>,
pub pointer: Option<Vec<u8>>,
pub unrecognized_even_field: bool,
pub delegate: Option<Vec<u8>>,
}
impl Inscription {
@@ -159,6 +162,49 @@ impl Inscription {
str::from_utf8(self.metaprotocol.as_ref()?).ok()
}
fn inscription_id_field(field: &Option<Vec<u8>>) -> Option<InscriptionId> {
let value = field.as_ref()?;
if value.len() < Txid::LEN {
return None;
}
if value.len() > Txid::LEN + 4 {
return None;
}
let (txid, index) = value.split_at(Txid::LEN);
if let Some(last) = index.last() {
// Accept fixed length encoding with 4 bytes (with potential trailing zeroes)
// or variable length (no trailing zeroes)
if index.len() != 4 && *last == 0 {
return None;
}
}
let txid = Txid::from_slice(txid).unwrap();
let index = [
index.first().copied().unwrap_or(0),
index.get(1).copied().unwrap_or(0),
index.get(2).copied().unwrap_or(0),
index.get(3).copied().unwrap_or(0),
];
let index = u32::from_le_bytes(index);
Some(InscriptionId { txid, index })
}
pub(crate) fn delegate(&self) -> Option<InscriptionId> {
Self::inscription_id_field(&self.delegate)
}
pub(crate) fn metadata(&self) -> Option<ciborium::Value> {
ciborium::from_reader(Cursor::new(self.metadata.as_ref()?)).ok()
}
pub(crate) fn parent(&self) -> Option<InscriptionId> {
use chainhook_sdk::bitcoin::hash_types::Txid as TXID_LEN;
let value = self.parent.as_ref()?;