Skip to content

Commit

Permalink
persistence: use new ContractStateEvolve and validator APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Aug 1, 2024
1 parent 9ad9495 commit 3bc0d76
Show file tree
Hide file tree
Showing 10 changed files with 280 additions and 208 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,5 @@ features = ["all"]
[patch.crates-io]
bp-consensus = { git = "https://github.com/BP-WG/bp-core", branch = "master" }
bp-invoice = { git = "https://github.com/BP-WG/bp-std.git", branch = "master" }
rgb-core = { git = "https://github.com/RGB-WG/rgb-core", branch = "movearound" }
rgb-core = { git = "https://github.com/RGB-WG/rgb-core", branch = "contract-state2" }
#rgb-core = { path = "../rgb-core" }
4 changes: 2 additions & 2 deletions src/containers/consignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ use super::{
ASCII_ARMOR_SCHEMA, ASCII_ARMOR_TERMINAL, ASCII_ARMOR_VERSION,
};
use crate::interface::{Iface, IfaceImpl};
use crate::persistence::MemContract;
use crate::persistence::{MemContract, MemContractState};
use crate::resolvers::ConsignmentResolver;
use crate::{BundleExt, SecretSeal, LIB_NAME_RGB_STD};

Expand Down Expand Up @@ -349,7 +349,7 @@ impl<const TRANSFER: bool> Consignment<TRANSFER> {
consignment: &index,
fallback: resolver,
};
let mut status = Validator::<MemContract, _, _>::validate(
let mut status = Validator::<MemContract<MemContractState>, _, _>::validate(
&index,
&resolver,
testnet,
Expand Down
3 changes: 1 addition & 2 deletions src/containers/indexed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
use std::collections::{BTreeMap, BTreeSet};
use std::ops::Deref;

use rgb::validation::{ConsignmentApi, EAnchor, Scripts};
use rgb::vm::OpRef;
use rgb::validation::{ConsignmentApi, EAnchor, OpRef, Scripts};
use rgb::{
BundleId, Extension, Genesis, OpId, Operation, Schema, Transition, TransitionBundle, XWitnessId,
};
Expand Down
107 changes: 90 additions & 17 deletions src/persistence/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::convert::Infallible;
use std::fmt::{Debug, Formatter};
use std::num::NonZeroU32;
#[cfg(feature = "fs")]
use std::path::PathBuf;
Expand All @@ -38,8 +39,8 @@ use bp::dbc::tapret::TapretCommitment;
use commit_verify::{CommitId, Conceal};
use rgb::validation::ResolveWitness;
use rgb::vm::{
ContractStateAccess, GlobalContractState, GlobalOrd, GlobalStateIter, TxOrd,
UnknownGlobalStateType, WitnessOrd,
AnchoredOpRef, ContractStateAccess, ContractStateEvolve, GlobalContractState, GlobalOrd,
GlobalStateIter, TxOrd, UnknownGlobalStateType, WitnessOrd,
};
use rgb::{
Assign, AssignmentType, Assignments, AssignmentsRef, AttachId, AttachState, BundleId,
Expand Down Expand Up @@ -445,7 +446,7 @@ pub struct MemState {
filename: PathBuf,

witnesses: LargeOrdMap<XWitnessId, TxOrd>,
contracts: TinyOrdMap<ContractId, MemContract>,
contracts: TinyOrdMap<ContractId, MemContractState>,
}

impl StrictSerialize for MemState {}
Expand Down Expand Up @@ -473,7 +474,7 @@ impl StoreTransaction for MemState {
impl StateProvider for MemState {}

impl StateReadProvider for MemState {
type ContractRead<'a> = MemContractFiltered<'a>;
type ContractRead<'a> = MemContract<&'a MemContractState>;
type Error = StateInconsistency;

fn contract_state(
Expand Down Expand Up @@ -501,7 +502,7 @@ impl StateReadProvider for MemState {
})
.map(|(id, ord)| (*id, *ord))
.collect();
Ok(MemContractFiltered { filter, unfiltered })
Ok(MemContract { filter, unfiltered })
}
}

Expand All @@ -525,7 +526,7 @@ impl StateWriteProvider for MemState {
}
} else {
self.contracts
.insert(contract_id, MemContract::new(schema, contract_id))?;
.insert(contract_id, MemContractState::new(schema, contract_id))?;
self.contracts.get_mut(&contract_id).expect("just inserted")
};
let mut writer = MemContractWriter {
Expand Down Expand Up @@ -621,7 +622,7 @@ impl MemGlobalState {
/// NB: MemContract provides an in-memory contract state used during contract
/// validation. It does not support filtering by witness transaction validity
/// and thus must not be used in any other cases in its explicit form. Pls see
/// [`MemContractFiltered`] instead.
/// [`MemContract`] instead.
#[derive(Getters, Clone, Eq, PartialEq, Debug)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB_STORAGE)]
Expand All @@ -630,7 +631,7 @@ impl MemGlobalState {
derive(Serialize, Deserialize),
serde(crate = "serde_crate", rename_all = "camelCase")
)]
pub struct MemContract {
pub struct MemContractState {
#[getter(as_copy)]
schema_id: SchemaId,
#[getter(as_copy)]
Expand All @@ -643,15 +644,15 @@ pub struct MemContract {
attach: LargeOrdSet<OutputAssignment<RevealedAttach>>,
}

impl MemContract {
impl MemContractState {
pub fn new(schema: &Schema, contract_id: ContractId) -> Self {
let global = TinyOrdMap::from_iter_unsafe(
schema
.global_types
.iter()
.map(|(ty, glob)| (*ty, MemGlobalState::new(glob.max_items))),
);
MemContract {
MemContractState {
schema_id: schema.schema_id(),
contract_id,
global,
Expand Down Expand Up @@ -771,12 +772,18 @@ impl MemContract {
}
}

pub struct MemContractFiltered<'mem> {
pub struct MemContract<M: Borrow<MemContractState>> {
filter: HashMap<XWitnessId, TxOrd>,
unfiltered: &'mem MemContract,
unfiltered: M,
}

impl<'mem> ContractStateAccess for MemContractFiltered<'mem> {
impl<M: Borrow<MemContractState>> Debug for MemContract<M> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("MemContractFiltered { .. }")
}
}

impl<M: Borrow<MemContractState>> ContractStateAccess for MemContract<M> {
fn global(
&self,
ty: GlobalStateType,
Expand Down Expand Up @@ -833,6 +840,7 @@ impl<'mem> ContractStateAccess for MemContractFiltered<'mem> {

let state = self
.unfiltered
.borrow()
.global
.get(&ty)
.ok_or(UnknownGlobalStateType(ty))?;
Expand Down Expand Up @@ -866,6 +874,7 @@ impl<'mem> ContractStateAccess for MemContractFiltered<'mem> {

fn rights(&self, outpoint: XOutpoint, ty: AssignmentType) -> u32 {
self.unfiltered
.borrow()
.rights
.iter()
.filter(|assignment| {
Expand All @@ -881,6 +890,7 @@ impl<'mem> ContractStateAccess for MemContractFiltered<'mem> {
ty: AssignmentType,
) -> impl DoubleEndedIterator<Item = FungibleState> {
self.unfiltered
.borrow()
.fungibles
.iter()
.filter(move |assignment| {
Expand All @@ -896,6 +906,7 @@ impl<'mem> ContractStateAccess for MemContractFiltered<'mem> {
ty: AssignmentType,
) -> impl DoubleEndedIterator<Item = impl Borrow<DataState>> {
self.unfiltered
.borrow()
.data
.iter()
.filter(move |assignment| {
Expand All @@ -911,6 +922,7 @@ impl<'mem> ContractStateAccess for MemContractFiltered<'mem> {
ty: AssignmentType,
) -> impl DoubleEndedIterator<Item = impl Borrow<AttachState>> {
self.unfiltered
.borrow()
.attach
.iter()
.filter(move |assignment| {
Expand All @@ -921,16 +933,74 @@ impl<'mem> ContractStateAccess for MemContractFiltered<'mem> {
}
}

impl<'mem> ContractStateRead for MemContractFiltered<'mem> {
impl ContractStateEvolve for MemContract<MemContractState> {
type Context<'ctx> = (&'ctx Schema, ContractId);

fn init(context: Self::Context<'_>) -> Self {
Self {
filter: empty!(),
unfiltered: MemContractState::new(context.0, context.1),
}
}

fn evolve_state(&mut self, op: AnchoredOpRef) -> Result<(), confinement::Error> {
fn ordering(filter: &HashMap<XWitnessId, TxOrd>, witness_id: XWitnessId) -> WitnessOrd {
let ord = filter.get(&witness_id).expect("unknown witness id");
WitnessOrd {
pub_ord: *ord,
witness_id,
}
}
(move || -> Result<(), SerializeError> {
fn writer(me: &mut MemContract<MemContractState>) -> MemContractWriter {
MemContractWriter {
writer: Box::new(|ord: WitnessOrd| -> Result<(), SerializeError> {
// NB: We do not check the existence of the witness since we have a newer
// version anyway and even if it is known we have to replace it
me.filter.insert(ord.witness_id, ord.pub_ord);
Ok(())
}),
contract: &mut me.unfiltered,
}
}
match op {
AnchoredOpRef::Genesis(genesis) => {
let mut writer = writer(self);
writer.add_genesis(genesis)
}
AnchoredOpRef::Transition(transition, witness_id) => {
let ord = ordering(&self.filter, witness_id);
let mut writer = writer(self);
writer.add_transition(transition, ord)
}
AnchoredOpRef::Extension(extension, witness_id) => {
let ord = ordering(&self.filter, witness_id);
let mut writer = writer(self);
writer.add_extension(extension, ord)
}
}
})()
.map_err(|err| match err {
SerializeError::Io(_) => {
unreachable!("I/O errors are not possible for memory structures")
}
SerializeError::Confinement(e) => e,
})?;
Ok(())
}
}

impl<M: Borrow<MemContractState>> ContractStateRead for MemContract<M> {
#[inline]
fn contract_id(&self) -> ContractId { self.unfiltered.contract_id }
fn contract_id(&self) -> ContractId { self.unfiltered.borrow().contract_id }

#[inline]
fn schema_id(&self) -> SchemaId { self.unfiltered.schema_id }
fn schema_id(&self) -> SchemaId { self.unfiltered.borrow().schema_id }

#[inline]
fn rights_all(&self) -> impl Iterator<Item = &OutputAssignment<VoidState>> {
self.unfiltered
.borrow()
.rights
.iter()
.filter(|assignment| assignment.check_witness(&self.filter))
Expand All @@ -939,6 +1009,7 @@ impl<'mem> ContractStateRead for MemContractFiltered<'mem> {
#[inline]
fn fungible_all(&self) -> impl Iterator<Item = &OutputAssignment<RevealedValue>> {
self.unfiltered
.borrow()
.fungibles
.iter()
.filter(|assignment| assignment.check_witness(&self.filter))
Expand All @@ -947,6 +1018,7 @@ impl<'mem> ContractStateRead for MemContractFiltered<'mem> {
#[inline]
fn data_all(&self) -> impl Iterator<Item = &OutputAssignment<RevealedData>> {
self.unfiltered
.borrow()
.data
.iter()
.filter(|assignment| assignment.check_witness(&self.filter))
Expand All @@ -955,6 +1027,7 @@ impl<'mem> ContractStateRead for MemContractFiltered<'mem> {
#[inline]
fn attach_all(&self) -> impl Iterator<Item = &OutputAssignment<RevealedAttach>> {
self.unfiltered
.borrow()
.attach
.iter()
.filter(|assignment| assignment.check_witness(&self.filter))
Expand All @@ -963,7 +1036,7 @@ impl<'mem> ContractStateRead for MemContractFiltered<'mem> {

pub struct MemContractWriter<'mem> {
writer: Box<dyn FnMut(WitnessOrd) -> Result<(), SerializeError> + 'mem>,
contract: &'mem mut MemContract,
contract: &'mem mut MemContractState,
}

impl<'mem> ContractStateWrite for MemContractWriter<'mem> {
Expand Down
3 changes: 2 additions & 1 deletion src/persistence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ pub use index::{
Index, IndexError, IndexInconsistency, IndexProvider, IndexReadError, IndexReadProvider,
IndexWriteError, IndexWriteProvider,
};
pub use memory::{MemContract, MemGlobalState, MemIndex, MemStash, MemState};
pub(crate) use memory::MemContract;
pub use memory::{MemContractState, MemGlobalState, MemIndex, MemStash, MemState};
pub use stash::{
ProviderError as StashProviderError, SchemaIfaces, Stash, StashDataError, StashError,
StashInconsistency, StashProvider, StashReadProvider, StashWriteProvider,
Expand Down
2 changes: 1 addition & 1 deletion src/stl/stl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use crate::LIB_NAME_RGB_STD;
/// Strict types id for the library providing standard data types which may be
/// used in RGB smart contracts.
pub const LIB_ID_RGB_STORAGE: &str =
"stl:DKVsldZ8-zYwnjtp-igdl80j-eifV0Ef-asKEvF6-JyZP3to#song-wave-story";
"stl:aHl1Tsu8-RxChWD4-DXqrqOO-qFlJXsK-0uWYfDv-H5BgmxE#plastic-shelter-podium";

/// Strict types id for the library providing standard data types which may be
/// used in RGB smart contracts.
Expand Down
Loading

0 comments on commit 3bc0d76

Please sign in to comment.