1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#[rustfmt::skip]
/// Decomposed amount table.
pub static DECOMPOSED_AMOUNTS: [u64; 172] = [
    1,                   2,                   3,                   4,                   5,                   6,                   7,                   8,                   9,
    10,                  20,                  30,                  40,                  50,                  60,                  70,                  80,                  90,
    100,                 200,                 300,                 400,                 500,                 600,                 700,                 800,                 900,
    1000,                2000,                3000,                4000,                5000,                6000,                7000,                8000,                9000,
    10000,               20000,               30000,               40000,               50000,               60000,               70000,               80000,               90000,
    100000,              200000,              300000,              400000,              500000,              600000,              700000,              800000,              900000,
    1000000,             2000000,             3000000,             4000000,             5000000,             6000000,             7000000,             8000000,             9000000,
    10000000,            20000000,            30000000,            40000000,            50000000,            60000000,            70000000,            80000000,            90000000,
    100000000,           200000000,           300000000,           400000000,           500000000,           600000000,           700000000,           800000000,           900000000,
    1000000000,          2000000000,          3000000000,          4000000000,          5000000000,          6000000000,          7000000000,          8000000000,          9000000000,
    10000000000,         20000000000,         30000000000,         40000000000,         50000000000,         60000000000,         70000000000,         80000000000,         90000000000,
    100000000000,        200000000000,        300000000000,        400000000000,        500000000000,        600000000000,        700000000000,        800000000000,        900000000000,
    1000000000000,       2000000000000,       3000000000000,       4000000000000,       5000000000000,       6000000000000,       7000000000000,       8000000000000,       9000000000000,
    10000000000000,      20000000000000,      30000000000000,      40000000000000,      50000000000000,      60000000000000,      70000000000000,      80000000000000,      90000000000000,
    100000000000000,     200000000000000,     300000000000000,     400000000000000,     500000000000000,     600000000000000,     700000000000000,     800000000000000,     900000000000000,
    1000000000000000,    2000000000000000,    3000000000000000,    4000000000000000,    5000000000000000,    6000000000000000,    7000000000000000,    8000000000000000,    9000000000000000,
    10000000000000000,   20000000000000000,   30000000000000000,   40000000000000000,   50000000000000000,   60000000000000000,   70000000000000000,   80000000000000000,   90000000000000000,
    100000000000000000,  200000000000000000,  300000000000000000,  400000000000000000,  500000000000000000,  600000000000000000,  700000000000000000,  800000000000000000,  900000000000000000,
    1000000000000000000, 2000000000000000000, 3000000000000000000, 4000000000000000000, 5000000000000000000, 6000000000000000000, 7000000000000000000, 8000000000000000000, 9000000000000000000,
    10000000000000000000
];

/// Checks that an output amount is decomposed.
///
/// This is also used during miner tx verification.
///
/// ref: <https://monero-book.cuprate.org/consensus_rules/transactions/ring_signatures.html#output-amount>
/// ref: <https://monero-book.cuprate.org/consensus_rules/blocks/miner_tx.html#output-amounts>
#[inline]
pub fn is_decomposed_amount(amount: &u64) -> bool {
    DECOMPOSED_AMOUNTS.binary_search(amount).is_ok()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn decomposed_amounts_return_decomposed() {
        for amount in DECOMPOSED_AMOUNTS.iter() {
            assert!(is_decomposed_amount(amount))
        }
    }

    #[test]
    fn non_decomposed_amounts_return_not_decomposed() {
        assert!(!is_decomposed_amount(&21));
        assert!(!is_decomposed_amount(&345431));
        assert!(!is_decomposed_amount(&20000001));
    }
}