From 8f7020c5a04d019e2fb376d95031be1fecfdedf6 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Tue, 15 Oct 2024 23:59:09 +0200 Subject: [PATCH] iface: add abiloity to select inputs for a given state to ContractIface --- Cargo.lock | 2 +- src/interface/calc.rs | 6 +++++- src/interface/contract.rs | 22 +++++++++++++++++++++- src/persistence/stash.rs | 19 +++++++++++++------ src/persistence/stock.rs | 2 ++ 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28d602ca..2cdf0702 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ version = 3 [[package]] name = "aluvm" version = "0.11.0-beta.9" -source = "git+https://github.com/AluVM/rust-aluvm?branch=develop#24bff9f61570ea26d14e86aa5e127937aa122440" +source = "git+https://github.com/AluVM/rust-aluvm?branch=develop#7adf61dbe4a3b39834bc3d665800024d66658e9c" dependencies = [ "amplify", "ascii-armor", diff --git a/src/interface/calc.rs b/src/interface/calc.rs index 50a6fd50..32043aa1 100644 --- a/src/interface/calc.rs +++ b/src/interface/calc.rs @@ -76,7 +76,7 @@ pub struct AllocatedState { pub insufficient: Option, } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct StateCalc { vm: aluvm::Vm, abi: StateAbi, @@ -189,4 +189,8 @@ impl StateCalc { .map_err(|err| StateCalcError::ChangeCalc(ty, err))?; self.fetch_state(ty, Reg16::Reg0) } + + pub fn is_sufficient_for(&self, ty: AssignmentType, state: &rgb::State) -> bool { + self.clone().calc_output(ty, state).is_ok() + } } diff --git a/src/interface/contract.rs b/src/interface/contract.rs index a5113fdf..f3fca6d8 100644 --- a/src/interface/contract.rs +++ b/src/interface/contract.rs @@ -22,13 +22,14 @@ use std::borrow::Borrow; use std::collections::{BTreeSet, HashMap, HashSet}; +use rgb::validation::Scripts; use rgb::{AssignmentType, ContractId, OpId, Schema, State, XOutputSeal, XWitnessId}; use strict_encoding::FieldName; use strict_types::{StrictVal, TypeSystem}; use crate::contract::{OutputAssignment, WitnessInfo}; use crate::info::ContractInfo; -use crate::interface::{AssignmentsFilter, IfaceImpl}; +use crate::interface::{AssignmentsFilter, IfaceImpl, StateCalc}; use crate::persistence::ContractStateRead; #[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)] @@ -115,6 +116,7 @@ pub struct ContractIface { pub schema: Schema, pub iface: IfaceImpl, pub types: TypeSystem, + pub scripts: Scripts, pub info: ContractInfo, } @@ -175,6 +177,24 @@ impl ContractIface { .filter(move |outp| outp.opout.ty == type_id)) } + pub fn assignments_fulfilling<'c, K: Ord + 'c>( + &'c self, + name: impl Into, + filter: impl AssignmentsFilter + 'c, + state: &'c State, + sorting: impl FnMut(&&OutputAssignment) -> K, + ) -> Result + 'c, ContractError> { + let mut selected = self.assignments_by_type(name, filter)?.collect::>(); + selected.sort_by_key(sorting); + let mut calc = StateCalc::new(self.scripts.clone(), self.iface.state_abi); + Ok(selected.into_iter().take_while(move |a| { + if calc.reg_input(a.opout.ty, &a.state).is_err() { + return false; + } + calc.is_sufficient_for(a.opout.ty, state) + })) + } + pub fn history( &self, filter_outpoints: impl AssignmentsFilter, diff --git a/src/persistence/stash.rs b/src/persistence/stash.rs index bd0dba10..a5822a7b 100644 --- a/src/persistence/stash.rs +++ b/src/persistence/stash.rs @@ -292,6 +292,18 @@ impl Stash

{ .map_err(StashError::ReadProvider) } + pub(super) fn scripts<'a>( + &self, + lib_ids: impl IntoIterator, + ) -> Result> { + let mut scripts = BTreeMap::new(); + for id in lib_ids { + let lib = self.provider.lib(id)?; + scripts.insert(id, lib.clone()); + } + Ok(Scripts::from_checked(scripts)) + } + pub(super) fn extract<'a>( &self, schema: &Schema, @@ -359,12 +371,7 @@ impl Stash

{ .ok_or(StashDataError::NoIfaceImpl(schema.schema_id(), iface.iface_id()))?; let (types, _) = self.extract(&schema_ifaces.schema, [iface])?; - let mut scripts = BTreeMap::new(); - for id in iimpl.state_abi.lib_ids() { - let lib = self.provider.lib(id)?; - scripts.insert(id, lib.clone()); - } - let scripts = Scripts::from_checked(scripts); + let scripts = self.scripts(iimpl.state_abi.lib_ids())?; let builder = if let Some(transition_name) = transition_name { TransitionBuilder::named_transition( diff --git a/src/persistence/stock.rs b/src/persistence/stock.rs index 1d8191a7..a142358e 100644 --- a/src/persistence/stock.rs +++ b/src/persistence/stock.rs @@ -579,6 +579,7 @@ impl Stock { state, schema: schema_ifaces.schema.clone(), iface: iimpl.clone(), + scripts: self.stash.scripts(iimpl.state_abi.lib_ids())?, types, info, })) @@ -604,6 +605,7 @@ impl Stock { state, schema: schema_ifaces.schema.clone(), iface: iimpl.clone(), + scripts: self.stash.scripts(iimpl.state_abi.lib_ids())?, types, info, })