compressor.py raw

   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)
  59