Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: fix codecov #26

Merged
merged 2 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,15 @@ jobs:
docker-compose -f docker/docker-compose.dev.postgres.yml up -d
docker-compose -f docker/docker-compose.dev.postgres.yml logs -t -f --no-color &> docker-compose-logs.txt &

- name: Cargo test
- name: Update Rust
run: |
rustup update
RUST_BACKTRACE=1 cargo test --all -- --test-threads=1

- name: Install and run cargo-tarpaulin
run: |
cargo install cargo-tarpaulin
cargo --version
cargo tarpaulin --out lcov -- --test-threads=1

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4
Expand Down
16 changes: 10 additions & 6 deletions src/db/cache/index_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@
};

use super::{
db_cache::DbCache,
transaction_cache::{InputRuneBalance, TransactionCache},
transaction_location::TransactionLocation,
utils::move_block_output_cache_to_output_cache,
db_cache::DbCache, input_rune_balance::InputRuneBalance, transaction_cache::TransactionCache,
transaction_location::TransactionLocation, utils::move_block_output_cache_to_output_cache,
};

/// Holds rune data across multiple blocks for faster computations. Processes rune events as they happen during transactions and
Expand Down Expand Up @@ -106,7 +104,10 @@
try_debug!(ctx, "INPUT {rune_id} {balances:?} {location}");
}
if input_runes.len() > 0 {
try_debug!(ctx, "First output: {first_eligible_output:?}, total_outputs: {total_outputs}");
try_debug!(

Check warning on line 107 in src/db/cache/index_cache.rs

View check run for this annotation

Codecov / codecov/patch

src/db/cache/index_cache.rs#L107

Added line #L107 was not covered by tests
ctx,
"First output: {first_eligible_output:?}, total_outputs: {total_outputs}"
);
}
}
self.tx_cache = TransactionCache::new(
Expand All @@ -125,7 +126,10 @@
}

pub fn end_block(&mut self) {
move_block_output_cache_to_output_cache(&mut self.block_output_cache, &mut self.output_cache);
move_block_output_cache_to_output_cache(
&mut self.block_output_cache,
&mut self.output_cache,

Check warning on line 131 in src/db/cache/index_cache.rs

View check run for this annotation

Codecov / codecov/patch

src/db/cache/index_cache.rs#L130-L131

Added lines #L130 - L131 were not covered by tests
);
}

pub async fn apply_runestone(
Expand Down
29 changes: 29 additions & 0 deletions src/db/cache/input_rune_balance.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#[derive(Debug, Clone)]
pub struct InputRuneBalance {
/// Previous owner of this balance. If this is `None`, it means the balance was just minted or premined.
pub address: Option<String>,
/// How much balance was input to this transaction.
pub amount: u128,
}

#[cfg(test)]
impl InputRuneBalance {
pub fn dummy() -> Self {
InputRuneBalance {
address: Some(
"bc1p8zxlhgdsq6dmkzk4ammzcx55c3hfrg69ftx0gzlnfwq0wh38prds0nzqwf".to_string(),
),
amount: 1000,
}
}

pub fn amount(&mut self, amount: u128) -> &mut Self {
self.amount = amount;
return self;
}

pub fn address(&mut self, address: Option<String>) -> &mut Self {
self.address = address;
return self;
}
}
1 change: 1 addition & 0 deletions src/db/cache/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod db_cache;
pub mod index_cache;
pub mod input_rune_balance;
pub mod transaction_cache;
pub mod transaction_location;
pub mod utils;
13 changes: 4 additions & 9 deletions src/db/cache/transaction_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,10 @@ use crate::{
try_debug, try_info, try_warn,
};

use super::{transaction_location::TransactionLocation, utils::move_rune_balance_to_output};

#[derive(Debug, Clone)]
pub struct InputRuneBalance {
/// Previous owner of this balance. If this is `None`, it means the balance was just minted or premined.
pub address: Option<String>,
/// How much balance was input to this transaction.
pub amount: u128,
}
use super::{
input_rune_balance::InputRuneBalance, transaction_location::TransactionLocation,
utils::move_rune_balance_to_output,
};

/// Holds cached data relevant to a single transaction during indexing.
pub struct TransactionCache {
Expand Down
2 changes: 1 addition & 1 deletion src/db/cache/transaction_location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl fmt::Display for TransactionLocation {

#[cfg(test)]
impl TransactionLocation {
pub fn factory() -> Self {
pub fn dummy() -> Self {
TransactionLocation {
network: Network::Bitcoin,
block_hash: "0000000000000000000320283a032748cef8227873ff4872689bf23f1cda83a5"
Expand Down
245 changes: 95 additions & 150 deletions src/db/cache/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
try_info, try_warn,
};

use super::{transaction_cache::InputRuneBalance, transaction_location::TransactionLocation};
use super::{input_rune_balance::InputRuneBalance, transaction_location::TransactionLocation};

/// Takes all transaction inputs and transforms them into rune balances to be allocated for operations. Looks inside an output LRU
/// cache and the DB when there are cache misses.
Expand Down Expand Up @@ -88,7 +88,7 @@ pub fn move_block_output_cache_to_output_cache(
block_output_cache.clear();
}

/// Creates a new ledger entry.
/// Creates a new ledger entry while incrementing the `next_event_index`.
pub fn new_ledger_entry(
location: &TransactionLocation,
amount: Option<u128>,
Expand Down Expand Up @@ -286,166 +286,111 @@ pub fn is_rune_mintable(

#[cfg(test)]
mod test {
use std::collections::{HashMap, VecDeque};
use test_case::test_case;
mod move_balance {
use std::collections::{HashMap, VecDeque};

use bitcoin::ScriptBuf;
use chainhook_sdk::utils::Context;
use ordinals::RuneId;
use bitcoin::ScriptBuf;
use chainhook_sdk::utils::Context;
use ordinals::RuneId;

use crate::db::{
cache::{
transaction_cache::InputRuneBalance, transaction_location::TransactionLocation,
utils::move_rune_balance_to_output,
},
models::{db_ledger_operation::DbLedgerOperation, db_rune::DbRune},
types::{pg_numeric_u128::PgNumericU128, pg_numeric_u64::PgNumericU64},
};

use super::is_rune_mintable;

#[test]
fn receives_are_registered_first() {
let ctx = Context::empty();
let location = TransactionLocation {
network: bitcoin::Network::Bitcoin,
block_hash: "00000000000000000002c0cc73626b56fb3ee1ce605b0ce125cc4fb58775a0a9"
.to_string(),
block_height: 840002,
timestamp: 0,
tx_id: "37cd29676d626492cd9f20c60bc4f20347af9c0d91b5689ed75c05bb3e2f73ef".to_string(),
tx_index: 2936,
use crate::db::{
cache::{
input_rune_balance::InputRuneBalance, transaction_location::TransactionLocation,
utils::move_rune_balance_to_output,
},
models::db_ledger_operation::DbLedgerOperation,
};
let mut available_inputs = VecDeque::new();
// An input from a previous tx
available_inputs.push_back(InputRuneBalance {
address: Some(
"bc1p8zxlhgdsq6dmkzk4ammzcx55c3hfrg69ftx0gzlnfwq0wh38prds0nzqwf".to_string(),
),
amount: 1000,
});
// A mint
available_inputs.push_back(InputRuneBalance {
address: None,
amount: 1000,
});
let mut eligible_outputs = HashMap::new();
eligible_outputs.insert(
0u32,
ScriptBuf::from_hex(
"5120388dfba1b0069bbb0ad5eef62c1a94c46e91a3454accf40bf34b80f75e2708db",
)
.unwrap(),
);
let mut next_event_index = 0;
let results = move_rune_balance_to_output(
&location,
Some(0),
&RuneId::new(840000, 25).unwrap(),
&mut available_inputs,
&eligible_outputs,
0,
&mut next_event_index,
&ctx,
);

let receive = results.get(0).unwrap();
assert_eq!(receive.event_index.0, 0u32);
assert_eq!(receive.operation, DbLedgerOperation::Receive);
assert_eq!(receive.amount.unwrap().0, 2000u128);
#[test]
fn ledger_writes_receive_before_send() {
let address =
Some("bc1p8zxlhgdsq6dmkzk4ammzcx55c3hfrg69ftx0gzlnfwq0wh38prds0nzqwf".to_string());
let mut available_inputs = VecDeque::new();
let mut input1 = InputRuneBalance::dummy();
input1.address(address.clone()).amount(1000);
available_inputs.push_back(input1);
let mut input2 = InputRuneBalance::dummy();
input2.address(None).amount(1000);
available_inputs.push_back(input2);
let mut eligible_outputs = HashMap::new();
eligible_outputs.insert(
0u32,
ScriptBuf::from_hex(
"5120388dfba1b0069bbb0ad5eef62c1a94c46e91a3454accf40bf34b80f75e2708db",
)
.unwrap(),
);
let mut next_event_index = 0;

let send = results.get(1).unwrap();
assert_eq!(send.event_index.0, 1u32);
assert_eq!(send.operation, DbLedgerOperation::Send);
assert_eq!(send.amount.unwrap().0, 1000u128);
let results = move_rune_balance_to_output(
&TransactionLocation::dummy(),
Some(0),
&RuneId::new(840000, 25).unwrap(),
&mut available_inputs,
&eligible_outputs,
0,
&mut next_event_index,
&Context::empty(),
);

assert_eq!(results.len(), 2);
}
let receive = results.get(0).unwrap();
assert_eq!(receive.event_index.0, 0u32);
assert_eq!(receive.operation, DbLedgerOperation::Receive);
assert_eq!(receive.amount.unwrap().0, 2000u128);

#[test_case(840000 => false; "early block")]
#[test_case(840500 => false; "late block")]
#[test_case(840150 => true; "block in window")]
#[test_case(840100 => true; "first block")]
#[test_case(840200 => true; "last block")]
fn mint_block_height_terms_are_validated(block_height: u64) -> bool {
let mut rune = DbRune::factory();
rune.terms_height_start(Some(PgNumericU64(840100)));
rune.terms_height_end(Some(PgNumericU64(840200)));
let mut location = TransactionLocation::factory();
location.block_height(block_height);
is_rune_mintable(&rune, 0, &location)
}
let send = results.get(1).unwrap();
assert_eq!(send.event_index.0, 1u32);
assert_eq!(send.operation, DbLedgerOperation::Send);
assert_eq!(send.amount.unwrap().0, 1000u128);

#[test_case(840000 => false; "early block")]
#[test_case(840500 => false; "late block")]
#[test_case(840150 => true; "block in window")]
#[test_case(840100 => true; "first block")]
#[test_case(840200 => true; "last block")]
fn mint_block_offset_terms_are_validated(block_height: u64) -> bool {
let mut rune = DbRune::factory();
rune.terms_offset_start(Some(PgNumericU64(100)));
rune.terms_offset_end(Some(PgNumericU64(200)));
let mut location = TransactionLocation::factory();
location.block_height(block_height);
is_rune_mintable(&rune, 0, &location)
assert_eq!(results.len(), 2);
}
}

#[test_case(0 => true; "first mint")]
#[test_case(49 => true; "last mint")]
#[test_case(50 => false; "out of range")]
fn mint_cap_is_validated(cap: u128) -> bool {
let mut rune = DbRune::factory();
rune.terms_cap(Some(PgNumericU128(50)));
is_rune_mintable(&rune, cap, &TransactionLocation::factory())
}
mod mint_validation {
use test_case::test_case;

// use std::{collections::HashMap, num::NonZeroUsize, str::FromStr};
use crate::db::{
cache::{transaction_location::TransactionLocation, utils::is_rune_mintable},
models::db_rune::DbRune,
types::{pg_numeric_u128::PgNumericU128, pg_numeric_u64::PgNumericU64},
};

// use chainhook_sdk::{
// types::{
// bitcoin::{OutPoint, TxIn},
// TransactionIdentifier,
// },
// utils::Context,
// };
// use lru::LruCache;
// use ordinals::RuneId;
#[test_case(840000 => false; "early block")]
#[test_case(840500 => false; "late block")]
#[test_case(840150 => true; "block in window")]
#[test_case(840100 => true; "first block")]
#[test_case(840200 => true; "last block")]
fn mint_block_height_terms_are_validated(block_height: u64) -> bool {
let mut rune = DbRune::factory();
rune.terms_height_start(Some(PgNumericU64(840100)));
rune.terms_height_end(Some(PgNumericU64(840200)));
let mut location = TransactionLocation::dummy();
location.block_height(block_height);
is_rune_mintable(&rune, 0, &location)
}

// use crate::db::cache::transaction_cache::InputRuneBalance;
#[test_case(840000 => false; "early block")]
#[test_case(840500 => false; "late block")]
#[test_case(840150 => true; "block in window")]
#[test_case(840100 => true; "first block")]
#[test_case(840200 => true; "last block")]
fn mint_block_offset_terms_are_validated(block_height: u64) -> bool {
let mut rune = DbRune::factory();
rune.terms_offset_start(Some(PgNumericU64(100)));
rune.terms_offset_end(Some(PgNumericU64(200)));
let mut location = TransactionLocation::dummy();
location.block_height(block_height);
is_rune_mintable(&rune, 0, &location)
}

// #[test]
// fn from_output_cache() {
// let tx_inputs = vec![TxIn {
// previous_output: OutPoint {
// txid: TransactionIdentifier {
// hash: "aea76e5ef8135851d0387074cf7672013779e4506e56122e0e698e12ede62681"
// .to_string(),
// },
// vout: 2,
// value: 100,
// block_height: 848300,
// },
// script_sig: "".to_string(),
// sequence: 1,
// witness: vec![],
// }];
// let mut value = HashMap::new();
// value.insert(
// RuneId::from_str("840000:1").unwrap(),
// vec![InputRuneBalance {
// address: Some("1EDYZPvGqKzZYp6DoTtcgXwvSAkA9d9UKU".to_string()),
// amount: 10000,
// }],
// );
// let mut output_cache: LruCache<(String, u32), HashMap<RuneId, Vec<InputRuneBalance>>> =
// LruCache::new(NonZeroUsize::new(2).unwrap());
// output_cache.put(
// (
// "aea76e5ef8135851d0387074cf7672013779e4506e56122e0e698e12ede62681".to_string(),
// 2,
// ),
// value,
// );
// let ctx = Context::empty();
// }
#[test_case(0 => true; "first mint")]
#[test_case(49 => true; "last mint")]
#[test_case(50 => false; "out of range")]
fn mint_cap_is_validated(cap: u128) -> bool {
let mut rune = DbRune::factory();
rune.terms_cap(Some(PgNumericU128(50)));
is_rune_mintable(&rune, cap, &TransactionLocation::dummy())
}
}
}
Loading
Loading