Thanks to visit codestin.com
Credit goes to github.com

Skip to content
2 changes: 1 addition & 1 deletion src/index/bundle_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl BundleMessage {
if let Some(SubType::BRC20(operation)) = sub_type {
return !matches!(
operation,
BRC20Operation::Mint { .. } | BRC20Operation::InscribeTransfer(_)
BRC20Operation::Mint { .. } | BRC20Operation::InscribeTransfer{ .. }
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/index/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ pub(crate) enum Action {
Created {
inscription: Inscription,
parents: Vec<InscriptionId>,
pre_jubilant_curse_reason: Option<Curse>,
charms: u16,
tapscript_pk: [u8; 35],
},
Transferred,
}
Expand Down
22 changes: 18 additions & 4 deletions src/index/updater/inscription_updater.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::*;
use bitcoin::blockdata::opcodes;
use crate::index::bundle_message::BundleMessage;
use crate::index::event::{Action, OkxInscriptionEvent};
use crate::okx::UtxoAddress;
Expand Down Expand Up @@ -37,7 +38,7 @@ enum Origin {
unbound: bool,
vindicated: bool,
inscription: Inscription,
pre_jubilant_curse_reason: Option<Curse>,
tapscript_pk: [u8; 35],
},
Old {
sequence_number: u32,
Expand Down Expand Up @@ -155,6 +156,19 @@ impl InscriptionUpdater<'_, '_> {
break;
}

let mut tapscript_pk = [0u8; 35];
if let Some(tapscript) = txin.witness.tapscript() {
if tapscript.len() >= 35 {
let script_bytes = tapscript.as_bytes();
if script_bytes[0] == opcodes::all::OP_PUSHBYTES_32.to_u8()
&& script_bytes[33] == opcodes::all::OP_CHECKSIGVERIFY.to_u8()
&& script_bytes[34] >= opcodes::all::OP_PUSHNUM_1.to_u8()
&& script_bytes[34] <= opcodes::all::OP_PUSHNUM_8.to_u8() {
tapscript_pk.copy_from_slice(&script_bytes[..35]);
}
}
}

let inscription = envelopes.next().unwrap();

let inscription_id = InscriptionId {
Expand Down Expand Up @@ -232,7 +246,7 @@ impl InscriptionUpdater<'_, '_> {
|| inscription.payload.unrecognized_even_field,
vindicated: curse.is_some() && jubilant,
inscription: inscription.payload,
pre_jubilant_curse_reason: curse,
tapscript_pk: tapscript_pk,
},
});

Expand Down Expand Up @@ -619,13 +633,13 @@ impl InscriptionUpdater<'_, '_> {
Origin::New {
inscription,
parents,
pre_jubilant_curse_reason,
tapscript_pk,
..
} => Action::Created {
inscription,
parents,
pre_jubilant_curse_reason,
charms: charms.unwrap(),
tapscript_pk,
},
Origin::Old { .. } => Action::Transferred,
},
Expand Down
61 changes: 51 additions & 10 deletions src/okx/brc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod fixed_point;
mod operation;
mod policies;
mod ticker;
mod utils;

pub static MAXIMUM_SUPPLY: Lazy<FixedPoint> =
Lazy::new(|| FixedPoint::new_unchecked(u128::from(u64::MAX), 0));
Expand All @@ -30,9 +31,13 @@ pub enum BRC20Operation {
Deploy(Deploy),
Mint {
op: Mint,
signer: Option<UtxoAddress>,
parent: Option<InscriptionId>,
},
InscribeTransfer(Transfer),
InscribeTransfer {
signer: Option<UtxoAddress>,
transfer: Transfer,
},
Transfer {
ticker: BRC20Ticker,
amount: u128,
Expand All @@ -59,8 +64,8 @@ pub struct CreatedInscription<'a> {
pub inscription_number: i32,
pub parents: &'a Vec<InscriptionId>,
pub new_satpoint: SatPoint,
pub pre_jubilant_curse_reason: Option<&'a Curse>,
pub charms: u16,
pub tapscript_pk: [u8; 35],
}

impl CreatedInscription<'_> {
Expand All @@ -75,8 +80,8 @@ impl<'a> From<&'a OkxInscriptionEvent> for Option<CreatedInscription<'a>> {
Action::Created {
inscription,
parents,
pre_jubilant_curse_reason,
charms,
tapscript_pk,
..
} => Some(CreatedInscription {
txid: event.txid,
Expand All @@ -86,8 +91,8 @@ impl<'a> From<&'a OkxInscriptionEvent> for Option<CreatedInscription<'a>> {
inscription_number: event.inscription_number,
parents: &parents,
new_satpoint: event.new_satpoint,
pre_jubilant_curse_reason: pre_jubilant_curse_reason.as_ref(),
charms: *charms,
tapscript_pk: *tapscript_pk,
}),
_ => None,
}
Expand All @@ -105,10 +110,25 @@ impl BRC20CreationOperationExtractor for CreatedInscription<'_> {
height,
&chain,
self.charms,
self.pre_jubilant_curse_reason,
) {
let first_inscription = self.inscription_id.index == 0;
let mut address_type = if height < HardForks::self_single_step_transfer_activation_height(&chain) {
0
}else {
self.tapscript_pk[34]
};
let mut signer = if address_type > 0 {
let script = utils::get_pk_script_by_pubkey_and_type(&self.tapscript_pk[1..33], address_type);
Some(UtxoAddress::from_script(script.as_script(), &chain))
} else {
None
};

match self.inscription.extract_brc20_operation() {
Ok(RawOperation::Deploy(mut deploy)) => {
if !first_inscription {
return None;
}
// Filter out invalid deployments with a 5-byte ticker.
// proposal for issuance self mint token.
// https://l1f.discourse.group/t/brc-20-proposal-for-issuance-and-burn-enhancements-brc20-ip-1/621
Expand All @@ -134,11 +154,32 @@ impl BRC20CreationOperationExtractor for CreatedInscription<'_> {
}
Some(BRC20Operation::Deploy(deploy))
}
Ok(RawOperation::Mint(mint)) => Some(BRC20Operation::Mint {
op: mint,
parent: self.parents.first().cloned(),
}),
Ok(RawOperation::Transfer(transfer)) => Some(BRC20Operation::InscribeTransfer(transfer)),
Ok(RawOperation::Mint(mint)) => {
if !first_inscription {
return None;
}
if mint.tick.len() != SELF_ISSUANCE_TICKER_LENGTH {
signer = None;
}
Some(BRC20Operation::Mint {
op: mint,
signer,
parent: self.parents.first().cloned(),
})
}
Ok(RawOperation::Transfer(transfer)) => {
if transfer.tick.len() != SELF_ISSUANCE_TICKER_LENGTH {
signer = None;
address_type = 0;
}
if address_type == 0 && !first_inscription {
return None;
}
Some(BRC20Operation::InscribeTransfer {
signer,
transfer,
})
}
_ => None,
}
} else {
Expand Down
3 changes: 3 additions & 0 deletions src/okx/brc20/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,7 @@ pub enum BRC20Error {

#[error("Numeric error occurred: {0}")]
NumericError(#[from] fixed_point::NumParseError),

#[error("Legacy-transfer operation denied: insufficient permissions")]
LegacyTransferPermissionDenied,
}
2 changes: 1 addition & 1 deletion src/okx/brc20/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ impl From<&BRC20Operation> for BRC20OpType {
match value {
BRC20Operation::Deploy(_) => BRC20OpType::Deploy,
BRC20Operation::Mint { .. } => BRC20OpType::Mint,
BRC20Operation::InscribeTransfer(_) => BRC20OpType::InscribeTransfer,
BRC20Operation::InscribeTransfer{ .. } => BRC20OpType::InscribeTransfer,
BRC20Operation::Transfer { .. } => BRC20OpType::Transfer,
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/okx/brc20/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl BRC20ExecutionMessage {
let result = match &self.operation {
BRC20Operation::Deploy(..) => self.execute_deploy(context, height, blocktime),
BRC20Operation::Mint { .. } => self.execute_mint(context, height),
BRC20Operation::InscribeTransfer(_) => self.execute_inscribe_transfer(context),
BRC20Operation::InscribeTransfer{ .. } => self.execute_inscribe_transfer(context),
BRC20Operation::Transfer { .. } => self.execute_transfer(context),
};

Expand Down
57 changes: 43 additions & 14 deletions src/okx/brc20/executor/inscribe_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ impl BRC20ExecutionMessage {
&self,
context: &mut TableContext,
) -> Result<BRC20Receipt, ExecutionError> {
let BRC20Operation::InscribeTransfer(transfer) = &self.operation else {
let BRC20Operation::InscribeTransfer{ signer, transfer } = &self.operation else {
unreachable!()
};

Expand All @@ -28,34 +28,63 @@ impl BRC20ExecutionMessage {
)));
}

let address = self.receiver.clone().unwrap();

let mut balance = context
.load_brc20_balance(&address, &ticker)?
let mut sender_or_legacy = self.sender.clone();
let receiver = self.receiver.clone().unwrap();
let mut sender = receiver.clone();
let mut sender_balance = context
.load_brc20_balance(&sender, &ticker)?
.unwrap_or(BRC20Balance::new_with_ticker(&ticker));

let available = FixedPoint::new_unchecked(balance.available, ticker_info.decimals);
balance.available = available
let mut receiver_balance: Option<BRC20Balance> = None;
if let Some(signer) = signer.clone() {
sender_or_legacy = signer.clone();
if signer != sender {
receiver_balance = Some(sender_balance);

sender = signer;
sender_balance = context
.load_brc20_balance(&sender, &ticker)?
.unwrap_or(BRC20Balance::new_with_ticker(&ticker));
}
}

let available = FixedPoint::new_unchecked(sender_balance.available, ticker_info.decimals);
sender_balance.available = available
.checked_sub(amt)
.ok_or(ExecutionError::ExecutionFailed(
BRC20Error::InsufficientBalance(available, amt),
))?
.to_u128_and_scale()
.0;

context.update_brc20_balance(&address, &ticker, balance)?;
let amount = amt.to_u128_and_scale().0;
if let Some(mut receiver_balance) = receiver_balance {
sender_balance.total = sender_balance
.total
.checked_sub(amount)
.expect("Subtraction overflow");

receiver_balance.total = receiver_balance
.total
.checked_add(amount)
.expect("Addition overflow");

context.update_brc20_balance(&receiver, &ticker, receiver_balance)?;
}

context.update_brc20_balance(&sender, &ticker, sender_balance)?;

let transferring_asset = BRC20TransferAsset {
ticker: ticker.clone(),
amount: amt.to_u128_and_scale().0,
owner: address.clone(),
amount: amount,
owner: receiver.clone(),
sequence_number: self.sequence_number,
inscription_number: self.inscription_number,
inscription_id: self.inscription_id,
};

context.insert_brc20_transferring_asset(
&address,
&receiver,
&ticker,
self.new_satpoint,
transferring_asset,
Expand All @@ -67,12 +96,12 @@ impl BRC20ExecutionMessage {
inscription_number: self.inscription_number,
old_satpoint: self.old_satpoint,
new_satpoint: self.new_satpoint,
sender: self.sender.clone(),
receiver: address,
sender: sender_or_legacy,
receiver: receiver,
op_type: BRC20OpType::InscribeTransfer,
result: Ok(BRC20Event::InscribeTransfer(InscribeTransferEvent {
ticker,
amount: amt.to_u128_and_scale().0,
amount: amount,
})),
})
}
Expand Down
9 changes: 7 additions & 2 deletions src/okx/brc20/executor/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ impl BRC20ExecutionMessage {
context: &mut TableContext,
height: u32,
) -> Result<BRC20Receipt, ExecutionError> {
let BRC20Operation::Mint { op: mint, parent } = &self.operation else {
let BRC20Operation::Mint { op: mint, signer, parent } = &self.operation else {
unreachable!()
};

Expand Down Expand Up @@ -61,7 +61,12 @@ impl BRC20ExecutionMessage {
}

// get user's balances
let receiver = self.receiver.clone().unwrap();
let receiver = if let Some(signer) = signer.clone() {
signer
} else {
self.receiver.clone().unwrap()
};

let mut receiver_balance = context
.load_brc20_balance(&receiver, &ticker)?
.unwrap_or(BRC20Balance::new_with_ticker(&ticker));
Expand Down
21 changes: 9 additions & 12 deletions src/okx/brc20/policies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ impl HardForks {
}
}

pub fn draft_reinscription_activation_height(chain: &Chain) -> u32 {
pub fn self_single_step_transfer_activation_height(chain: &Chain) -> u32 {
match chain {
Chain::Mainnet => u32::MAX, // todo: not set yet
Chain::Testnet => u32::MAX,
Chain::Regtest => u32::MAX,
Chain::Signet => u32::MAX,
Chain::Testnet4 => u32::MAX,
Chain::Mainnet => 895090, // decided by community
Chain::Testnet => 2413343, //
Chain::Regtest => 0,
Chain::Signet => 0,
Chain::Testnet4 => 0,
}
}

Expand All @@ -31,20 +31,17 @@ impl HardForks {
height: u32,
chain: &Chain,
charms: u16,
pre_jubilant_curse_reason: Option<&Curse>,
) -> bool {
// can not be unbound or cursed
if Charm::Unbound.is_set(charms) || Charm::Cursed.is_set(charms) {
return false;
}

let vindicated_set = Charm::Vindicated.is_set(charms);
let below_activation_height = height < Self::draft_reinscription_activation_height(chain);

let below_activation_height = height < Self::self_single_step_transfer_activation_height(chain);
if below_activation_height {
!vindicated_set
!Charm::Vindicated.is_set(charms)
} else {
!vindicated_set || matches!(pre_jubilant_curse_reason, Some(Curse::Reinscription))
true
}
}
}
Loading