Skip to content

Commit

Permalink
Merge pull request #77 from RGB-WG/fix/73
Browse files Browse the repository at this point in the history
Fix use of velocity classes
  • Loading branch information
dr-orlovsky authored Jun 30, 2023
2 parents e74d292 + c4711b5 commit f3d0639
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 13 deletions.
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ pub use invoice::{
};
pub use pay::{InventoryWallet, PayError};

/// BIP32 derivation index for outputs which may contain assigned RGB state.
pub const RGB_NATIVE_DERIVATION_INDEX: u32 = 9;
/// BIP32 derivation index for outputs which are tweaked with Tapret commitment
/// and may also optionally contain assigned RGB state.
pub const RGB_TAPRET_DERIVATION_INDEX: u32 = 10;

// 1. Construct main state transition with transition builder
// -- shortcut using invoice to do that construction (like .with_invoice())
// -- have a construction for the "remaining state" assigned to a seal
Expand Down
13 changes: 7 additions & 6 deletions src/pay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@ use rgbstd::interface::{BuilderError, ContractSuppl, TypedState, VelocityHint};
use rgbstd::persistence::{ConsignerError, Inventory, InventoryError, Stash};

use crate::invoice::Beneficiary;
use crate::psbt::{DbcPsbtError, PsbtDbc, RgbExt, RgbInExt, RgbPsbtError};
use crate::RgbInvoice;
use crate::psbt::{DbcPsbtError, PsbtDbc, RgbExt, RgbInExt, RgbOutExt, RgbPsbtError};
use crate::{RgbInvoice, RGB_NATIVE_DERIVATION_INDEX, RGB_TAPRET_DERIVATION_INDEX};

#[derive(Debug, Display, Error, From)]
#[display(inner)]
pub enum PayError<E1: Error, E2: Error>
where E1: From<E2>
{
/// not enough PSBT output found to put all required state (can't add
/// assignment {1} for {0}-velocity state).
/// assignment type {1} for {0}-velocity state).
#[display(doc_comments)]
NoBlankOrChange(VelocityHint, AssignmentType),

Expand Down Expand Up @@ -143,16 +143,17 @@ pub trait InventoryWallet: Inventory {
if beneficiary_output == Some(no as u32) {
continue;
}
if let Some(class) = outp
if outp
// NB: Here we assume that if output has derivation information it belongs to our wallet.
.bip32_derivation
.first_key_value()
.and_then(|(_, src)| src.1.into_iter().rev().nth(1))
.copied()
.map(u32::from)
.and_then(|index| u8::try_from(index).ok())
.and_then(|index| VelocityHint::try_from(index).ok())
.filter(|index| *index == RGB_NATIVE_DERIVATION_INDEX || *index == RGB_TAPRET_DERIVATION_INDEX)
.is_some()
{
let class = outp.rgb_velocity_hint().unwrap_or_default();
out_classes.entry(class).or_default().push(no as u32);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/psbt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ pub use tapret::{
};

pub use self::rgb::{
ProprietaryKeyRgb, RgbExt, RgbInExt, RgbPsbtError, PSBT_GLOBAL_RGB_TRANSITION,
PSBT_IN_RGB_CONSUMED_BY, PSBT_RGB_PREFIX,
ProprietaryKeyRgb, RgbExt, RgbInExt, RgbOutExt, RgbPsbtError, PSBT_GLOBAL_RGB_TRANSITION,
PSBT_IN_RGB_CONSUMED_BY, PSBT_OUT_RGB_VELOCITY_HINT, PSBT_RGB_PREFIX,
};
52 changes: 52 additions & 0 deletions src/psbt/rgb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use bitcoin::psbt::{self, PartiallySignedTransaction as Psbt};
use commit_verify::mpc;
use rgb::{BundleItem, ContractId, OpId, Operation, Transition, TransitionBundle};
use rgbstd::accessors::{MergeReveal, MergeRevealError};
use rgbstd::interface::VelocityHint;
use strict_encoding::{SerializeError, StrictDeserialize, StrictSerialize};

use super::lnpbp4::OutputLnpbp4;
Expand All @@ -52,6 +53,9 @@ pub const PSBT_GLOBAL_RGB_TRANSITION: u8 = 0x01;
/// Proprietary key subtype for storing RGB state transition node id which
/// consumes this input.
pub const PSBT_IN_RGB_CONSUMED_BY: u8 = 0x03;
/// Proprietary key subtype for storing hint for the velocity of the state
/// which can be assigned to the provided output.
pub const PSBT_OUT_RGB_VELOCITY_HINT: u8 = 0x10;

/// Extension trait for static functions returning RGB-related proprietary keys.
pub trait ProprietaryKeyRgb {
Expand All @@ -72,6 +76,14 @@ pub trait ProprietaryKeyRgb {
key: contract_id.to_vec(),
}
}

fn rgb_out_velocity_hint() -> ProprietaryKey {
ProprietaryKey {
prefix: PSBT_RGB_PREFIX.to_vec(),
subtype: PSBT_OUT_RGB_VELOCITY_HINT,
key: vec![],
}
}
}

impl ProprietaryKeyRgb for ProprietaryKey {}
Expand Down Expand Up @@ -288,3 +300,43 @@ impl RgbInExt for psbt::Input {
}
}
}

pub trait RgbOutExt {
/// Returns hint for the velocity of the state which may be assigned to the
/// provided output.
///
/// We do not error on invalid data in order to support future update of
/// this proprietary key to a standard one. In this case, the invalid
/// data will be filtered at the moment of PSBT deserialization and this
/// function will return `None` only in situations when the key is absent.
fn rgb_velocity_hint(&self) -> Option<VelocityHint>;

/// Adds hint for the velocity of the state which may be assigned to the
/// PSBT output.
///
/// # Returns
///
/// `false`, if a velocity hint was already present in the input and
/// `true` otherwise.
fn set_rgb_velocity_hint(&mut self, hint: VelocityHint) -> bool;
}

impl RgbOutExt for psbt::Output {
fn rgb_velocity_hint(&self) -> Option<VelocityHint> {
let data = self
.proprietary
.get(&ProprietaryKey::rgb_out_velocity_hint())?;
if data.len() != 1 {
None
} else {
data.first().map(VelocityHint::with_value)
}
}

fn set_rgb_velocity_hint(&mut self, hint: VelocityHint) -> bool {
let prev = self.rgb_velocity_hint();
self.proprietary
.insert(ProprietaryKey::rgb_out_velocity_hint(), vec![hint as u8]);
Some(hint) == prev
}
}
23 changes: 18 additions & 5 deletions std/src/interface/suppl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,26 @@ pub enum VelocityHint {
Unspecified = 0,
/// Should be used for thinks like secondary issuance for tokens which do
/// not inflate very often.
Seldom = 10,
Seldom = 15,
/// Should be used for digital identity revocations.
Episodic = 25,
Episodic = 31,
/// Should be used for digital art, shares, bonds etc.
Regular = 50,
Regular = 63,
/// Should be used for fungible tokens.
Frequent = 75,
Frequent = 127,
/// Should be used for stablecoins and money.
HighFrequency = 100,
HighFrequency = 255,
}

impl VelocityHint {
pub fn with_value(value: &u8) -> Self {
match *value {
0 => VelocityHint::Unspecified,
1..=15 => VelocityHint::Seldom,
16..=31 => VelocityHint::Episodic,
32..=63 => VelocityHint::Regular,
64..=127 => VelocityHint::Frequent,
128..=255 => VelocityHint::HighFrequency,
}
}
}

0 comments on commit f3d0639

Please sign in to comment.