def __post(url, payload): header = {'Content-type': 'application/json'} try: response = requests.post(url, json=payload, headers=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, requests.exceptions.ReadTimeout): raise SDKException(ErrorCode.connect_timeout(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'] != 0: if content['result'] != '': raise SDKException(ErrorCode.other_error( content['result'])) from None else: raise SDKException(ErrorCode.other_error( content['desc'])) from None return content
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
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 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 __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 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 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 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 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 __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
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'))
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)
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'))
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'))
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'))
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
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.'))
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
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)
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.'))
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 generate_blk_proof(self, commit_tx_hash: str, is_big_endian: bool = True, hex_contract_address: str = ''): if len(hex_contract_address) == 0: hex_contract_address = self.__sdk.neo_vm.claim_record( ).hex_contract_address count = 0 while True: try: merkle_proof = self.__sdk.default_network.get_merkle_proof( commit_tx_hash) if isinstance(merkle_proof, dict): break except SDKException as e: if count > 5 or 'INVALID PARAMS' not in e.args[1]: raise e sleep(6) count += 1 tx_block_height = merkle_proof['BlockHeight'] current_block_height = merkle_proof['CurBlockHeight'] target_hash = merkle_proof['TransactionsRoot'] merkle_root = merkle_proof['CurBlockRoot'] target_hash_list = merkle_proof['TargetHashes'] proof_node = MerkleVerifier.get_proof(tx_block_height, target_hash_list, current_block_height) result = MerkleVerifier.validate_proof(proof_node, target_hash, merkle_root, is_big_endian) if not result: raise SDKException(ErrorCode.other_error('Invalid merkle proof')) self.__blk_proof.set_proof(commit_tx_hash, hex_contract_address, tx_block_height, merkle_root, proof_node) return self.__blk_proof
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()
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))
def decrypt_with_cbc_mode(cipher_text: bytes, private_key: bytes, iv: bytes, encode_g_tilde: bytes) -> bytes: aes_key = ECIES.generate_decrypt_aes_key(private_key, encode_g_tilde) try: plain_text = AESHandler.aes_cbc_decrypt(cipher_text, iv, aes_key) except ValueError as e: raise SDKException(ErrorCode.other_error(e.args[0])) return plain_text
def get_notify_list(event: dict): Event.__check_event(event) try: return event['Notify'] except KeyError: raise SDKException( ErrorCode.other_error( f'Notify not found in {event}')) from None
def generate_signature(self, iss: Account, verify_kid: bool = True): if not isinstance(self.__head, Header) or not isinstance( self.__payload, Payload): raise SDKException( ErrorCode.other_error('Please set claim parameters first.')) if verify_kid: key_index = int(self.__head.kid.split('-')[1]) result = self.__sdk.native_vm.ont_id().verify_signature( iss.get_ont_id(), key_index, iss) if not result: raise SDKException( ErrorCode.other_error('Issuer account error.')) b64_head = self.__head.to_base64() b64_payload = self.__payload.to_base64() msg = f'{b64_head}.{b64_payload}'.encode('utf-8') self.__signature = iss.generate_signature(msg) return self.__signature
async def __post(self, url: str, data: str): try: if self.__session is None: async with ClientSession() as session: async with session.post(url, data=data, timeout=10) as response: res = json.loads(await response.content.read(-1)) else: async with self.__session.post(url, data=data, timeout=10) as response: res = json.loads(await response.content.read(-1)) if res['Error'] != 0: if res['Result'] != '': raise SDKException(ErrorCode.other_error(res['Result'])) else: raise SDKException(ErrorCode.other_error(res['Desc'])) return res except (asyncio.TimeoutError, client_exceptions.ClientConnectorError): raise SDKException(ErrorCode.connect_timeout(self._url)) from None
def from_hex_contract_code(cls, code: str): """ generate contract address from avm bytecode. """ try: return cls.__from_byte_script(bytes.fromhex(code), little_endian=False) except ValueError: raise SDKException(ErrorCode.other_error('Invalid avm code.'))
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