def validate_proof(proof: List[dict], hex_target_hash: str, hex_merkle_root: str, is_big_endian: bool = False):
     if is_big_endian:
         hex_merkle_root = NeoData.to_reserve_hex_str(hex_merkle_root)
         hex_target_hash = NeoData.to_reserve_hex_str(hex_target_hash)
     if len(proof) == 0:
         return hex_target_hash == hex_merkle_root
     else:
         hex_proof_hash = hex_target_hash
         for node in proof:
             if is_big_endian:
                 sibling = NeoData.to_reserve_hex_str(node['TargetHash'])
             else:
                 sibling = node['TargetHash']
             try:
                 direction = node['Direction'].lower()
             except KeyError:
                 raise SDKException(ErrorCode.other_error('Invalid proof'))
             if direction == 'left':
                 value = bytes.fromhex('01' + sibling + hex_proof_hash)
                 hex_proof_hash = Digest.sha256(value, is_hex=True)
             elif direction == 'right':
                 value = bytes.fromhex('01' + hex_proof_hash + sibling)
                 hex_proof_hash = Digest.sha256(value, is_hex=True)
             else:
                 raise SDKException(ErrorCode.other_error('Invalid proof.'))
         return hex_proof_hash == hex_merkle_root
Пример #2
0
 def new_transfer_multi_tx(self, transfer_list: list,
                           payer: Union[str, bytes,
                                        Address], gas_price: int,
                           gas_limit: int) -> InvokeTransaction:
     """
     This interface is used to generate a transaction which can
     transfer amount of token from from-account to to-account multiple times.
     """
     func = NeoInvokeFunction('transferMulti')
     for index, item in enumerate(transfer_list):
         if not isinstance(item[2], int):
             raise SDKException(
                 ErrorCode.param_err(
                     'the data type of value should be int.'))
         if item[2] < 0:
             raise SDKException(
                 ErrorCode.param_err(
                     'the value should be equal or great than 0.'))
         transfer_list[index] = [
             Address.b58decode(item[0]),
             Address.b58decode(item[1]), item[2]
         ]
     for item in transfer_list:
         func.add_params_value(item)
     params = InvokeTransaction.generate_neo_vm_invoke_code(
         self._contract_address, func)
     tx = InvokeTransaction(payer, gas_price, gas_limit, params)
     return tx
Пример #3
0
 async def send_neo_vm_transaction(self,
                                   contract_address: str or bytes
                                   or bytearray,
                                   signer: Account or None,
                                   payer: Account or None,
                                   gas_price: int,
                                   gas_limit: int,
                                   func: AbiFunction or NeoInvokeFunction,
                                   is_full: bool = False):
     if isinstance(func, AbiFunction):
         params = BuildParams.serialize_abi_function(func)
     elif isinstance(func, NeoInvokeFunction):
         params = func.create_invoke_code()
     else:
         raise SDKException(
             ErrorCode.other_error('the type of func is error.'))
     contract_address = ensure_bytearray_contract_address(contract_address)
     params.append(0x67)
     for i in contract_address:
         params.append(i)
     if payer is None:
         raise SDKException(ErrorCode.param_err('payer account is None.'))
     tx = Transaction(0, 0xd1, gas_price, gas_limit,
                      payer.get_address_bytes(), params)
     tx.sign_transaction(payer)
     if isinstance(
             signer, Account
     ) and signer.get_address_base58() != payer.get_address_base58():
         tx.add_sign_transaction(signer)
     return await self.send_raw_transaction(tx, is_full)
Пример #4
0
 async def connect(self):
     try:
         self.__ws_client = await client.connect(self.__url)
     except ConnectionAbortedError as e:
         raise SDKException(ErrorCode.other_error(e.args[1])) from None
     except socket.gaierror as e:
         raise SDKException(ErrorCode.other_error(e.args[1])) from None
Пример #5
0
 def add_multi_sign_transaction(self, m: int, pub_keys: List[bytes]
                                or List[str], signer: Account):
     """
     This interface is used to generate an Transaction object which has multi signature.
     """
     for index, pk in enumerate(pub_keys):
         if isinstance(pk, str):
             pub_keys[index] = pk.encode('ascii')
     pub_keys = ProgramBuilder.sort_public_keys(pub_keys)
     tx_hash = self.hash256()
     sig_data = signer.generate_signature(tx_hash)
     if self.sig_list is None or len(self.sig_list) == 0:
         self.sig_list = []
     elif len(self.sig_list) >= TX_MAX_SIG_SIZE:
         raise SDKException(
             ErrorCode.param_err(
                 'the number of transaction signatures should not be over 16'
             ))
     else:
         for i in range(len(self.sig_list)):
             if self.sig_list[i].public_keys == pub_keys:
                 if len(self.sig_list[i].sig_data) + 1 > len(pub_keys):
                     raise SDKException(
                         ErrorCode.param_err('too more sigData'))
                 if self.sig_list[i].m != m:
                     raise SDKException(ErrorCode.param_err('M error'))
                 self.sig_list[i].sig_data.append(sig_data)
                 return
     sig = Sig(pub_keys, m, [sig_data])
     self.sig_list.append(sig)
Пример #6
0
 def get_account_data_by_b58_address(self, b58_address: str) -> AccountData:
     if not isinstance(b58_address, str):
         raise SDKException(ErrorCode.require_str_params)
     for acct in self.wallet_in_mem.accounts:
         if not isinstance(acct, AccountData):
             raise SDKException(ErrorCode.other_error('Invalid account data in memory.'))
         if acct.b58_address == b58_address:
             return acct
     raise SDKException(ErrorCode.other_error(f'Get account {b58_address} failed.'))
Пример #7
0
 def __init__(self, script_hash: Union[bytes, bytearray]):
     if not isinstance(script_hash, bytes):
         try:
             script_hash = bytes(script_hash)
         except TypeError:
             raise SDKException(ErrorCode.other_error('Invalid script hash.'))
     if len(script_hash) != 20:
         raise SDKException(ErrorCode.other_error('Invalid script hash.'))
     self.ZERO = script_hash
Пример #8
0
 def compare_pubkey(pub_key: bytes):
     if not isinstance(pub_key, bytes):
         raise SDKException(ErrorCode.other_error('Invalid key.'))
     if KeyType.from_pubkey(pub_key) == KeyType.SM2:
         raise SDKException(ErrorCode.other_error('Unsupported key type'))
     elif KeyType.from_pubkey(pub_key) == KeyType.ECDSA:
         x = pub_key[1:]
         return util.string_to_number(x)
     else:
         return str(pub_key)
Пример #9
0
 async def get_memory_pool_tx_state(self, tx_hash: str, is_full: bool = False):
     payload = self.generate_json_rpc_payload(RpcMethod.GET_MEM_POOL_TX_STATE, [tx_hash])
     response = await self.__post(payload)
     if response.get('result', '') == '':
         raise SDKException(ErrorCode.invalid_tx_hash(tx_hash))
     if response.get('error', -1) != 0:
         raise SDKException(ErrorCode.other_error(response.get('result', '')))
     if is_full:
         return response
     return response['result']['State']
Пример #10
0
 def get_control_info_by_index(self, ont_id: str, index: int) -> Control:
     if not isinstance(ont_id, str):
         raise SDKException(ErrorCode.require_str_params)
     if not ont_id.startswith(DID_ONT):
         raise SDKException(ErrorCode.invalid_ont_id_format(ont_id))
     identity = self.get_identity_by_ont_id(ont_id)
     try:
         ctrl = identity.controls[index]
     except IndexError:
         raise SDKException(ErrorCode.other_error(f'Get {ont_id}\'s control account failed.'))
     return ctrl
Пример #11
0
 def get_public_key_by_hex_private_key(private_key: str):
     if not isinstance(private_key, str):
         raise SDKException(
             ErrorCode.other_error(
                 'The type of private key should be hexadecimal str.'))
     if len(private_key) != 64:
         raise SDKException(
             ErrorCode.other_error(
                 'The length of private key should be 64 bytes.'))
     private_key = bytes.fromhex(private_key)
     point_str = ECIES.get_public_key_by_bytes_private_key(private_key)
     return point_str.hex()
Пример #12
0
 def to_int(hex_str: str) -> int:
     if len(hex_str) == 0:
         return 0
     try:
         array = bytearray.fromhex(hex_str)
     except ValueError as e:
         raise SDKException(ErrorCode.other_error(e.args[0]))
     array.reverse()
     try:
         num = int(bytearray.hex(array), 16)
     except ValueError as e:
         raise SDKException(ErrorCode.other_error(e.args[0]))
     return num
Пример #13
0
 def __post(self, method, b58_address: str or None, pwd: str or None, params):
     payload = dict(qid=str(randint(0, maxsize)), method=method, params=params)
     if isinstance(b58_address, str):
         payload['account'] = b58_address
     if isinstance(pwd, str):
         payload['pwd'] = pwd
     try:
         response = requests.post(self.__url, json=payload, headers=self.__header, timeout=10)
     except requests.exceptions.MissingSchema as e:
         raise SDKException(ErrorCode.connect_err(e.args[0])) from None
     except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError):
         raise SDKException(ErrorCode.other_error(''.join(['ConnectionError: ', self.__url]))) from None
     except requests.exceptions.ReadTimeout:
         raise SDKException(ErrorCode.other_error(''.join(['ReadTimeout: ', self.__url]))) from None
     try:
         content = response.content.decode('utf-8')
     except Exception as e:
         raise SDKException(ErrorCode.other_error(e.args[0])) from None
     if response.status_code != 200:
         raise SDKException(ErrorCode.other_error(content))
     try:
         content = json.loads(content)
     except json.decoder.JSONDecodeError as e:
         raise SDKException(ErrorCode.other_error(e.args[0])) from None
     if content['error_code'] != 0:
         if content['error_info'] != '':
             raise SDKException(ErrorCode.other_error(content['error_info']))
         else:
             raise SDKException(ErrorCode.other_error(content['result']))
     return content
Пример #14
0
 async def get_contract(self, hex_contract_address: str, is_full: bool = False) -> dict:
     """
     This interface is used to get the information of smart contract based on the specified hexadecimal hash value.
     """
     if not isinstance(hex_contract_address, str):
         raise SDKException(ErrorCode.param_err('a hexadecimal contract address is required.'))
     if len(hex_contract_address) != 40:
         raise SDKException(ErrorCode.param_err('the length of the contract address should be 40 bytes.'))
     payload = self.generate_json_rpc_payload(RpcMethod.GET_SMART_CONTRACT, [hex_contract_address, 1])
     response = await self.__post(payload)
     if is_full:
         return response
     result = response['result']
     return dict() if result is None else result
Пример #15
0
 def get_gas_consumed(event: dict):
     Event.__check_event(event)
     try:
         return event['GasConsumed']
     except KeyError:
         raise SDKException(
             ErrorCode.other_error('Gas consumed not found in event'))
Пример #16
0
 def get_state(event: dict):
     Event.__check_event(event)
     try:
         return event['State']
     except KeyError:
         raise SDKException(
             ErrorCode.other_error('State not found in event'))
Пример #17
0
 def get_tx_hash(event: dict):
     Event.__check_event(event)
     try:
         return event['TxHash']
     except KeyError:
         raise SDKException(
             ErrorCode.other_error('TxHash not found in event'))
Пример #18
0
 def from_signature_scheme(scheme: SignatureScheme):
     if scheme == SignatureScheme.SHA224withECDSA:
         return KeyType.ECDSA
     elif scheme == SignatureScheme.SHA256withECDSA:
         return KeyType.ECDSA
     elif scheme == SignatureScheme.SHA384withECDSA:
         return KeyType.ECDSA
     elif scheme == SignatureScheme.SHA384withECDSA:
         return KeyType.ECDSA
     elif scheme == SignatureScheme.SHA512withECDSA:
         return KeyType.ECDSA
     elif scheme == SignatureScheme.SHA3_224withECDSA:
         return KeyType.ECDSA
     elif scheme == SignatureScheme.SHA3_256withECDSA:
         return KeyType.ECDSA
     elif scheme == SignatureScheme.SHA3_384withECDSA:
         return KeyType.ECDSA
     elif scheme == SignatureScheme.SHA3_512withECDSA:
         return KeyType.ECDSA
     elif scheme == SignatureScheme.RIPEMD160withECDSA:
         return KeyType.ECDSA
     elif scheme == SignatureScheme.SM3withSM2:
         return KeyType.SM2
     else:
         raise SDKException(
             ErrorCode.other_error('invalid signature scheme.'))
Пример #19
0
 def hex_contract_address(self, hex_contract_address):
     if isinstance(hex_contract_address,
                   str) and len(hex_contract_address) == 40:
         self.__hex_contract_address = hex_contract_address
     else:
         raise SDKException(
             ErrorCode.invalid_contract_address(hex_contract_address))
Пример #20
0
 def to_utf8_str(ascii_str: str) -> str:
     try:
         utf8_str = bytes.fromhex(ascii_str)
         utf8_str = utf8_str.decode('utf-8')
     except ValueError as e:
         raise SDKException(ErrorCode.other_error(e.args[0]))
     return utf8_str
Пример #21
0
 async def __send_recv(self, msg: dict, is_full: bool):
     if self.__ws_client is None or self.__ws_client.closed:
         try:
             await self.connect()
         except TimeoutError:
             raise SDKException(ErrorCode.connect_timeout(
                 self.__url)) from None
     await self.__ws_client.send(json.dumps(msg))
     response = await self.__ws_client.recv()
     response = json.loads(response)
     if is_full:
         return response
     if response['Error'] != 0:
         raise SDKException(
             ErrorCode.other_error(response.get('Result', '')))
     return response.get('Result', dict())
Пример #22
0
 def __init__(self, wallet_path: str = '', scheme: SignatureScheme = SignatureScheme.SHA256withECDSA):
     if not isinstance(scheme, SignatureScheme):
         raise SDKException(ErrorCode.other_error('Invalid signature scheme.'))
     self.scheme = scheme
     self.wallet_file = WalletData()
     self.wallet_in_mem = WalletData()
     self.__wallet_path = wallet_path
Пример #23
0
 def __post(self, url: str, data: str):
     try:
         response = requests.post(url, data=data, timeout=10)
     except requests.exceptions.MissingSchema as e:
         raise SDKException(ErrorCode.connect_err(e.args[0]))
     except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError):
         raise SDKException(ErrorCode.connect_timeout(self._url)) from None
     if response.status_code != 200:
         raise SDKException(ErrorCode.other_error(response.content.decode('utf-8')))
     try:
         response = json.loads(response.content.decode('utf-8'))
     except json.decoder.JSONDecodeError as e:
         raise SDKException(ErrorCode.other_error(e.args[0]))
     if response['Error'] != 0:
         raise SDKException(ErrorCode.other_error(response['Result']))
     return response
Пример #24
0
 def get_control_info_by_b58_address(self, ont_id: str, b58_address: str) -> Control:
     WalletManager.__check_ont_id(ont_id)
     identity = self.get_identity_by_ont_id(ont_id)
     for ctrl in identity.controls:
         if ctrl.b58_address == b58_address:
             return ctrl
     raise SDKException(ErrorCode.other_error(f'Get account {b58_address} failed.'))
Пример #25
0
 def __deserialize_stack_item(reader: BinaryReader) -> dict or bytearray:
     param_type = reader.read_byte()
     if param_type == BuildParams.Type.bytearray_type.value:
         b = reader.read_var_bytes()
         return b
     elif param_type == BuildParams.Type.bool_type.value:
         return reader.read_bool()
     elif param_type == BuildParams.Type.int_type.value:
         b = reader.read_var_bytes()
         return NeoData.__big_int_from_bytes(bytearray(b))
     elif param_type == BuildParams.Type.struct_type.value or param_type == BuildParams.Type.array_type.value:
         count = reader.read_var_int()
         item_list = list()
         for _ in range(count):
             item = NeoData.__deserialize_stack_item(reader)
             item_list.append(item)
         if param_type == BuildParams.Type.struct_type.value:
             return Struct(item_list)
         return item_list
     elif param_type == BuildParams.Type.dict_type.value:
         count = reader.read_var_int()
         item_dict = dict()
         for _ in range(count):
             key = NeoData.__deserialize_stack_item(reader)
             value = NeoData.__deserialize_stack_item(reader)
             item_dict[key] = value
         return item_dict
     else:
         raise SDKException(ErrorCode.other_error('type error'))
Пример #26
0
 def to_bytes_address(hex_address: str) -> bytes:
     try:
         bytes_address = bytes.fromhex(hex_address)
     except ValueError as e:
         raise SDKException(ErrorCode.other_error(e.args[0]))
     address = Address(bytes_address)
     return address.to_bytes()
Пример #27
0
 def push_bool(self, value: bool):
     if not isinstance(value, bool):
         raise SDKException(ErrorCode.other_error('invalid data'))
     if value:
         self.write_bytes(WASM_TRUE)
     else:
         self.write_bytes(WASM_FALSE)
Пример #28
0
 def write_var_uint(self, value: int):
     if not isinstance(value, int):
         raise SDKException(ErrorCode.other_error('invalid data'))
     if value < 0:
         raise SDKException(ErrorCode.other_error('invalid data'))
     elif value < 0xFD:
         self.write_bytes(value.to_bytes(length=1, byteorder='little', signed=False))
     elif value <= 0xFFFF:
         self.write_bytes(b'\xFD')
         self.write_bytes(value.to_bytes(length=2, byteorder='little', signed=False))
     elif value <= 0xFFFFFFFF:
         self.write_bytes(b'\xFE')
         self.write_bytes(value.to_bytes(length=4, byteorder='little', signed=False))
     else:
         self.write_bytes(b'\xFF')
         self.write_bytes(value.to_bytes(length=8, byteorder='little', signed=False))
Пример #29
0
 def add_identity(self, identity: Identity):
     for item in self.identities:
         if item.ont_id == identity.ont_id:
             raise SDKException(
                 ErrorCode.other_error(
                     'add identity failed, OntId conflict.'))
     self.identities.append(identity)
Пример #30
0
    def get_gcm_decoded_private_key(encrypted_key_str: str, password: str, b58_address: str, salt: str, n: int,
                                    scheme: SignatureScheme) -> str:
        """
        This interface is used to decrypt an private key which has been encrypted.

        :param encrypted_key_str: an gcm encrypted private key in the form of string.
        :param password: the secret pass phrase to generate the keys from.
        :param b58_address: a base58 encode address which should be correspond with the private key.
        :param salt: a string to use for better protection from dictionary attacks.
        :param n: CPU/memory cost parameter.
        :param scheme: the signature scheme.
        :return: a private key in the form of string.
        """
        r = 8
        p = 8
        dk_len = 64
        scrypt = Scrypt(n, r, p, dk_len)
        derived_key = scrypt.generate_kd(password, salt)
        iv = derived_key[0:12]
        key = derived_key[32:64]
        encrypted_key = base64.b64decode(encrypted_key_str).hex()
        mac_tag = bytes.fromhex(encrypted_key[64:96])
        cipher_text = bytes.fromhex(encrypted_key[0:64])
        private_key = AESHandler.aes_gcm_decrypt_with_iv(cipher_text, b58_address.encode(), mac_tag, key, iv)
        if len(private_key) == 0:
            raise SDKException(ErrorCode.decrypt_encrypted_private_key_error)
        acct = Account(private_key, scheme)
        if acct.get_address().b58encode() != b58_address:
            raise SDKException(ErrorCode.other_error('Address error.'))
        return private_key.hex()