Skip to content

Commit

Permalink
persistence: allow multiple witnesses per bundle
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Aug 1, 2024
1 parent 3263dfc commit b4d9880
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 34 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,4 @@ 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 = "contract-state2" }
rgb-core = { path = "../rgb-core" }
rgb-core = { git = "https://github.com/RGB-WG/rgb-core", branch = "contract-state2" }
12 changes: 2 additions & 10 deletions src/persistence/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,6 @@ pub enum IndexInconsistency {
/// outpoint {0} is not part of the contract {1}.
OutpointUnknown(XOutputSeal, ContractId),

/// index already contains information about bundle {bundle_id} which
/// specifies witness {present} instead of witness {expected}.
DistinctBundleWitness {
bundle_id: BundleId,
present: XWitnessId,
expected: XWitnessId,
},

/// index already contains information about bundle {bundle_id} which
/// specifies contract {present} instead of contract {expected}.
DistinctBundleContract {
Expand Down Expand Up @@ -336,7 +328,7 @@ impl<P: IndexProvider> Index<P> {
pub(super) fn bundle_info(
&self,
bundle_id: BundleId,
) -> Result<(XWitnessId, ContractId), IndexError<P>> {
) -> Result<(impl Iterator<Item = XWitnessId> + '_, ContractId), IndexError<P>> {
Ok(self.provider.bundle_info(bundle_id)?)
}
}
Expand Down Expand Up @@ -390,7 +382,7 @@ pub trait IndexReadProvider {
fn bundle_info(
&self,
bundle_id: BundleId,
) -> Result<(XWitnessId, ContractId), IndexReadError<Self::Error>>;
) -> Result<(impl Iterator<Item = XWitnessId>, ContractId), IndexReadError<Self::Error>>;
}

pub trait IndexWriteProvider: StoreTransaction<TransactionErr = Self::Error> {
Expand Down
39 changes: 18 additions & 21 deletions src/persistence/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,14 @@ impl StateReadProvider for MemState {
.collect();
Ok(MemContract { filter, unfiltered })
}

fn is_valid_witness(&self, witness_id: XWitnessId) -> Result<bool, Self::Error> {
let ord = self
.witnesses
.get(&witness_id)
.ok_or(StateInconsistency::AbsentValidWitness)?;
Ok(ord.is_valid())
}
}

impl StateWriteProvider for MemState {
Expand Down Expand Up @@ -1137,7 +1145,7 @@ pub struct MemIndex {

op_bundle_index: MediumOrdMap<OpId, BundleId>,
bundle_contract_index: MediumOrdMap<BundleId, ContractId>,
bundle_witness_index: MediumOrdMap<BundleId, XWitnessId>,
bundle_witness_index: MediumOrdMap<BundleId, TinyOrdSet<XWitnessId>>,
contract_index: TinyOrdMap<ContractId, ContractIndex>,
terminal_index: MediumOrdMap<XChain<SecretSeal>, Opout>,
}
Expand Down Expand Up @@ -1241,16 +1249,16 @@ impl IndexReadProvider for MemIndex {
fn bundle_info(
&self,
bundle_id: BundleId,
) -> Result<(XWitnessId, ContractId), IndexReadError<Self::Error>> {
let witness_id = self
) -> Result<(impl Iterator<Item = XWitnessId>, ContractId), IndexReadError<Self::Error>> {
let witness_ids = self
.bundle_witness_index
.get(&bundle_id)
.ok_or(IndexInconsistency::BundleWitnessUnknown(bundle_id))?;
let contract_id = self
.bundle_contract_index
.get(&bundle_id)
.ok_or(IndexInconsistency::BundleContractUnknown(bundle_id))?;
Ok((*witness_id, *contract_id))
Ok((witness_ids.iter().copied(), *contract_id))
}
}

Expand All @@ -1272,18 +1280,6 @@ impl IndexWriteProvider for MemIndex {
witness_id: XWitnessId,
contract_id: ContractId,
) -> Result<bool, IndexWriteError<Self::Error>> {
if let Some(alt) = self
.bundle_witness_index
.get(&bundle_id)
.filter(|alt| *alt != &witness_id)
{
return Err(IndexInconsistency::DistinctBundleWitness {
bundle_id,
present: *alt,
expected: witness_id,
}
.into());
}
if let Some(alt) = self
.bundle_contract_index
.get(&bundle_id)
Expand All @@ -1296,16 +1292,17 @@ impl IndexWriteProvider for MemIndex {
}
.into());
}
let present1 = self
let mut set = self
.bundle_witness_index
.insert(bundle_id, witness_id)?
.is_some();
.remove(&bundle_id)?
.unwrap_or_default();
set.push(witness_id)?;
self.bundle_witness_index.insert(bundle_id, set)?;
let present2 = self
.bundle_contract_index
.insert(bundle_id, contract_id)?
.is_some();
debug_assert_eq!(present1, present2);
Ok(!present1)
Ok(!present2)
}

fn register_operation(
Expand Down
23 changes: 23 additions & 0 deletions src/persistence/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::borrow::Borrow;
use std::collections::BTreeMap;
use std::error::Error;
use std::fmt::Debug;
Expand Down Expand Up @@ -64,6 +65,9 @@ pub enum StateError<P: StateProvider> {
pub enum StateInconsistency {
/// contract state {0} is not known.
UnknownContract(ContractId),
/// valid (non-archived) witness is absent in the list of witnesses for a
/// state transition bundle.
AbsentValidWitness,
}

#[derive(Clone, Eq, PartialEq, Debug, Hash)]
Expand Down Expand Up @@ -121,6 +125,23 @@ impl<P: StateProvider> State<P> {
.map_err(StateError::ReadProvider)
}

pub fn select_valid_witness(
&self,
witness_ids: impl IntoIterator<Item = impl Borrow<XWitnessId>>,
) -> Result<XWitnessId, StateError<P>> {
for witness_id in witness_ids {
let witness_id = *witness_id.borrow();
if self
.provider
.is_valid_witness(witness_id)
.map_err(StateError::ReadProvider)?
{
return Ok(witness_id);
}
}
Err(StateError::Inconsistency(StateInconsistency::AbsentValidWitness))
}

pub fn update_from_bundle<R: ResolveWitness>(
&mut self,
contract_id: ContractId,
Expand Down Expand Up @@ -244,6 +265,8 @@ pub trait StateReadProvider {
&self,
contract_id: ContractId,
) -> Result<Self::ContractRead<'_>, Self::Error>;

fn is_valid_witness(&self, witness_id: XWitnessId) -> Result<bool, Self::Error>;
}

pub trait StateWriteProvider: StoreTransaction<TransactionErr = Self::Error> {
Expand Down
3 changes: 2 additions & 1 deletion src/persistence/stock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1250,9 +1250,10 @@ impl<S: StashProvider, H: StateProvider, P: IndexProvider> Stock<S, H, P> {
}

fn bundled_witness(&self, bundle_id: BundleId) -> Result<BundledWitness, StockError<S, H, P>> {
let (witness_id, contract_id) = self.index.bundle_info(bundle_id)?;
let (witness_ids, contract_id) = self.index.bundle_info(bundle_id)?;

let bundle = self.stash.bundle(bundle_id)?.clone();
let witness_id = self.state.select_valid_witness(witness_ids)?;
let witness = self.stash.witness(witness_id)?;
let anchor = witness.anchors.clone();
let (tapret, opret) = match anchor {
Expand Down

0 comments on commit b4d9880

Please sign in to comment.