diff --git a/Cargo.toml b/Cargo.toml index b7e2c13117..20a9c21c08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,4 +15,4 @@ tempfile = "3.2.0" [[test]] name = "integration" -path = "tests/lib.rs" +path = "tests/integration.rs" diff --git a/README.md b/README.md index 1523e3398a..8e7153ac15 100644 --- a/README.md +++ b/README.md @@ -55,10 +55,24 @@ fn transfer(transaction: Transaction) { } ``` -The `find` command, unfinished, gives the current outpoint containing a given -satoshi as of a given height: +The `find` command, as of yet unfinished, gives the current outpoint containing +a given satoshi as of a given height: ``` $ sat-tracker find --blocksdir ~/.bicoin/blocks 0 0 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0 ``` + + +## Traits + +Satoshis have traits, based on their number. + +The `traits` command prints out the traits of a given satoshi: + +``` +$ sat-tracker traits 0 +zero +genesis +even +``` diff --git a/src/main.rs b/src/main.rs index e24eaafe2e..eee0f2c116 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,18 @@ mod traits; type Result> = std::result::Result; +fn subsidy(height: u64) -> u64 { + let subsidy = 50 * COIN_VALUE; + + let halvings = height / 210000; + + if halvings < 64 { + subsidy >> halvings + } else { + 0 + } +} + fn main() -> Result { Arguments::from_args().run() } diff --git a/src/range.rs b/src/range.rs index adbe40c8c1..1a4ad68b60 100644 --- a/src/range.rs +++ b/src/range.rs @@ -11,15 +11,3 @@ pub(crate) fn run(height: u64) -> Result { Ok(()) } - -fn subsidy(height: u64) -> u64 { - let subsidy = 50 * COIN_VALUE; - - let halvings = height / 210000; - - if halvings < 64 { - subsidy >> halvings - } else { - 0 - } -} diff --git a/src/traits.rs b/src/traits.rs index c638cebc3c..df2c682e90 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -2,7 +2,18 @@ use super::*; pub(crate) fn run(n: u64) -> Result { if n == 0 { - println!("divine"); + println!("zero"); } + + if n < subsidy(0) { + println!("genesis"); + } + + if n % 2 == 0 { + println!("even"); + } else { + println!("odd"); + } + Ok(()) } diff --git a/tests/lib.rs b/tests/integration.rs similarity index 88% rename from tests/lib.rs rename to tests/integration.rs index 427dae18df..b6826ddeec 100644 --- a/tests/lib.rs +++ b/tests/integration.rs @@ -8,6 +8,7 @@ use { }, executable_path::executable_path, std::{ + collections::BTreeSet, error::Error, fs::{self, File}, io::{self, Seek, SeekFrom, Write}, @@ -26,6 +27,7 @@ type Result = std::result::Result>; struct Test { args: Vec, expected_stdout: String, + ignore_stdout: bool, tempdir: TempDir, } @@ -34,6 +36,7 @@ impl Test { Ok(Self { args: Vec::new(), expected_stdout: String::new(), + ignore_stdout: false, tempdir: TempDir::new()?, }) } @@ -56,7 +59,18 @@ impl Test { } } + fn ignore_stdout(self) -> Self { + Self { + ignore_stdout: true, + ..self + } + } + fn run(self) -> Result { + self.run_with_stdout().map(|_| ()) + } + + fn run_with_stdout(self) -> Result { let blocksdir = self.tempdir.path().join("blocks"); fs::create_dir(&blocksdir)?; populate_blockfile(File::create(blocksdir.join("blk00000.dat"))?, 1)?; @@ -72,9 +86,13 @@ impl Test { panic!("Test failed: {}\n{}", output.status, stderr); } - assert_eq!(str::from_utf8(&output.stdout)?, self.expected_stdout); + let stdout = str::from_utf8(&output.stdout)?; + + if !self.ignore_stdout { + assert_eq!(stdout, self.expected_stdout); + } - Ok(()) + Ok(stdout.to_owned()) } } diff --git a/tests/traits.rs b/tests/traits.rs index 66c4e63dc3..6bac799591 100644 --- a/tests/traits.rs +++ b/tests/traits.rs @@ -1,9 +1,44 @@ use super::*; +fn traits(n: u64) -> Result> { + Ok( + Test::new()? + .args(&["traits", &n.to_string()]) + .ignore_stdout() + .run_with_stdout()? + .split_whitespace() + .map(str::to_owned) + .collect(), + ) +} + #[test] fn zero() -> Result { - Test::new()? - .args(&["traits", "0"]) - .expected_stdout("divine\n") - .run() + assert!(traits(0)?.contains("zero")); + assert!(!traits(1)?.contains("zero")); + Ok(()) +} + +#[test] +fn genesis() -> Result { + assert!(traits(0)?.contains("genesis")); + assert!(traits(50 * COIN_VALUE - 1)?.contains("genesis")); + assert!(!traits(50 * COIN_VALUE)?.contains("genesis")); + Ok(()) +} + +#[test] +fn even() -> Result { + assert!(traits(0)?.contains("even")); + assert!(!traits(1)?.contains("even")); + assert!(traits(2)?.contains("even")); + Ok(()) +} + +#[test] +fn odd() -> Result { + assert!(!traits(0)?.contains("odd")); + assert!(traits(1)?.contains("odd")); + assert!(!traits(2)?.contains("odd")); + Ok(()) }