Repository: LNP-BP/client_side_validation (language: rust)

Issue:
add support for deterministic entropy
Same as https://github.com/RGB-WG/rgb-wallet/issues/99, but [here](https://github.com/RGB-Tools/client_side_validation/compare/v0.10.4...static_0.10) you can see the method we had to duplicate (`try_commit` -> `try_commit_static`, needed by `dbc_conclude_static` in rgb-wallet).


Discussion / hints:

Fix patch:
diff --git a/commit_verify/src/mpc/atoms.rs b/commit_verify/src/mpc/atoms.rs
index d8291fe1..fb0e9a91 100644
--- a/commit_verify/src/mpc/atoms.rs
+++ b/commit_verify/src/mpc/atoms.rs
@@ -152,7 +152,6 @@ impl Commitment {
     pub fn from_slice(slice: &[u8]) -> Option<Self> { Bytes32::from_slice(slice).map(Self) }
 }
 
-// TODO: Either this type or [`MerkleTree`] should remain
 /// Structured source multi-message data for commitment creation
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 pub struct MultiSource {
@@ -160,13 +159,26 @@ pub struct MultiSource {
     pub min_depth: u5,
     /// Map of the messages by their respective protocol ids
     pub messages: MessageMap,
+    pub static_entropy: Option<u64>,
 }
 
 impl Default for MultiSource {
+    #[inline]
     fn default() -> Self {
         MultiSource {
             min_depth: u5::with(3),
             messages: Default::default(),
+            static_entropy: None,
+        }
+    }
+}
+
+impl MultiSource {
+    #[inline]
+    pub fn with_static_entropy(static_entropy: u64) -> Self {
+        MultiSource {
+            static_entropy: Some(static_entropy),
+            ..default!()
         }
     }
 }
diff --git a/commit_verify/src/mpc/tree.rs b/commit_verify/src/mpc/tree.rs
index a14d7b21..f5d5d2ff 100644
--- a/commit_verify/src/mpc/tree.rs
+++ b/commit_verify/src/mpc/tree.rs
@@ -23,7 +23,6 @@ use amplify::confinement::{MediumOrdMap, SmallVec};
 use amplify::num::{u256, u5};
 use amplify::Wrapper;
 
-#[cfg(feature = "rand")]
 pub use self::commit::Error;
 use crate::merkle::MerkleNode;
 use crate::mpc::atoms::Leaf;
@@ -85,10 +84,10 @@ impl Conceal for MerkleTree {
     fn conceal(&self) -> Self::Concealed { self.root() }
 }
 
-#[cfg(feature = "rand")]
 mod commit {
+    use std::collections::BTreeMap;
+
     use amplify::confinement::Confined;
-    use rand::{thread_rng, RngCore};
 
     use super::*;
     use crate::mpc::MultiSource;
@@ -112,11 +111,16 @@ mod commit {
         CantFitInMaxSlots(usize),
     }
 
+    /// # Panics
+    ///
+    /// Panics if the crate is compiled without `rand` feature enabled and the
+    /// MultiSource doesn't contain a static entropy.
     impl TryCommitVerify<MultiSource, UntaggedProtocol> for MerkleTree {
         type Error = Error;
 
         fn try_commit(source: &MultiSource) -> Result<Self, Error> {
-            use std::collections::BTreeMap;
+            #[cfg(feature = "rand")]
+            use rand::{thread_rng, RngCore};
 
             let msg_count = source.messages.len();
 
@@ -127,7 +131,15 @@ mod commit {
                 return Err(Error::TooManyMessages(msg_count));
             }
 
-            let entropy = thread_rng().next_u64();
+            #[cfg(feature = "rand")]
+            let entropy = source
+                .static_entropy
+                .unwrap_or_else(|| thread_rng().next_u64());
+            #[cfg(not(feature = "rand"))]
+            let entropy = source.static_entropy.expect(
+                "use must use `rand` feature for crate commit_verify if you do not provide with a \
+                 static entropy information in `MultiSource`",
+            );
 
             let mut map = BTreeMap::<u32, (ProtocolId, Message)>::new();
 
@@ -226,6 +238,7 @@ pub(crate) mod test_helpers {
         let src = MultiSource {
             min_depth: u5::ZERO,
             messages: Confined::try_from_iter(msgs.iter().map(|(a, b)| (*a, *b))).unwrap(),
+            static_entropy: None,
         };
         MerkleTree::try_commit(&src).unwrap()
     }


Test patch: