utils.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #
  2. # Adapted from: https://github.com/ethereum/pyethereum/blob/master/ethereum/utils.py
  3. #
  4. from py_ecc.secp256k1 import privtopub,ecdsa_raw_sign,ecdsa_raw_recover
  5. from .. import rlp
  6. from ..rlp.sedes import Binary
  7. from mmgen.globalvars import g
  8. try:
  9. assert not g.use_internal_keccak_module
  10. import sha3 as _sha3
  11. def sha3_256(x): return _sha3.keccak_256(x).digest()
  12. except:
  13. from mmgen.keccak import keccak_256
  14. def sha3_256(x):
  15. return keccak_256(x).digest()
  16. import struct
  17. ALL_BYTES = tuple( struct.pack('B', i) for i in range(256) )
  18. # from eth_utils:
  19. # Type ignored for `codecs.decode()` due to lack of mypy support for 'hex' encoding
  20. # https://github.com/python/typeshed/issues/300
  21. from typing import AnyStr,Any,Callable,TypeVar
  22. import codecs
  23. import functools
  24. T = TypeVar("T")
  25. TVal = TypeVar("TVal")
  26. TKey = TypeVar("TKey")
  27. def apply_to_return_value(callback: Callable[..., T]) -> Callable[..., Callable[..., T]]:
  28. def outer(fn):
  29. # We would need to type annotate *args and **kwargs but doing so segfaults
  30. # the PyPy builds. We ignore instead.
  31. @functools.wraps(fn)
  32. def inner(*args, **kwargs) -> T: # type: ignore
  33. return callback(fn(*args, **kwargs))
  34. return inner
  35. return outer
  36. to_list = apply_to_return_value(list)
  37. to_set = apply_to_return_value(set)
  38. to_dict = apply_to_return_value(dict)
  39. to_tuple = apply_to_return_value(tuple)
  40. to_list = apply_to_return_value(list)
  41. def encode_hex_0x(value: AnyStr) -> str:
  42. if not is_string(value):
  43. raise TypeError("Value must be an instance of str or unicode")
  44. binary_hex = codecs.encode(value, "hex") # type: ignore
  45. return '0x' + binary_hex.decode("ascii")
  46. def decode_hex(value: str) -> bytes:
  47. if not isinstance(value,str):
  48. raise TypeError("Value must be an instance of str")
  49. return codecs.decode(remove_0x_prefix(value), "hex") # type: ignore
  50. def is_bytes(value: Any) -> bool:
  51. return isinstance(value, (bytes,bytearray))
  52. def int_to_big_endian(value: int) -> bytes:
  53. return value.to_bytes((value.bit_length() + 7) // 8 or 1, "big")
  54. def big_endian_to_int(value: bytes) -> int:
  55. return int.from_bytes(value, "big")
  56. # end from eth_utils
  57. class Memoize:
  58. def __init__(self, fn):
  59. self.fn = fn
  60. self.memo = {}
  61. def __call__(self, *args):
  62. if args not in self.memo:
  63. self.memo[args] = self.fn(*args)
  64. return self.memo[args]
  65. TT256 = 2 ** 256
  66. def is_numeric(x): return isinstance(x, int)
  67. def is_string(x): return isinstance(x, bytes)
  68. def to_string(value):
  69. if isinstance(value, bytes):
  70. return value
  71. if isinstance(value, str):
  72. return bytes(value, 'utf-8')
  73. if isinstance(value, int):
  74. return bytes(str(value), 'utf-8')
  75. unicode = str
  76. def encode_int32(v):
  77. return v.to_bytes(32, byteorder='big')
  78. def str_to_bytes(value):
  79. if isinstance(value, bytearray):
  80. value = bytes(value)
  81. if isinstance(value, bytes):
  82. return value
  83. return bytes(value, 'utf-8')
  84. def ascii_chr(n):
  85. return ALL_BYTES[n]
  86. def encode_hex(n):
  87. if isinstance(n, str):
  88. return encode_hex(n.encode('ascii'))
  89. return encode_hex_0x(n)[2:]
  90. def ecrecover_to_pub(rawhash, v, r, s):
  91. result = ecdsa_raw_recover(rawhash, (v, r, s))
  92. if result:
  93. x, y = result
  94. pub = encode_int32(x) + encode_int32(y)
  95. else:
  96. raise ValueError('Invalid VRS')
  97. assert len(pub) == 64
  98. return pub
  99. def ecsign(rawhash, key):
  100. return ecdsa_raw_sign(rawhash, key)
  101. def mk_contract_address(sender, nonce):
  102. return sha3(rlp.encode([normalize_address(sender), nonce]))[12:]
  103. def mk_metropolis_contract_address(sender, initcode):
  104. return sha3(normalize_address(sender) + initcode)[12:]
  105. def sha3(seed):
  106. return sha3_256(to_string(seed))
  107. assert encode_hex(
  108. sha3(b'')) == 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
  109. @Memoize
  110. def privtoaddr(k):
  111. k = normalize_key(k)
  112. x, y = privtopub(k)
  113. return sha3(encode_int32(x) + encode_int32(y))[12:]
  114. def normalize_address(x, allow_blank=False):
  115. if is_numeric(x):
  116. return int_to_addr(x)
  117. if allow_blank and x in {'', b''}:
  118. return b''
  119. if len(x) in (42, 50) and x[:2] in {'0x', b'0x'}:
  120. x = x[2:]
  121. if len(x) in (40, 48):
  122. x = decode_hex(x)
  123. if len(x) == 24:
  124. assert len(x) == 24 and sha3(x[:20])[:4] == x[-4:]
  125. x = x[:20]
  126. if len(x) != 20:
  127. raise Exception("Invalid address format: %r" % x)
  128. return x
  129. def normalize_key(key):
  130. if is_numeric(key):
  131. o = encode_int32(key)
  132. elif len(key) == 32:
  133. o = key
  134. elif len(key) == 64:
  135. o = decode_hex(key)
  136. elif len(key) == 66 and key[:2] == '0x':
  137. o = decode_hex(key[2:])
  138. else:
  139. raise Exception("Invalid key format: %r" % key)
  140. if o == b'\x00' * 32:
  141. raise Exception("Zero privkey invalid")
  142. return o
  143. def int_to_addr(x):
  144. o = [b''] * 20
  145. for i in range(20):
  146. o[19 - i] = ascii_chr(x & 0xff)
  147. x >>= 8
  148. return b''.join(o)
  149. def remove_0x_prefix(s):
  150. return s[2:] if s[:2] in (b'0x', '0x') else s
  151. class Denoms():
  152. def __init__(self):
  153. self.wei = 1
  154. self.babbage = 10 ** 3
  155. self.ada = 10 ** 3
  156. self.kwei = 10 ** 6
  157. self.lovelace = 10 ** 6
  158. self.mwei = 10 ** 6
  159. self.shannon = 10 ** 9
  160. self.gwei = 10 ** 9
  161. self.szabo = 10 ** 12
  162. self.finney = 10 ** 15
  163. self.mether = 10 ** 15
  164. self.ether = 10 ** 18
  165. self.turing = 2 ** 256 - 1
  166. address = Binary.fixed_length(20, allow_empty=True)