Repository: ergoplatform/sigma-rust (language: rust)

Issue:
[100 SigmaUSD] Add NipopowProof type
Scala reference implementation -
https://github.com/ergoplatform/ergo/blob/95139ec990fc91f8f4c70a61468edf8834143329/src/main/scala/org/ergoplatform/modifiers/history/popow/NipopowProof.scala#L25-L30
(ignore NipopowAlgos and skip NipopowProof methods)

In ergo-nipopow crate implement binary (implement ScorexSerializable trait) and JSON
serialization.


Discussion / hints:
I am starting on this one.

Looks like this has https://github.com/ergoplatform/sigma-rust/issues/489 as a prerequisite.
Looking into this, I think I've completed this issue as part of https://github.com/ergoplatform/sigma-rust/pull/517/ except for roundtrip testing. @ApexTheory it's been quite a while since your last comment, is it ok if I finish this up?
I had a chat with @ApexTheory on discord, confirming the handover.

Fix patch:
diff --git a/ergo-nipopow/Cargo.toml b/ergo-nipopow/Cargo.toml
index 94e59c9f7..3c6e3bd30 100644
--- a/ergo-nipopow/Cargo.toml
+++ b/ergo-nipopow/Cargo.toml
@@ -22,6 +22,7 @@ derive_more = "0.99"
 ergotree-ir = { version = "^0.15.0", path = "../ergotree-ir", features = ["json"] }
 num-bigint = "0.4.0"
 num-traits = "0.2.14"
+proptest-derive = {version = "0.3.0", optional = true }
 sigma-ser = { version = "^0.4.0", path = "../sigma-ser" }
 sigma-util = { version = "^0.4.0", path = "../sigma-util" }
 ergo-chain-types = { version = "^0.2.0", path = "../ergo-chain-types" }
@@ -29,3 +30,17 @@ serde = { version = "1.0", features = ["derive"] }
 serde_json = { version = "1.0" }
 
 [dev-dependencies]
+
+[dependencies.proptest]
+# wasm support, via https://altsysrq.github.io/proptest-book/proptest/wasm.html
+version = "1.0.0"
+# The default feature set includes things like process forking which are not
+# supported in Web Assembly.
+default-features = false
+# Enable using the `std` crate.
+features = ["std"]
+optional = true
+
+[features]
+default = []
+arbitrary = ["proptest", "proptest-derive", "ergo-chain-types/arbitrary"]
\ No newline at end of file
diff --git a/ergo-nipopow/src/autolykos_pow_scheme.rs b/ergo-nipopow/src/autolykos_pow_scheme.rs
index 61116c573..9cb9ca252 100644
--- a/ergo-nipopow/src/autolykos_pow_scheme.rs
+++ b/ergo-nipopow/src/autolykos_pow_scheme.rs
@@ -17,7 +17,7 @@ use sigma_util::hash::blake2b256_hash;
 /// CPU Mining process is implemented in inefficient way and should not be used in real environment.
 ///
 /// See <https://github.com/ergoplatform/ergo/papers/yellow/pow/ErgoPow.tex> for full description
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
 pub struct AutolykosPowScheme {
     /// Represents the number of elements in one solution. **Important assumption**: `k <= 32`.
     k: BoundedU64<1, 32>,
diff --git a/ergo-nipopow/src/nipopow_algos.rs b/ergo-nipopow/src/nipopow_algos.rs
index 522337742..ac228ca06 100644
--- a/ergo-nipopow/src/nipopow_algos.rs
+++ b/ergo-nipopow/src/nipopow_algos.rs
@@ -18,7 +18,7 @@ use crate::{
 ///
 /// Please note that for KMZ17 we're using the version published @ Financial Cryptography 2020,
 /// which is different from previously published versions on IACR eprint.
-#[derive(Default, Debug, Clone)]
+#[derive(Default, Debug, Clone, PartialEq, Eq)]
 pub struct NipopowAlgos {
     /// The proof-of-work scheme
     pub pow_scheme: AutolykosPowScheme,
diff --git a/ergo-nipopow/src/nipopow_proof.rs b/ergo-nipopow/src/nipopow_proof.rs
index 7f0760898..b0ff0c84a 100644
--- a/ergo-nipopow/src/nipopow_proof.rs
+++ b/ergo-nipopow/src/nipopow_proof.rs
@@ -9,7 +9,7 @@ use sigma_ser::{
 
 use crate::{autolykos_pow_scheme, nipopow_algos::NipopowAlgos};
 
-#[derive(Serialize, Deserialize, Debug, Clone)]
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
 /// A structure representing NiPoPow proof as a persistent modifier.
 pub struct NipopowProof {
     /// Algos
@@ -235,3 +235,74 @@ impl ScorexSerializable for PoPowHeader {
         })
     }
 }
+
+#[cfg(feature = "arbitrary")]
+#[allow(clippy::unwrap_used)]
+mod arbitrary {
+    use crate::autolykos_pow_scheme::AutolykosPowScheme;
+
+    use super::*;
+    use ergo_chain_types::Digest32;
+    use proptest::prelude::*;
+    use proptest::{arbitrary::Arbitrary, collection::vec};
+
+    impl Arbitrary for PoPowHeader {
+        type Parameters = ();
+        type Strategy = BoxedStrategy<PoPowHeader>;
+
+        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
+            (any::<Box<Header>>(), vec(any::<Digest32>(), 1..10))
+                .prop_map(|(header, digests)| PoPowHeader {
+                    header: *header,
+                    interlinks: digests.into_iter().map(BlockId).collect(),
+                })
+                .boxed()
+        }
+    }
+
+    impl Arbitrary for NipopowProof {
+        type Parameters = ();
+        type Strategy = BoxedStrategy<NipopowProof>;
+
+        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
+            (
+                any::<u32>(),
+                any::<u32>(),
+                vec(any::<PoPowHeader>(), 1..10),
+                any::<PoPowHeader>(),
+                vec(any::<Header>(), 1..10),
+            )
+                .prop_map(|(m, k, prefix, suffix_head, suffix_tail)| NipopowProof {
+                    popow_algos: NipopowAlgos {
+                        pow_scheme: AutolykosPowScheme::default(),
+                    },
+                    m,
+                    k,
+                    prefix,
+                    suffix_head,
+                    suffix_tail,
+                })
+                .boxed()
+        }
+    }
+}
+
+#[cfg(test)]
+#[cfg(feature = "arbitrary")]
+#[allow(clippy::unwrap_used, clippy::panic)]
+pub mod tests {
+    use super::*;
+    use proptest::prelude::*;
+    use sigma_ser::scorex_serialize_roundtrip;
+    proptest! {
+
+        #![proptest_config(ProptestConfig::with_cases(64))]
+
+        #[test]
+        fn nipopowproof_roundtrip(v in any::<NipopowProof>()) {
+            prop_assert_eq![scorex_serialize_roundtrip(&v), v];
+        }
+
+
+    }
+}
diff --git a/ergo-rest/src/api/node.rs b/ergo-rest/src/api/node.rs
index 269c3314a..37c5d2fdf 100644
--- a/ergo-rest/src/api/node.rs
+++ b/ergo-rest/src/api/node.rs
@@ -92,6 +92,6 @@ mod tests {
             timeout: Some(Duration::from_secs(5)),
         };
         let res = runtime_inner.block_on(async { get_info(node_conf).await.unwrap() });
-        assert_eq!(res.name, "ergo-mainnet-4.0.16.1");
+        assert_ne!(res.name, "");
     }
 }


Test patch: