def validate_blk_proof(self, is_big_endian: bool = False) -> bool: if self.__blk_proof.get('Type', '') != 'MerkleProof': raise SDKException(ErrorCode.invalid_blk_proof) try: tx_hash = self.__blk_proof['TxnHash'] except KeyError: raise SDKException(ErrorCode.invalid_blk_proof) proof_node = self.__blk_proof.get('Nodes', list()) merkle_root = self.__blk_proof.get('MerkleRoot', '') try: blk_height = self.__blk_proof['BlockHeight'] except KeyError: raise SDKException(ErrorCode.invalid_blk_proof) block = self.__sdk.default_network.get_block_by_height(blk_height) tx_list = block.get('Transactions', list()) tx_exist = False for tx in tx_list: if tx.get('Hash', '') == tx_hash: tx_exist = True break if not tx_exist: return False blk_head = block.get('Header', dict()) target_hash = blk_head.get('TransactionsRoot', '') try: result = MerkleVerifier.validate_proof(proof_node, target_hash, merkle_root, is_big_endian) except SDKException: result = False return result
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)
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()
def controls(self, ctrl_lst: List[Control]): if not isinstance(ctrl_lst, list): raise SDKException(ErrorCode.require_list_params) for ctrl in ctrl_lst: if not isinstance(ctrl, Control): raise SDKException(ErrorCode.require_control_params) self.__controls = ctrl_lst
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
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)
def from_str(str_alg: str): if not isinstance(str_alg, str): raise SDKException(ErrorCode.require_str_params) if str_alg == 'ES224' or str_alg == 'ONT-ES224': return ClmAlg.ES224 elif str_alg == 'ES256' or str_alg == 'ONT-ES256': return ClmAlg.ES256 elif str_alg == 'ES384' or str_alg == 'ONT-ES384': return ClmAlg.ES384 elif str_alg == 'ES512' or str_alg == 'ONT-ES512': return ClmAlg.ES512 elif str_alg == 'ES3-224' or str_alg == 'ONT-ES3-224': return ClmAlg.ES3_224 elif str_alg == 'ES3-256' or str_alg == 'ONT-ES3-256': return ClmAlg.ES3_256 elif str_alg == 'ES3-384' or str_alg == 'ONT-ES3-384': return ClmAlg.ES3_384 elif str_alg == 'ES3-512' or str_alg == 'ONT-ES3-512': return ClmAlg.ES3_512 elif str_alg == 'ER160' or str_alg == 'ONT-ER160': return ClmAlg.ER160 elif str_alg == 'SM' or str_alg == 'ONT-SM': return ClmAlg.SM elif str_alg == 'EDS512' or str_alg == 'ONT-EDS512': return ClmAlg.EDS512 else: raise SDKException(ErrorCode.invalid_claim_alg)
def add_control_by_hex_private_key(self, ont_id: str, password: str, hex_private_key: str) -> Account: WalletManager.__check_ont_id(ont_id) if not isinstance(password, str): raise SDKException(ErrorCode.require_str_params) if not isinstance(hex_private_key, str): raise SDKException(ErrorCode.require_str_params) return self.__add_control(ont_id, password, hex_private_key)
def from_claim_alg(alg: str): if not isinstance(alg, str): raise SDKException(ErrorCode.require_str_params) if alg == 'ES224' or alg == 'ONT-ES224': return SignatureScheme.SHA224withECDSA elif alg == 'ES256' or alg == 'ONT-ES256': return SignatureScheme.SHA256withECDSA elif alg == 'ES384' or alg == 'ONT-ES384': return SignatureScheme.SHA384withECDSA elif alg == 'ES512' or alg == 'ONT-ES512': return SignatureScheme.SHA512withECDSA elif alg == 'ES3-224' or alg == 'ONT-ES3-224': return SignatureScheme.SHA3_224withECDSA elif alg == 'ES3-256' or alg == 'ONT-ES3-256': return SignatureScheme.SHA3_256withECDSA elif alg == 'ES3-384' or alg == 'ONT-ES3-384': return SignatureScheme.SHA3_384withECDSA elif alg == 'ER160' or alg == 'ONT-ER160': return SignatureScheme.RIPEMD160withECDSA elif alg == 'SM' or alg == 'ONT-SM': return SignatureScheme.SM3withSM2 elif alg == 'EDS512' or alg == 'ONT-EDS512': return SignatureScheme.EDDSAwithSHA256 else: raise SDKException(ErrorCode.unknown_asymmetric_key_type)
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
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
def kid(self, kid: str): if not isinstance(kid, str): raise SDKException(ErrorCode.invalid_claim_head_params) if 'did:ont:' not in kid: raise SDKException(ErrorCode.invalid_claim_head_params) if '#keys-' not in kid: raise SDKException(ErrorCode.invalid_claim_head_params) self.__kid = kid
def wrapper(*args, **kwargs): bound_values = sig.bind(*args, **kwargs) ont_id = bound_values.arguments.get('ont_id') 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)) return func(*args, **kwargs)
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
def from_str_type(str_type: str): if not isinstance(str_type, str): raise SDKException(ErrorCode.require_str_params) if str_type == 'JWT': return ClmType.raw_claim elif str_type == 'JWT-X': return ClmType.witness_claim else: raise SDKException(ErrorCode.invalid_claim_type)
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.'))
def test_sdk_exception(self): try: raise SDKException(ErrorCode.param_error) except SDKException as e: self.assertEqual('param error', e.args[1]) try: raise SDKException(ErrorCode.asset_name_error) except SDKException as e: self.assertEqual('OntAsset Error, asset name error', e.args[1])
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']
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)
def create_wallet_file(self, wallet_path: str = ''): if not isinstance(wallet_path, str): raise SDKException(ErrorCode.require_str_params) if wallet_path != '': self.__wallet_path = wallet_path if not path.isfile(self.__wallet_path): self.wallet_in_mem.create_time = datetime.today().strftime("%Y-%m-%d %H:%M:%S") self.save() else: raise SDKException(ErrorCode.other_error('Wallet file has existed.'))
def from_json(self, json_blk_proof: str, is_big_endian: bool = False): if not isinstance(json_blk_proof, str): raise SDKException(ErrorCode.require_str_params) try: dict_blk_proof = json.loads(json_blk_proof) except json.decoder.JSONDecodeError: raise SDKException(ErrorCode.invalid_b64_claim_data) proof = BlockchainProof(self.__sdk) proof.proof = dict_blk_proof, is_big_endian return proof
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
def from_json(json_head: str): if not isinstance(json_head, str): raise SDKException(ErrorCode.require_str_params) dict_head = json.loads(json_head) try: alg = ClmAlg.from_str(dict_head['alg']) typ = ClmType.from_str_type(dict_head['typ']) head = Header(dict_head['kid'], alg, typ) except KeyError: raise SDKException(ErrorCode.invalid_b64_claim_data) return head
def from_str_type(str_type: str): if not isinstance(str_type, str): raise SDKException(ErrorCode.require_str_params) if str_type == 'ECDSA': return KeyType.ECDSA elif str_type == 'SM2': return KeyType.SM2 elif str_type == 'EDDSA': return KeyType.ECDSA else: raise SDKException(ErrorCode.unknown_asymmetric_key_type)
def __init__(self, key, chain_code: bytes, index: int, depth: int, parent_fingerprint: bytes): if index < 0 or index > MAX_INDEX: raise SDKException(ErrorCode.hd_index_out_of_range) if not isinstance(chain_code, bytes): raise SDKException(ErrorCode.require_bytes_params) if depth == 0: parent_fingerprint = MASTER_KEY_FINGERPRINT self._key = key self._chain_code = chain_code self._depth = depth self._index = index self._parent_fingerprint = to_bytes(parent_fingerprint)
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()
def get_default_account_data(self) -> AccountData: """ This interface is used to get the default account in WalletManager. :return: an AccountData object that contain all the information of a default account. """ 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.is_default: return acct raise SDKException(ErrorCode.get_default_account_err)
def open_wallet(self, wallet_path: str = '', is_create: bool = True): if not isinstance(wallet_path, str): raise SDKException(ErrorCode.require_str_params) if wallet_path != '': self.__wallet_path = wallet_path if is_create and not path.isfile(self.__wallet_path): self.create_wallet_file() if not path.isfile(self.__wallet_path): raise SDKException(ErrorCode.invalid_wallet_path(self.__wallet_path)) self.wallet_file = self.load_file() self.wallet_in_mem = copy.deepcopy(self.wallet_file) return self.wallet_file
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
def __init__(self, ont_id: str = '', label: str = '', lock: bool = False, controls: List[Control] = None, is_default=False): if controls is None: controls = list() if not isinstance(ont_id, str): raise SDKException(ErrorCode.require_str_params) if len(ont_id) != 0 and not ont_id.startswith(DID_ONT): raise SDKException(ErrorCode.invalid_ont_id_format(ont_id)) self.__ont_id = ont_id self.label = label self.lock = lock self.__controls = controls self.is_default = is_default