/ test / functional / test_framework / compressor.py
compressor.py
 1  #!/usr/bin/env python3
 2  # Copyright (c) 2025-present The Bitcoin Core developers
 3  # Distributed under the MIT software license, see the accompanying
 4  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 5  """Routines for compressing transaction output amounts and scripts."""
 6  import unittest
 7  
 8  from .messages import COIN
 9  
10  
11  def compress_amount(n):
12      if n == 0:
13          return 0
14      e = 0
15      while ((n % 10) == 0) and (e < 9):
16          n //= 10
17          e += 1
18      if e < 9:
19          d = n % 10
20          assert (d >= 1 and d <= 9)
21          n //= 10
22          return 1 + (n*9 + d - 1)*10 + e
23      else:
24          return 1 + (n - 1)*10 + 9
25  
26  
27  def decompress_amount(x):
28      if x == 0:
29          return 0
30      x -= 1
31      e = x % 10
32      x //= 10
33      n = 0
34      if e < 9:
35          d = (x % 9) + 1
36          x //= 9
37          n = x * 10 + d
38      else:
39          n = x + 1
40      while e > 0:
41          n *= 10
42          e -= 1
43      return n
44  
45  
46  class TestFrameworkCompressor(unittest.TestCase):
47      def test_amount_compress_decompress(self):
48          def check_amount(amount, expected_compressed):
49              self.assertEqual(compress_amount(amount), expected_compressed)
50              self.assertEqual(decompress_amount(expected_compressed), amount)
51  
52          # test cases from compress_tests.cpp:compress_amounts
53          check_amount(0, 0x0)
54          check_amount(1, 0x1)
55          check_amount(1000000, 0x7)
56          check_amount(COIN, 0x9)
57          check_amount(50*COIN, 0x32)
58          check_amount(21000000*COIN, 0x1406f40)