LCOV - code coverage report
Current view: top level - src/test - compress_tests.cpp (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 100.0 % 93 93
Test Date: 2024-11-04 04:45:35 Functions: 100.0 % 15 15
Branches: 51.0 % 616 314

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2012-2021 The Bitcoin Core developers
       2                 :             : // Distributed under the MIT software license, see the accompanying
       3                 :             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4                 :             : 
       5                 :             : #include <compressor.h>
       6                 :             : #include <script/script.h>
       7                 :             : #include <test/util/random.h>
       8                 :             : #include <test/util/setup_common.h>
       9                 :             : 
      10                 :             : #include <stdint.h>
      11                 :             : 
      12                 :             : #include <boost/test/unit_test.hpp>
      13                 :             : 
      14                 :             : // amounts 0.00000001 .. 0.00100000
      15                 :             : #define NUM_MULTIPLES_UNIT 100000
      16                 :             : 
      17                 :             : // amounts 0.01 .. 100.00
      18                 :             : #define NUM_MULTIPLES_CENT 10000
      19                 :             : 
      20                 :             : // amounts 1 .. 10000
      21                 :             : #define NUM_MULTIPLES_1BTC 10000
      22                 :             : 
      23                 :             : // amounts 50 .. 21000000
      24                 :             : #define NUM_MULTIPLES_50BTC 420000
      25                 :             : 
      26                 :             : BOOST_FIXTURE_TEST_SUITE(compress_tests, BasicTestingSetup)
      27                 :             : 
      28                 :      540000 : bool static TestEncode(uint64_t in) {
      29                 :      540000 :     return in == DecompressAmount(CompressAmount(in));
      30                 :             : }
      31                 :             : 
      32                 :      100000 : bool static TestDecode(uint64_t in) {
      33                 :      100000 :     return in == CompressAmount(DecompressAmount(in));
      34                 :             : }
      35                 :             : 
      36                 :           6 : bool static TestPair(uint64_t dec, uint64_t enc) {
      37   [ +  -  -  + ]:          12 :     return CompressAmount(dec) == enc &&
      38                 :           6 :            DecompressAmount(enc) == dec;
      39                 :             : }
      40                 :             : 
      41   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(compress_amounts)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      42                 :             : {
      43   [ +  -  +  - ]:           2 :     BOOST_CHECK(TestPair(            0,       0x0));
      44   [ +  -  +  - ]:           2 :     BOOST_CHECK(TestPair(            1,       0x1));
      45   [ +  -  +  - ]:           2 :     BOOST_CHECK(TestPair(         CENT,       0x7));
      46   [ +  -  +  - ]:           2 :     BOOST_CHECK(TestPair(         COIN,       0x9));
      47   [ +  -  +  - ]:           2 :     BOOST_CHECK(TestPair(      50*COIN,      0x32));
      48   [ +  -  +  - ]:           2 :     BOOST_CHECK(TestPair(21000000*COIN, 0x1406f40));
      49                 :             : 
      50         [ +  + ]:      100001 :     for (uint64_t i = 1; i <= NUM_MULTIPLES_UNIT; i++)
      51   [ +  -  +  - ]:      200000 :         BOOST_CHECK(TestEncode(i));
      52                 :             : 
      53         [ +  + ]:       10001 :     for (uint64_t i = 1; i <= NUM_MULTIPLES_CENT; i++)
      54   [ +  -  +  - ]:       20000 :         BOOST_CHECK(TestEncode(i * CENT));
      55                 :             : 
      56         [ +  + ]:       10001 :     for (uint64_t i = 1; i <= NUM_MULTIPLES_1BTC; i++)
      57   [ +  -  +  - ]:       20000 :         BOOST_CHECK(TestEncode(i * COIN));
      58                 :             : 
      59         [ +  + ]:      420001 :     for (uint64_t i = 1; i <= NUM_MULTIPLES_50BTC; i++)
      60   [ +  -  +  - ]:      840000 :         BOOST_CHECK(TestEncode(i * 50 * COIN));
      61                 :             : 
      62         [ +  + ]:      100001 :     for (uint64_t i = 0; i < 100000; i++)
      63   [ +  -  +  - ]:      200000 :         BOOST_CHECK(TestDecode(i));
      64                 :           1 : }
      65                 :             : 
      66   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(compress_script_to_ckey_id)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      67                 :             : {
      68                 :             :     // case CKeyID
      69                 :           1 :     CKey key = GenerateRandomKey();
      70         [ +  - ]:           1 :     CPubKey pubkey = key.GetPubKey();
      71                 :             : 
      72   [ +  -  +  -  :           1 :     CScript script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
          +  -  +  -  +  
                -  +  - ]
      73   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(script.size(), 25U);
                   +  - ]
      74                 :             : 
      75                 :           1 :     CompressedScript out;
      76         [ +  - ]:           1 :     bool done = CompressScript(script, out);
      77   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(done, true);
      78                 :             : 
      79                 :             :     // Check compressed script
      80   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(out.size(), 21U);
                   +  - ]
      81   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(out[0], 0x00);
                   +  - ]
      82   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(memcmp(out.data() + 1, script.data() + 3, 20), 0); // compare the 20 relevant chars of the CKeyId in the script
             -  +  +  - ]
      83                 :           1 : }
      84                 :             : 
      85   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(compress_script_to_cscript_id)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      86                 :             : {
      87                 :             :     // case CScriptID
      88                 :           1 :     CScript script, redeemScript;
      89   [ +  -  +  -  :           2 :     script << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
             +  -  +  - ]
      90   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(script.size(), 23U);
                   +  - ]
      91                 :             : 
      92                 :           1 :     CompressedScript out;
      93         [ +  - ]:           1 :     bool done = CompressScript(script, out);
      94   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(done, true);
      95                 :             : 
      96                 :             :     // Check compressed script
      97   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(out.size(), 21U);
                   +  - ]
      98   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(out[0], 0x01);
                   +  - ]
      99   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(memcmp(out.data() + 1, script.data() + 2, 20), 0); // compare the 20 relevant chars of the CScriptId in the script
             -  +  +  - ]
     100                 :           1 : }
     101                 :             : 
     102   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(compress_script_to_compressed_pubkey_id)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     103                 :             : {
     104                 :           1 :     CKey key = GenerateRandomKey(); // case compressed PubKeyID
     105                 :             : 
     106   [ +  -  +  -  :           1 :     CScript script = CScript() << ToByteVector(key.GetPubKey()) << OP_CHECKSIG; // COMPRESSED_PUBLIC_KEY_SIZE (33)
                   +  - ]
     107   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(script.size(), 35U);
                   +  - ]
     108                 :             : 
     109                 :           1 :     CompressedScript out;
     110         [ +  - ]:           1 :     bool done = CompressScript(script, out);
     111   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(done, true);
     112                 :             : 
     113                 :             :     // Check compressed script
     114   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(out.size(), 33U);
                   +  - ]
     115   [ +  -  -  +  :           2 :     BOOST_CHECK_EQUAL(memcmp(out.data(), script.data() + 1, 1), 0);
             +  -  +  - ]
     116   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(memcmp(out.data() + 1, script.data() + 2, 32), 0); // compare the 32 chars of the compressed CPubKey
             -  +  +  - ]
     117                 :           1 : }
     118                 :             : 
     119   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(compress_script_to_uncompressed_pubkey_id)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     120                 :             : {
     121                 :           1 :     CKey key = GenerateRandomKey(/*compressed=*/false); // case uncompressed PubKeyID
     122   [ +  -  +  -  :           1 :     CScript script =  CScript() << ToByteVector(key.GetPubKey()) << OP_CHECKSIG; // PUBLIC_KEY_SIZE (65)
                   +  - ]
     123   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(script.size(), 67U);                   // 1 char code + 65 char pubkey + OP_CHECKSIG
                   +  - ]
     124                 :             : 
     125                 :           1 :     CompressedScript out;
     126         [ +  - ]:           1 :     bool done = CompressScript(script, out);
     127   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(done, true);
     128                 :             : 
     129                 :             :     // Check compressed script
     130   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(out.size(), 33U);
                   +  - ]
     131   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(memcmp(out.data() + 1, script.data() + 2, 32), 0); // first 32 chars of CPubKey are copied into out[1:]
             -  +  +  - ]
     132   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(out[0], 0x04 | (script[65] & 0x01)); // least significant bit (lsb) of last char of pubkey is mapped into out[0]
             -  +  +  - ]
     133                 :           1 : }
     134                 :             : 
     135   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(compress_p2pk_scripts_not_on_curve)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     136                 :             : {
     137                 :           1 :     XOnlyPubKey x_not_on_curve;
     138                 :           1 :     do {
     139                 :           1 :         x_not_on_curve = XOnlyPubKey(m_rng.randbytes(32));
     140         [ -  + ]:           1 :     } while (x_not_on_curve.IsFullyValid());
     141                 :             : 
     142                 :             :     // Check that P2PK script with uncompressed pubkey [=> OP_PUSH65 <0x04 .....> OP_CHECKSIG]
     143                 :             :     // which is not fully valid (i.e. point is not on curve) can't be compressed
     144                 :           1 :     std::vector<unsigned char> pubkey_raw(65, 0);
     145                 :           1 :     pubkey_raw[0] = 4;
     146                 :           1 :     std::copy(x_not_on_curve.begin(), x_not_on_curve.end(), &pubkey_raw[1]);
     147                 :           1 :     CPubKey pubkey_not_on_curve(pubkey_raw);
     148         [ -  + ]:           1 :     assert(pubkey_not_on_curve.IsValid());
     149   [ +  -  -  + ]:           1 :     assert(!pubkey_not_on_curve.IsFullyValid());
     150   [ +  -  +  - ]:           1 :     CScript script = CScript() << ToByteVector(pubkey_not_on_curve) << OP_CHECKSIG;
     151   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(script.size(), 67U);
                   +  - ]
     152                 :             : 
     153                 :           1 :     CompressedScript out;
     154         [ +  - ]:           1 :     bool done = CompressScript(script, out);
     155   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(done, false);
     156                 :             : 
     157                 :             :     // Check that compressed P2PK script with uncompressed pubkey that is not fully
     158                 :             :     // valid (i.e. x coordinate of the pubkey is not on curve) can't be decompressed
     159                 :           1 :     CompressedScript compressed_script(x_not_on_curve.begin(), x_not_on_curve.end());
     160         [ +  + ]:           3 :     for (unsigned int compression_id : {4, 5}) {
     161                 :           2 :         CScript uncompressed_script;
     162         [ +  - ]:           2 :         bool success = DecompressScript(uncompressed_script, compression_id, compressed_script);
     163   [ +  -  +  - ]:           2 :         BOOST_CHECK_EQUAL(success, false);
     164                 :           2 :     }
     165                 :           1 : }
     166                 :             : 
     167                 :             : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1