Пример #1
0
 def process_sign_typeddata(self, data_bin):
     """Process a WalletConnect eth_signTypedData call"""
     data_obj = json.loads(data_bin)
     chain_id = None
     if "domain" in data_obj and "chainId" in data_obj["domain"]:
         chain_id = data_obj["domain"]["chainId"]
         if isinstance(chain_id, str) and chain_id.startswith("eip155:"):
             chain_id = int(chain_id[7:])
     # Silent ignore when chain ids mismatch
     if chain_id is not None and self.chainID != data_obj["domain"]["chainId"]:
         logger.debug("Wrong chain id in signedTypedData")
         return None
     hash_domain, hash_data = typed_sign_hash(data_obj)
     sign_request = (
         "WalletConnect signature request :\n\n"
         f"- Data to sign (typed) :\n"
         f"{print_text_query(data_obj)}"
         f"\n - Hash domain (hex) :\n"
         f" 0x{hash_domain.hex().upper()}\n"
         f"\n - Hash data (hex) :\n"
         f" 0x{hash_data.hex().upper()}\n"
     )
     if self.current_device.has_screen:
         sign_request += USER_SCREEN
     elif self.current_device.has_hardware_button:
         sign_request += USER_BUTTON
     if self.confirm_callback(sign_request):
         if self.current_device.has_screen:
             v, r, s = self.current_device.sign_eip712(hash_domain, hash_data)
             return self.eth.encode_vrs(v, r, s)
         # else
         hash_sign = sha3(EIP712_HEADER + hash_domain + hash_data)
         der_signature = self.current_device.sign(hash_sign)
         return self.eth.encode_datasign(hash_sign, der_signature)
Пример #2
0
 def process_sign_message(self, data_hex):
     """Process a WalletConnect personal_sign and eth_sign call"""
     # sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))
     data_bin = bytes.fromhex(data_hex[2:])
     msg_header = MESSAGE_HEADER + str(len(data_bin)).encode("ascii")
     sign_request = (
         "WalletConnect signature request :\n\n"
         f"- Data to sign (hex) :\n"
         f"- {data_hex}\n"
         f"\n Data to sign (ASCII/UTF8) :\n"
     )
     try:
         sign_request += f" {data_bin.decode('utf8')}\n"
     except UnicodeDecodeError:
         sign_request += " <can't decode sign data to text>"
     if self.current_device.has_screen:
         hash2_data = sha2(data_bin).hex().upper()
         sign_request += f"\n Hash data to sign (hex) :\n {hash2_data}\n"
         sign_request += USER_SCREEN
     elif self.current_device.has_hardware_button:
         sign_request += USER_BUTTON
     if self.confirm_callback(sign_request):
         if self.current_device.has_screen:
             v, r, s = self.current_device.sign_message(data_bin)
             return self.eth.encode_vrs(v, r, s)
         # else
         hash_sign = sha3(msg_header + data_bin)
         der_signature = self.current_device.sign(hash_sign)
         return self.eth.encode_datasign(hash_sign, der_signature)
Пример #3
0
 def __init__(self, pubkey, network, api, chainID, ERC20=None):
     self.pubkey = pubkey
     key_hash = sha3(self.pubkey[1:])
     self.address = format_checksum_address(key_hash.hex()[-40:])
     self.ERC20 = ERC20
     self.api = api
     self.decimals = self.get_decimals()
     self.token_symbol = self.get_symbol()
     self.chainID = chainID
Пример #4
0
def format_checksum_address(addr):
    # Format an ETH address with checksum (without 0x)
    addr = addr.lower()
    addr_sha3hash = sha3(addr.encode("ascii")).hex()
    cs_address = ""
    for idx, ci in enumerate(addr):
        if ci in "abcdef":
            cs_address += ci.upper() if int(addr_sha3hash[idx], 16) >= 8 else ci
            continue
        cs_address += ci
    return cs_address
Пример #5
0
 def prepare(self, toaddr, paymentvalue, gprice, glimit, data=bytearray(b"")):
     """Build a transaction to be signed.
     toaddr in hex without 0x
     value in wei, gprice in Wei
     """
     if self.ERC20:
         maxspendable = self.getbalance(False)
         balance_eth = self.getbalance()
         if balance_eth < (gprice * glimit):
             raise NotEnoughTokens("Not enough native ETH funding for the tx fee")
     else:
         maxspendable = self.getbalance() - (gprice * glimit)
     if paymentvalue > maxspendable or paymentvalue < 0:
         if self.ERC20:
             sym = self.token_symbol
         else:
             sym = "native ETH"
         raise NotEnoughTokens(f"Not enough {sym} tokens for the tx")
     self.nonce = int2bytearray(self.getnonce())
     self.gasprice = int2bytearray(gprice)
     self.startgas = int2bytearray(glimit)
     if self.ERC20:
         self.to = bytearray.fromhex(self.ERC20[2:])
         self.value = int2bytearray(int(0))
         self.data = bytearray.fromhex(TRANSFERT_FUNCTION + "00" * 12 + toaddr) + uint256(
             paymentvalue
         )
     else:
         self.to = bytearray.fromhex(toaddr)
         self.value = int2bytearray(int(paymentvalue))
         self.data = data
     v = int2bytearray(self.chainID)
     r = int2bytearray(0)
     s = int2bytearray(0)
     signing_tx = rlp_encode(
         [
             self.nonce,
             self.gasprice,
             self.startgas,
             self.to,
             self.value,
             self.data,
             v,
             r,
             s,
         ]
     )
     self.datahash = sha3(signing_tx)
     return (signing_tx, self.datahash)
Пример #6
0
def full_message_digest(domain_hash, digest_data):
    return sha3(b"\x19\x01" + domain_hash + digest_data)
Пример #7
0
def encode_value(vtype, value, go):
    """Encode a given value in Python bytes."""
    if vtype == "bool":
        if not isinstance(value, bool):
            raise ValueError("bool type is not a bool value.")
        return uint256(1) if value else uint256(0)
    if vtype == "address":
        if not isinstance(value, str):
            raise ValueError("address type is not a str value.")
        if len(value) != 42 or value[:2] != "0x":
            raise ValueError("address is not a 0x hex value.")
        try:
            int_value = int(value[2:], 16)
        except ValueError:
            raise ValueError("address is not a 0x hex value.")
        return uint256(int_value)
    if vtype in int_types or vtype in uint_types:
        if isinstance(value, str):
            # Fallback for dapp encoding uint as string
            try:
                value = int(value, 10)
            except ValueError:
                raise ValueError(vtype + " is not a valid string.")
        if not isinstance(value, int):
            raise ValueError(vtype + " type is not a int nor str value.")
        if value >= 0:
            intval_bin = uint256(value)
        else:
            intval_bin = uint256(2**256 + value)
        return intval_bin
    if vtype in bytes_types:
        if not isinstance(value, str):
            raise ValueError("bytes type is not a str value.")
        if value[:2] != "0x":
            raise ValueError("bytes is not a 0x hex value.")
        try:
            out = bytes.fromhex(value[2:])
        except ValueError:
            raise ValueError("bytes is not a 0x hex value.")
        while len(out) < 32:
            out += b"\0"
        return out
    if vtype == "bytes":
        if not isinstance(value, str):
            raise ValueError("bytes type is not a str value.")
        if value[:2] != "0x":
            raise ValueError("bytes is not a 0x hex value.")
        try:
            out = bytes.fromhex(value[2:])
        except ValueError:
            raise ValueError("bytes is not a 0x hex value.")
        return sha3(out)
    if vtype == "string":
        if not isinstance(value, str):
            raise ValueError("string type is not a str value.")
        return sha3(value.encode("utf8"))
    if vtype.endswith("[]"):
        if not isinstance(value, list):
            raise ValueError("array type is not a list value.")
        elements = [encode_value(vtype[:-2], val, go) for val in value]
        return sha3(b"".join(elements))
    # Should be a struct finally
    if not isinstance(value, dict):
        raise ValueError("struct type is not a dict value.")
    return hash_struct(vtype, go, value)
Пример #8
0
def type_hash(name, types_obj):
    """Compute typeHash (hash of the encodeType type string)."""
    subtypes_list = collect_sub_types(name, types_obj)
    subtypes_list.sort()
    types_list = [name, *subtypes_list]
    return sha3(encode_types(types_list, types_obj).encode("utf8"))
Пример #9
0
def hash_struct(name, types_obj, data_obj):
    """Compute the hashStruct = keccak256(typeHash ‖ encodeData(s))."""
    return sha3(
        type_hash(name, types_obj) + encode_data(name, types_obj, data_obj))