From 32a44a25039eb0c046599b54661cc1e1d939cae9 Mon Sep 17 00:00:00 2001
From: hinto-janai <hinto.janai@protonmail.com>
Date: Thu, 25 Apr 2024 14:58:45 -0400
Subject: [PATCH 1/2] test-utils: compare data against RPC (#115)

* cargo: add `pretty_assertions`

* test-utils: add tests to compare data against RPC data, and fix

* small fixes

* database: fix `cumulative_generated_coins` from test data

block had wrong data which offset all of the asserts
---
 Cargo.lock                     |   2 +
 Cargo.toml                     |   1 +
 database/Cargo.toml            |   2 +-
 database/src/ops/blockchain.rs |   6 +-
 test-utils/Cargo.toml          |   2 +
 test-utils/src/data/free.rs    | 101 ++++++++++++++++++++++++++++-----
 6 files changed, 96 insertions(+), 18 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 56bfa311..59f14afa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -650,6 +650,7 @@ dependencies = [
  "borsh",
  "bytes",
  "bzip2",
+ "cuprate-helper",
  "cuprate-types",
  "futures",
  "hex",
@@ -657,6 +658,7 @@ dependencies = [
  "monero-p2p",
  "monero-serai",
  "monero-wire",
+ "pretty_assertions",
  "reqwest",
  "serde",
  "serde_json",
diff --git a/Cargo.toml b/Cargo.toml
index cf51f5fb..ca695ac5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -76,6 +76,7 @@ tracing               = { version = "0.1.40", default-features = false }
 ## workspace.dev-dependencies
 tempfile              = { version = "3" }
 reqwest               = { version = "0.11.24" }
+pretty_assertions     = { version = "1.4.0" }
 proptest              = { version = "1" }
 proptest-derive       = { version = "0.4.0" }
 
diff --git a/database/Cargo.toml b/database/Cargo.toml
index f73dcb44..d925b51a 100644
--- a/database/Cargo.toml
+++ b/database/Cargo.toml
@@ -53,6 +53,6 @@ cuprate-helper = { path = "../helper", features = ["thread"] }
 cuprate-test-utils = { path = "../test-utils" }
 page_size = { version = "0.6.0" }
 tempfile = { version = "3.10.0" }
-pretty_assertions = { version = "1.4.0" }
+pretty_assertions = { workspace = true }
 hex = { workspace = true }
 hex-literal = { workspace = true }
\ No newline at end of file
diff --git a/database/src/ops/blockchain.rs b/database/src/ops/blockchain.rs
index b94cea05..784ec506 100644
--- a/database/src/ops/blockchain.rs
+++ b/database/src/ops/blockchain.rs
@@ -156,15 +156,15 @@ mod test {
             );
             assert_eq!(
                 cumulative_generated_coins(&0, tables.block_infos()).unwrap(),
-                13_138_270_467_918,
+                14_535_350_982_449,
             );
             assert_eq!(
                 cumulative_generated_coins(&1, tables.block_infos()).unwrap(),
-                16_542_044_490_081,
+                17_939_125_004_612,
             );
             assert_eq!(
                 cumulative_generated_coins(&2, tables.block_infos()).unwrap(),
-                17_142_044_490_081,
+                18_539_125_004_612,
             );
             assert!(matches!(
                 cumulative_generated_coins(&3, tables.block_infos()),
diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml
index 25be6356..c9e468bb 100644
--- a/test-utils/Cargo.toml
+++ b/test-utils/Cargo.toml
@@ -7,6 +7,7 @@ authors = ["Boog900", "hinto-janai"]
 
 [dependencies]
 cuprate-types = { path = "../types" }
+cuprate-helper = { path = "../helper", features = ["map"] }
 monero-wire = { path = "../net/monero-wire" }
 monero-p2p = { path = "../p2p/monero-p2p", features = ["borsh"] }
 
@@ -34,3 +35,4 @@ zip = "0.6"
 
 [dev-dependencies]
 hex = { workspace = true }
+pretty_assertions = { workspace = true }
\ No newline at end of file
diff --git a/test-utils/src/data/free.rs b/test-utils/src/data/free.rs
index a08c6fec..c2c2c82b 100644
--- a/test-utils/src/data/free.rs
+++ b/test-utils/src/data/free.rs
@@ -11,6 +11,7 @@ use std::sync::{Arc, OnceLock};
 use hex_literal::hex;
 use monero_serai::{block::Block, transaction::Transaction};
 
+use cuprate_helper::map::combine_low_high_bits_to_u128;
 use cuprate_types::{TransactionVerificationData, VerifiedBlockInformation};
 
 use crate::data::constants::{
@@ -34,7 +35,8 @@ struct VerifiedBlockMap {
     generated_coins: u64,
     weight: usize,
     long_term_weight: usize,
-    cumulative_difficulty: u128,
+    cumulative_difficulty_low: u64,
+    cumulative_difficulty_high: u64,
     // Vec of `tx_blob`'s, i.e. the data in `/test-utils/src/data/tx/`.
     // This should the actual `tx_blob`'s of the transactions within this block.
     txs: &'static [&'static [u8]],
@@ -54,7 +56,8 @@ impl VerifiedBlockMap {
             generated_coins,
             weight,
             long_term_weight,
-            cumulative_difficulty,
+            cumulative_difficulty_low,
+            cumulative_difficulty_high,
             txs,
         } = self;
 
@@ -90,7 +93,10 @@ impl VerifiedBlockMap {
             generated_coins,
             weight,
             long_term_weight,
-            cumulative_difficulty,
+            cumulative_difficulty: combine_low_high_bits_to_u128(
+                cumulative_difficulty_low,
+                cumulative_difficulty_high,
+            ),
         }
     }
 }
@@ -131,7 +137,8 @@ macro_rules! verified_block_information_fn {
         generated_coins: $generated_coins:literal, // Generated coins in block (minus fees)
         weight: $weight:literal, // Block weight
         long_term_weight: $long_term_weight:literal, // Block long term weight
-        cumulative_difficulty: $cumulative_difficulty:literal, // Block cumulative difficulty
+        cumulative_difficulty_low: $cumulative_difficulty_low:literal, // Least significant 64-bits of block cumulative difficulty
+        cumulative_difficulty_high: $cumulative_difficulty_high:literal, // Most significant 64-bits of block cumulative difficulty
         tx_len: $tx_len:literal, // Amount of transactions in this block
     ) => {
         #[doc = concat!(
@@ -148,6 +155,8 @@ macro_rules! verified_block_information_fn {
         /// ```rust
         #[doc = "# use cuprate_test_utils::data::*;"]
         #[doc = "# use hex_literal::hex;"]
+        #[doc = "use cuprate_helper::map::combine_low_high_bits_to_u128;"]
+        #[doc = ""]
         #[doc = concat!("let block = ", stringify!($fn_name), "();")]
         #[doc = concat!("assert_eq!(&block.block.serialize(), ", stringify!($block_blob), ");")]
         #[doc = concat!("assert_eq!(block.pow_hash, hex!(\"", $pow_hash, "\"));")]
@@ -155,8 +164,16 @@ macro_rules! verified_block_information_fn {
         #[doc = concat!("assert_eq!(block.generated_coins, ", $generated_coins, ");")]
         #[doc = concat!("assert_eq!(block.weight, ", $weight, ");")]
         #[doc = concat!("assert_eq!(block.long_term_weight, ", $long_term_weight, ");")]
-        #[doc = concat!("assert_eq!(block.cumulative_difficulty, ", $cumulative_difficulty, ");")]
         #[doc = concat!("assert_eq!(block.txs.len(), ", $tx_len, ");")]
+        #[doc = ""]
+        #[doc = concat!(
+            "assert_eq!(block.cumulative_difficulty, ",
+            "combine_low_high_bits_to_u128(",
+            stringify!($cumulative_difficulty_low),
+            ", ",
+            stringify!($cumulative_difficulty_high),
+            "));"
+        )]
         /// ```
         pub fn $fn_name() -> &'static VerifiedBlockInformation {
             static BLOCK: OnceLock<VerifiedBlockInformation> = OnceLock::new();
@@ -168,7 +185,8 @@ macro_rules! verified_block_information_fn {
                     generated_coins: $generated_coins,
                     weight: $weight,
                     long_term_weight: $long_term_weight,
-                    cumulative_difficulty: $cumulative_difficulty,
+                    cumulative_difficulty_low: $cumulative_difficulty_low,
+                    cumulative_difficulty_high: $cumulative_difficulty_high,
                     txs: &[$($tx_blob),*],
                 }
                 .into_verified()
@@ -181,12 +199,13 @@ verified_block_information_fn! {
     fn_name: block_v1_tx2,
     block_blob: BLOCK_5ECB7E,
     tx_blobs: [TX_2180A8, TX_D7FEBD],
-    pow_hash: "84f64766475d51837ac9efbef1926486e58563c95a19fef4aec3254f03000000",
-    height: 202_612,
-    generated_coins: 13_138_270_467_918,
-    weight: 55_503,
-    long_term_weight: 55_503,
-    cumulative_difficulty: 126_654_460_829_362,
+    pow_hash: "c960d540000459480560b7816de968c7470083e5874e10040bdd4cc501000000",
+    height: 202_609,
+    generated_coins: 14_535_350_982_449,
+    weight: 21_905,
+    long_term_weight: 21_905,
+    cumulative_difficulty_low: 126_650_740_038_710,
+    cumulative_difficulty_high: 0,
     tx_len: 2,
 }
 
@@ -199,7 +218,8 @@ verified_block_information_fn! {
     generated_coins: 3_403_774_022_163,
     weight: 6_597,
     long_term_weight: 6_597,
-    cumulative_difficulty: 23_558_910_234_058_343,
+    cumulative_difficulty_low: 23_558_910_234_058_343,
+    cumulative_difficulty_high: 0,
     tx_len: 3,
 }
 
@@ -212,7 +232,8 @@ verified_block_information_fn! {
     generated_coins: 600_000_000_000,
     weight: 106,
     long_term_weight: 176_470,
-    cumulative_difficulty: 236_046_001_376_524_168,
+    cumulative_difficulty_low: 236_046_001_376_524_168,
+    cumulative_difficulty_high: 0,
     tx_len: 0,
 }
 
@@ -267,3 +288,55 @@ transaction_verification_data_fn! {
     weight: 2743,
     hash: "84d48dc11ec91950f8b70a85af9db91fe0c8abef71ef5db08304f7344b99ea66",
 }
+
+//---------------------------------------------------------------------------------------------------- TESTS
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    use pretty_assertions::assert_eq;
+
+    use crate::rpc::HttpRpcClient;
+
+    /// Assert the defined blocks are the same compared to ones received from a local RPC call.
+    #[ignore] // FIXME: doesn't work in CI, we need a real unrestricted node
+    #[tokio::test]
+    async fn block_same_as_rpc() {
+        let rpc = HttpRpcClient::new(None).await;
+        for block in [block_v1_tx2(), block_v9_tx3(), block_v16_tx0()] {
+            println!("block_height: {}", block.height);
+            let block_rpc = rpc.get_verified_block_information(block.height).await;
+            assert_eq!(block, &block_rpc);
+        }
+    }
+
+    /// Same as `block_same_as_rpc` but for transactions.
+    /// This also tests all the transactions within the defined blocks.
+    #[ignore] // FIXME: doesn't work in CI, we need a real unrestricted node
+    #[tokio::test]
+    async fn tx_same_as_rpc() {
+        let rpc = HttpRpcClient::new(None).await;
+
+        let mut txs = [block_v1_tx2(), block_v9_tx3(), block_v16_tx0()]
+            .into_iter()
+            .flat_map(|block| block.txs.iter().map(|arc| (**arc).clone()))
+            .collect::<Vec<TransactionVerificationData>>();
+
+        txs.extend([
+            tx_v1_sig0().clone(),
+            tx_v1_sig2().clone(),
+            tx_v2_rct3().clone(),
+        ]);
+
+        for tx in txs {
+            println!("tx_hash: {:?}", tx.tx_hash);
+            let tx_rpc = rpc
+                .get_transaction_verification_data(&[tx.tx_hash])
+                .await
+                .collect::<Vec<TransactionVerificationData>>()
+                .pop()
+                .unwrap();
+            assert_eq!(tx, tx_rpc);
+        }
+    }
+}

From 2ac90420c658663564a71b7ecb52d74f3c2c9d0f Mon Sep 17 00:00:00 2001
From: hinto-janai <hinto.janai@protonmail.com>
Date: Fri, 26 Apr 2024 19:49:55 -0400
Subject: [PATCH 2/2] ci: fix windows/macos (#116)

* cryptonight: include homebrew directories

* test-utils: add arm macos to `monerod` downloader

* ci: install windows-gnu
---
 .github/workflows/ci.yml           | 6 ++++++
 cryptonight/build.rs               | 5 ++++-
 test-utils/src/monerod/download.rs | 2 ++
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ebf40b12..96c7ce6a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -96,6 +96,12 @@ jobs:
         update: true
         install: mingw-w64-x86_64-toolchain mingw-w64-x86_64-boost msys2-runtime-devel git mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja
 
+    - name: Switch target (Windows)
+      if: matrix.os == 'windows-latest'
+      run: |
+        rustup toolchain install stable-x86_64-pc-windows-gnu -c clippy --no-self-update
+        rustup default stable-x86_64-pc-windows-gnu
+
     - name: Documentation
       run: cargo doc --workspace --all-features
 
diff --git a/cryptonight/build.rs b/cryptonight/build.rs
index 0950d94c..465236ec 100644
--- a/cryptonight/build.rs
+++ b/cryptonight/build.rs
@@ -32,7 +32,10 @@ fn main() {
         //    29 | extern int ftime (struct timeb *__timebuf)
         //       |            ^~~~~
         // This flag doesn't work on MSVC and breaks CI.
-        .flag_if_supported("-Wno-deprecated-declarations");
+        .flag_if_supported("-Wno-deprecated-declarations")
+        // `#include <boost>` isn't found without this in macOS CI.
+        // <https://github.com/Cuprate/cuprate/pull/116>
+        .flag_if_supported("-I/opt/homebrew/include");
 
     // Optimization flags are automatically added.
     // https://docs.rs/cc/latest/cc/struct.Build.html#method.opt_level
diff --git a/test-utils/src/monerod/download.rs b/test-utils/src/monerod/download.rs
index 699323f7..296b3a2b 100644
--- a/test-utils/src/monerod/download.rs
+++ b/test-utils/src/monerod/download.rs
@@ -29,6 +29,7 @@ fn file_name(version: &str) -> (String, String) {
         ("linux", "x64" | "x86_64") => format!("monero-linux-x64-{version}.tar.bz2"),
         ("linux", "x86") => format!("monero-linux-x86-{version}.tar.bz2"),
         ("macos", "x64" | "x86_64") => format!("monero-mac-x64-{version}.tar.bz2"),
+        ("macos", "aarch64") => format!("monero-mac-armv8-{version}.tar.bz2"),
         _ => panic!("Can't get monerod for {OS}, {ARCH}."),
     };
 
@@ -42,6 +43,7 @@ fn file_name(version: &str) -> (String, String) {
         ("macos", "x64" | "x86_64") => {
             format!("monero-x86_64-apple-darwin11-{version}")
         }
+        ("macos", "aarch64") => format!("monero-aarch64-apple-darwin11-{version}"),
         _ => panic!("Can't get monerod for {OS}, {ARCH}."),
     };