params.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
  4. # Copyright (C)2013-2022 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen
  9. # https://gitlab.com/mmgen/mmgen
  10. """
  11. Bitcoin protocol
  12. """
  13. from ...protocol import CoinProtocol,decoded_wif,decoded_addr,_finfo,_nw
  14. from .common import b58chk_decode,b58chk_encode,hash160
  15. class mainnet(CoinProtocol.Secp256k1): # chainparams.cpp
  16. """
  17. All Bitcoin code and chain forks inherit from this class
  18. """
  19. mod_clsname = 'Bitcoin'
  20. network_names = _nw('mainnet','testnet','regtest')
  21. addr_ver_info = { '00': 'p2pkh', '05': 'p2sh' }
  22. addr_len = 20
  23. wif_ver_num = { 'std': '80' }
  24. mmtypes = ('L','C','S','B')
  25. dfl_mmtype = 'L'
  26. coin_amt = 'BTCAmt'
  27. max_tx_fee = '0.003'
  28. sighash_type = 'ALL'
  29. block0 = '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'
  30. forks = [
  31. _finfo(478559,'00000000000000000019f112ec0a9982926f1258cdcc558dd7c3b7e5dc7fa148','BCH',False),
  32. ]
  33. caps = ('rbf','segwit')
  34. mmcaps = ('key','addr','rpc_init','tx')
  35. base_proto = 'Bitcoin'
  36. base_proto_coin = 'BTC'
  37. base_coin = 'BTC'
  38. # From BIP173: witness version 'n' is stored as 'OP_n'. OP_0 is encoded as 0x00,
  39. # but OP_1 through OP_16 are encoded as 0x51 though 0x60 (81 to 96 in decimal).
  40. witness_vernum_hex = '00'
  41. witness_vernum = int(witness_vernum_hex,16)
  42. bech32_hrp = 'bc'
  43. sign_mode = 'daemon'
  44. avg_bdi = int(9.7 * 60) # average block discovery interval (historical)
  45. halving_interval = 210000
  46. diff_adjust_interval = 2016
  47. max_halvings = 64
  48. start_subsidy = 50
  49. ignore_daemon_version = False
  50. max_int = 0xffffffff
  51. def encode_wif(self,privbytes,pubkey_type,compressed): # input is preprocessed hex
  52. assert len(privbytes) == self.privkey_len, f'{len(privbytes)} bytes: incorrect private key length!'
  53. assert pubkey_type in self.wif_ver_bytes, f'{pubkey_type!r}: invalid pubkey_type'
  54. return b58chk_encode(
  55. self.wif_ver_bytes[pubkey_type]
  56. + privbytes
  57. + (b'',b'\x01')[bool(compressed)])
  58. def decode_wif(self,wif):
  59. key_data = b58chk_decode(wif)
  60. vlen = self.wif_ver_bytes_len or self.get_wif_ver_bytes_len(key_data)
  61. key = key_data[vlen:]
  62. if len(key) == self.privkey_len + 1:
  63. assert key[-1] == 0x01, f'{key[-1]!r}: invalid compressed key suffix byte'
  64. elif len(key) != self.privkey_len:
  65. raise ValueError(f'{len(key)}: invalid key length')
  66. return decoded_wif(
  67. sec = key[:self.privkey_len],
  68. pubkey_type = self.wif_ver_bytes_to_pubkey_type[key_data[:vlen]],
  69. compressed = len(key) == self.privkey_len + 1 )
  70. def decode_addr(self,addr):
  71. if 'B' in self.mmtypes and addr[:len(self.bech32_hrp)] == self.bech32_hrp:
  72. import mmgen.contrib.bech32 as bech32
  73. ret = bech32.decode(self.bech32_hrp,addr)
  74. if ret[0] != self.witness_vernum:
  75. from ...util import msg
  76. msg(f'{ret[0]}: Invalid witness version number')
  77. return False
  78. return decoded_addr( bytes(ret[1]), None, 'bech32' ) if ret[1] else False
  79. return self.decode_addr_bytes(b58chk_decode(addr))
  80. def pubhash2addr(self,pubhash,p2sh):
  81. assert len(pubhash) == 20, f'{len(pubhash)}: invalid length for pubkey hash'
  82. return b58chk_encode(
  83. self.addr_fmt_to_ver_bytes[('p2pkh','p2sh')[p2sh]] + pubhash
  84. )
  85. # Segwit:
  86. def pubhash2redeem_script(self,pubhash):
  87. # https://bitcoincore.org/en/segwit_wallet_dev/
  88. # The P2SH redeemScript is always 22 bytes. It starts with a OP_0, followed
  89. # by a canonical push of the keyhash (i.e. 0x0014{20-byte keyhash})
  90. return bytes.fromhex(self.witness_vernum_hex + '14') + pubhash
  91. def pubhash2segwitaddr(self,pubhash):
  92. return self.pubhash2addr(
  93. hash160( self.pubhash2redeem_script(pubhash) ),
  94. p2sh = True )
  95. def pubhash2bech32addr(self,pubhash):
  96. import mmgen.contrib.bech32 as bech32
  97. return bech32.bech32_encode(
  98. hrp = self.bech32_hrp,
  99. data = [self.witness_vernum] + bech32.convertbits(list(pubhash),8,5) )
  100. class testnet(mainnet):
  101. addr_ver_info = { '6f': 'p2pkh', 'c4': 'p2sh' }
  102. wif_ver_num = { 'std': 'ef' }
  103. bech32_hrp = 'tb'
  104. class regtest(testnet):
  105. bech32_hrp = 'bcrt'
  106. halving_interval = 150