Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support spending mixed opret/tapret outputs #252

Merged
merged 5 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/containers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ pub use file::{FileContent, LoadError, UniversalFile};
pub use indexed::IndexedConsignment;
pub use kit::{Kit, KitId, ValidKit};
pub use partials::{
Batch, BundleDichotomy, CloseMethodSet, Fascia, TransitionInfo, TransitionInfoError,
Batch, BundleDichotomy, CloseMethodSet, Dichotomy, Fascia, TransitionDichotomy, TransitionInfo,
TransitionInfoError,
};
pub use seal::{BuilderSeal, VoutSeal};
pub use suppl::{
Expand Down
72 changes: 50 additions & 22 deletions src/containers/partials.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ use std::cmp::Ordering;
use std::collections::{BTreeMap, BTreeSet};
use std::hash::{Hash, Hasher};
use std::ops::{BitOr, BitOrAssign};
use std::vec;
use std::{iter, vec};

use amplify::confinement::{Confined, U24};
use bp::seals::txout::CloseMethod;
use rgb::{
ContractId, OpId, Operation, Transition, TransitionBundle, TxoSeal, XOutpoint, XOutputSeal,
XWitnessId,
};
use strict_encoding::{StrictDeserialize, StrictDumb, StrictSerialize};
use strict_encoding::{StrictDecode, StrictDeserialize, StrictDumb, StrictEncode, StrictSerialize};

use crate::containers::{AnchorSet, XPubWitness};
use crate::LIB_NAME_RGB_STD;
Expand Down Expand Up @@ -194,55 +194,85 @@ pub enum TransitionInfoError {
serde(crate = "serde_crate", rename_all = "camelCase")
)]
pub struct Batch {
pub main: TransitionInfo,
pub blanks: Confined<Vec<TransitionInfo>, 0, { U24 - 1 }>,
pub main: TransitionDichotomy,
pub blanks: Confined<Vec<TransitionDichotomy>, 0, { U24 - 1 }>,
}

impl StrictSerialize for Batch {}
impl StrictDeserialize for Batch {}

impl IntoIterator for Batch {
type Item = TransitionInfo;
type IntoIter = vec::IntoIter<TransitionInfo>;
type IntoIter = iter::FlatMap<
vec::IntoIter<Dichotomy<TransitionInfo>>,
vec::IntoIter<TransitionInfo>,
fn(Dichotomy<TransitionInfo>) -> <Dichotomy<TransitionInfo> as IntoIterator>::IntoIter,
>;

fn into_iter(self) -> Self::IntoIter {
let mut vec = self.blanks.into_inner();
vec.push(self.main);
vec.into_iter()
vec.into_iter().flat_map(TransitionDichotomy::into_iter)
}
}

impl Batch {
pub fn close_method_set(&self) -> CloseMethodSet {
let mut methods = CloseMethodSet::from(self.main.method);
self.blanks.iter().for_each(|i| methods |= i.method);
let mut methods = CloseMethodSet::from(self.main.first.method);
if let Some(info) = &self.main.second {
methods |= info.method;
}
self.blanks.iter().for_each(|i| methods |= i.first.method);
self.blanks
.iter()
.filter_map(|i| i.second.as_ref())
.for_each(|i| methods |= i.method);
methods
}

pub fn set_priority(&mut self, priority: u8) {
self.main.transition.nonce = priority;
for info in &mut self.blanks {
self.main.first.transition.nonce = priority;
if let Some(info) = &mut self.main.second {
info.transition.nonce = priority;
}
for info in &mut self.blanks {
info.first.transition.nonce = priority;
if let Some(info) = &mut info.second {
info.transition.nonce = priority;
}
}
}
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub type BundleDichotomy = Dichotomy<TransitionBundle>;
pub type TransitionDichotomy = Dichotomy<TransitionInfo>;

#[derive(Clone, PartialEq, Eq, Hash, Debug)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB_STD)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate", rename_all = "camelCase")
)]
pub struct BundleDichotomy {
pub first: TransitionBundle,
pub second: Option<TransitionBundle>,
pub struct Dichotomy<T: StrictDumb + StrictEncode + StrictDecode> {
pub first: T,
pub second: Option<T>,
}

impl IntoIterator for BundleDichotomy {
type Item = TransitionBundle;
type IntoIter = vec::IntoIter<TransitionBundle>;
impl<T: StrictDumb + StrictEncode + StrictDecode> FromIterator<T> for Dichotomy<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut iter = iter.into_iter();
let first = iter.next().expect("iterator must have at least one item");
let second = iter.next();
assert!(iter.next().is_none(), "iterator must have at most two items");
Self { first, second }
}
}

impl<T: StrictDumb + StrictEncode + StrictDecode> IntoIterator for Dichotomy<T> {
type Item = T;
type IntoIter = vec::IntoIter<T>;

fn into_iter(self) -> Self::IntoIter {
let mut vec = Vec::with_capacity(2);
Expand All @@ -254,12 +284,10 @@ impl IntoIterator for BundleDichotomy {
}
}

impl BundleDichotomy {
pub fn with(first: TransitionBundle, second: Option<TransitionBundle>) -> Self {
Self { first, second }
}
impl<T: StrictDumb + StrictEncode + StrictDecode> Dichotomy<T> {
pub fn with(first: T, second: Option<T>) -> Self { Self { first, second } }

pub fn iter(&self) -> vec::IntoIter<&TransitionBundle> {
pub fn iter(&self) -> vec::IntoIter<&T> {
let mut vec = Vec::with_capacity(2);
vec.push(&self.first);
if let Some(ref s) = self.second {
Expand Down
2 changes: 2 additions & 0 deletions src/interface/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,8 @@ impl TransitionBuilder {
Ok(self)
}

pub fn has_inputs(&self) -> bool { !self.inputs.is_empty() }

pub fn complete_transition(self) -> Result<Transition, BuilderError> {
let (_, _, _, global, assignments, _, _) = self.builder.complete(Some(&self.inputs));

Expand Down
Loading
Loading