Ejemplo n.º 1
0
 def __init__(self, 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 = ''
 def to_utf8_str(ascii_str: str) -> str:
     try:
         utf8_str = binascii.a2b_hex(ascii_str)
         utf8_str = utf8_str.decode('utf-8')
     except (ValueError, binascii.Error) as e:
         raise SDKException(ErrorCode.other_error(e.args[0]))
     return utf8_str
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
    def new_add_recovery_transaction(self, ont_id: str, pub_key: str or bytes,
                                     b58_recovery_address: str,
                                     b58_payer_address: str, gas_limit: int,
                                     gas_price: int):
        """
        This interface is used to generate a Transaction object which is used to add the recovery.

        :param ont_id: OntId.
        :param pub_key: the hexadecimal public key in the form of string.
        :param b58_recovery_address: a base58 encode address which indicate who is the recovery.
        :param b58_payer_address: a base58 encode address which indicate who will pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return:
        """
        if isinstance(pub_key, str):
            bytes_pub_key = bytes.fromhex(pub_key)
        elif isinstance(pub_key, bytes):
            bytes_pub_key = pub_key
        else:
            raise SDKException(
                ErrorCode.params_type_error(
                    'a bytes or str type of public key is required.'))
        bytes_recovery_address = Address.b58decode(
            b58_recovery_address).to_bytes()
        args = dict(ontid=ont_id.encode('utf-8'),
                    recovery=bytes_recovery_address,
                    pk=bytes_pub_key)
        tx = self.__generate_transaction('addRecovery', args,
                                         b58_payer_address, gas_limit,
                                         gas_price)
        return tx
    def read_var_int(self, max_size=sys.maxsize):
        """
        Read a variable length integer from the stream.
        The NEO network protocol supports encoded storage for space saving. See: http://docs.neo.org/en-us/node/network-protocol.html#convention

        Args:
            max_size (int): (Optional) maximum number of bytes to read.

        Returns:
            int:
        """
        fb = self.read_byte()
        if fb is 0:
            return fb
        if hex(fb) == '0xfd':
            value = self.read_uint16()
        elif hex(fb) == '0xfe':
            value = self.read_uint32()
        elif hex(fb) == '0xff':
            value = self.read_uint64()
        else:
            value = fb
        if value > max_size:
            raise SDKException(ErrorCode.param_err('Invalid format'))
        return int(value)
Ejemplo n.º 6
0
    def new_registry_ont_id_transaction(self, ont_id: str, pub_key: str
                                        or bytes, b58_payer_address: str,
                                        gas_limit: int,
                                        gas_price: int) -> Transaction:
        """
        This interface is used to generate a Transaction object which is used to register ONT ID.

        :param ont_id: OntId.
        :param pub_key: the hexadecimal public key in the form of string.
        :param b58_payer_address: a base58 encode address which indicate who will pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: a Transaction object which is used to register ONT ID.
        """
        if isinstance(pub_key, str):
            bytes_ctrl_pub_key = bytes.fromhex(pub_key)
        elif isinstance(pub_key, bytes):
            bytes_ctrl_pub_key = pub_key
        else:
            raise SDKException(
                ErrorCode.param_err(
                    'a bytes or str type of public key is required.'))
        args = dict(ontid=ont_id.encode('utf-8'), ctrl_pk=bytes_ctrl_pub_key)
        tx = self.__generate_transaction('regIDWithPublicKey', args,
                                         b58_payer_address, gas_limit,
                                         gas_price)
        return tx
Ejemplo n.º 7
0
 def parse_pub_keys(ont_id: str, raw_pub_keys: str or bytes) -> list:
     if isinstance(raw_pub_keys, str):
         stream = StreamManager.get_stream(bytearray.fromhex(raw_pub_keys))
     elif isinstance(raw_pub_keys, bytes):
         stream = StreamManager.get_stream(raw_pub_keys)
     else:
         raise SDKException(
             ErrorCode.params_type_error(
                 'bytes or str parameter is required.'))
     reader = BinaryReader(stream)
     pub_keys = list()
     while True:
         try:
             kid = f'{ont_id}#keys-{reader.read_int32()}'
             bytes_key = reader.read_var_bytes()
             hex_pub_key = bytes_key.hex()
             if len(bytes_key) == 33:
                 key_info = dict(PubKeyId=kid,
                                 Type=KeyType.ECDSA.name,
                                 Curve=Curve.P256.name,
                                 Value=hex_pub_key)
             else:
                 key_type = KeyType.from_label(bytes_key[0])
                 curve = Curve.from_label(bytes_key[1])
                 key_info = dict(PubKeyId=kid,
                                 Type=key_type,
                                 Curve=curve,
                                 Value=hex_pub_key)
             pub_keys.append(key_info)
         except SDKException as e:
             if e.args[0] != 10001:
                 raise e
             else:
                 break
     return pub_keys
Ejemplo n.º 8
0
 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
Ejemplo n.º 9
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()
Ejemplo n.º 10
0
 def default_signature_scheme(self, scheme: SignatureScheme):
     if isinstance(scheme, SignatureScheme):
         self.__default_signature_scheme = scheme
         self.__wallet_manager.set_signature_scheme(scheme)
     else:
         raise SDKException(
             ErrorCode.other_error('Invalid signature scheme'))
Ejemplo n.º 11
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.'))
Ejemplo n.º 12
0
 def get_public_key_by_bytes_private_key(private_key: bytes):
     if not isinstance(private_key, bytes):
         raise SDKException(ErrorCode.other_error('The type of private key should be bytes.'))
     if len(private_key) != 32:
         raise SDKException(ErrorCode.other_error('The length of private key should be 32 bytes.'))
     private_key = SigningKey.from_string(string=private_key, curve=NIST256p)
     public_key = private_key.get_verifying_key()
     order = public_key.pubkey.order
     x_int = public_key.pubkey.point.x()
     y_int = public_key.pubkey.point.y()
     x_str = number_to_string(x_int, order)
     if y_int % 2 == 0:
         point_str = b''.join([b'\x02', x_str])
     else:
         point_str = b''.join([b'\x03', x_str])
     return point_str
Ejemplo n.º 13
0
 def decrypt_with_gcm_mode(nonce: bytes, mac_tag: bytes, cipher_text: bytes, private_key: bytes, hdr: bytes,
                           encode_g_tilde: bytes):
     if not isinstance(private_key, bytes):
         raise SDKException(ErrorCode.other_error('the length of private key should be 32 bytes.'))
     if len(private_key) != 32:
         raise SDKException(ErrorCode.other_error('the length of private key should be 32 bytes.'))
     str_g_tilde_x = encode_g_tilde[1:33]
     str_g_tilde_y = encode_g_tilde[33:65]
     g_tilde_x = string_to_number(str_g_tilde_x)
     g_tilde_y = string_to_number(str_g_tilde_y)
     g_tilde = Point(NIST256p.curve, g_tilde_x, g_tilde_y, NIST256p.order)
     h_tilde = g_tilde * SigningKey.from_string(string=private_key, curve=NIST256p).privkey.secret_multiplier
     seed = b''.join([encode_g_tilde, number_to_string(h_tilde.x(), NIST256p.order)])
     aes_key = pbkdf2(seed, 32)
     plain_text = AESHandler.aes_gcm_decrypt(cipher_text, hdr, nonce, mac_tag, aes_key)
     return plain_text
Ejemplo n.º 14
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.'))
Ejemplo n.º 15
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())
Ejemplo n.º 16
0
 def get_tx_hash(event: dict):
     ContractEventParser.__check_event(event)
     try:
         return event['TxHash']
     except KeyError:
         raise SDKException(
             ErrorCode.other_error('TxHash not found in event'))
Ejemplo n.º 17
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)
Ejemplo n.º 18
0
 def get_state(event: dict):
     ContractEventParser.__check_event(event)
     try:
         return event['State']
     except KeyError:
         raise SDKException(
             ErrorCode.other_error('State not found in event'))
Ejemplo n.º 19
0
    def new_revoke_public_key_transaction(self, ont_id: str,
                                          bytes_operator: bytes,
                                          revoked_pub_key: str or bytes,
                                          b58_payer_address: str,
                                          gas_limit: int, gas_price: int):
        """
        This interface is used to generate a Transaction object which is used to remove public key.

        :param ont_id: OntId.
        :param bytes_operator: operator args in from of bytes.
        :param revoked_pub_key: a public key string which will be removed.
        :param b58_payer_address: a base58 encode address which indicate who will pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: a Transaction object which is used to remove public key.
        """
        if isinstance(revoked_pub_key, str):
            bytes_revoked_pub_key = bytes.fromhex(revoked_pub_key)
        elif isinstance(revoked_pub_key, bytes):
            bytes_revoked_pub_key = revoked_pub_key
        else:
            raise SDKException(
                ErrorCode.params_type_error(
                    'a bytes or str type of public key is required.'))
        bytes_ont_id = ont_id.encode('utf-8')
        args = dict(ontid=bytes_ont_id,
                    pk=bytes_revoked_pub_key,
                    operator=bytes_operator)
        tx = self.__generate_transaction('removeKey', args, b58_payer_address,
                                         gas_limit, gas_price)
        return tx
Ejemplo n.º 20
0
 def get_gas_consumed(event: dict):
     ContractEventParser.__check_event(event)
     try:
         return event['GasConsumed']
     except KeyError:
         raise SDKException(
             ErrorCode.other_error('Gas consumed not found in event'))
Ejemplo n.º 21
0
    def new_remove_attribute_transaction(self, ont_id: str, pub_key: str
                                         or bytes, attrib_key: str,
                                         b58_payer_address: str,
                                         gas_limit: int, gas_price: int):
        """
        This interface is used to generate a Transaction object which is used to remove attribute.

        :param ont_id: OntId.
        :param pub_key: the hexadecimal public key in the form of string.
        :param attrib_key: a string which is used to indicate which attribute we want to remove.
        :param b58_payer_address: a base58 encode address which indicate who will pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: a Transaction object which is used to remove attribute.
        """
        if isinstance(pub_key, str):
            bytes_pub_key = bytes.fromhex(pub_key)
        elif isinstance(pub_key, bytes):
            bytes_pub_key = pub_key
        else:
            raise SDKException(
                ErrorCode.params_type_error(
                    'a bytes or str type of public key is required.'))
        args = dict(ontid=ont_id.encode('utf-8'),
                    attrib_key=attrib_key.encode('utf-8'),
                    pk=bytes_pub_key)
        tx = self.__generate_transaction('removeAttribute', args,
                                         b58_payer_address, gas_limit,
                                         gas_price)
        return tx
Ejemplo n.º 22
0
 def get_notify_list(event: dict):
     ContractEventParser.__check_event(event)
     try:
         return event['Notify']
     except KeyError:
         raise SDKException(
             ErrorCode.other_error('Notify not found in event'))
Ejemplo n.º 23
0
 def parse_attributes(serialized_attributes: str or bytes):
     if len(serialized_attributes) == 0:
         return list()
     if isinstance(serialized_attributes, str):
         stream = StreamManager.get_stream(
             bytearray.fromhex(serialized_attributes))
     elif isinstance(serialized_attributes, bytes):
         stream = StreamManager.get_stream(serialized_attributes)
     else:
         raise SDKException(
             ErrorCode.params_type_error(
                 'bytes or str parameter is required.'))
     reader = BinaryReader(stream)
     attributes_list = []
     while True:
         try:
             attr_key = reader.read_var_bytes().decode('utf-8')
             attr_type = reader.read_var_bytes().decode('utf-8')
             attr_value = reader.read_var_bytes().decode('utf-8')
             attr = dict(Key=attr_key, Type=attr_type, Value=attr_value)
             attributes_list.append(attr)
         except SDKException as e:
             if 10000 < e.args[0] < 20000:
                 break
             else:
                 raise e
     return attributes_list
Ejemplo n.º 24
0
 def generate_blk_proof(self,
                        iss_acct: Account,
                        payer: Account,
                        gas_limit: int,
                        gas_price: int,
                        is_big_endian: bool = True,
                        hex_contract_address: str = ''):
     if not isinstance(hex_contract_address, str):
         raise SDKException(ErrorCode.require_str_params)
     if len(hex_contract_address) != 0 and len(hex_contract_address) == 40:
         self.__sdk.neo_vm.claim_record(
         ).hex_contract_address = hex_contract_address
     tx_hash = self.__sdk.neo_vm.claim_record().commit(
         self.payload.jti, iss_acct, self.payload.sub, payer, gas_limit,
         gas_price)
     sleep(10)
     hex_contract_address = self.__sdk.neo_vm.claim_record(
     ).hex_contract_address
     merkle_proof = self.__sdk.get_network().get_merkle_proof(tx_hash)
     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(tx_hash, hex_contract_address,
                                tx_block_height, merkle_root, proof_node)
     return self.__blk_proof
 def __deserialize_stack_item(reader: BinaryReader):
     t = reader.read_byte()
     if t == BuildParams.Type.bytearray_type.value:
         b = reader.read_var_bytes()
         return b
     elif t == BuildParams.Type.bool_type.value:
         return reader.read_bool()
     elif t == BuildParams.Type.int_type.value:
         b = reader.read_var_bytes()
         return ContractDataParser.__big_int_from_bytes(bytearray(b))
     elif t == BuildParams.Type.struct_type.value or t == BuildParams.Type.array_type.value:
         count = reader.read_var_int()
         item_list = list()
         for _ in range(count):
             item = ContractDataParser.__deserialize_stack_item(reader)
             item_list.append(item)
         if t == BuildParams.Type.struct_type.value:
             return Struct(item_list)
         return item_list
     elif t == BuildParams.Type.dict_type.value:
         count = reader.read_var_int()
         item_dict = dict()
         for _ in range(count):
             key = ContractDataParser.__deserialize_stack_item(reader)
             value = ContractDataParser.__deserialize_stack_item(reader)
             item_dict[key] = value
         return item_dict
     else:
         raise SDKException(ErrorCode.other_error('type error'))
Ejemplo n.º 26
0
 def load_file(self):
     with open(self.__wallet_path, 'rb') as f:
         content = f.read()
         if content.startswith(codecs.BOM_UTF8):
             content = content[len(codecs.BOM_UTF8):]
         content = content.decode('utf-8')
         wallet_dict = json.loads(content)
         create_time = wallet_dict.get('createTime', '')
         default_id = wallet_dict.get('defaultOntid', '')
         default_address = wallet_dict.get('defaultAccountAddress', '')
         identities = wallet_dict.get('identities', list())
         try:
             scrypt_dict = wallet_dict['scrypt']
             scrypt_obj = Scrypt(scrypt_dict.get('n', 16384),
                                 scrypt_dict.get('r', 8),
                                 scrypt_dict.get('p', 8),
                                 scrypt_dict.get('dk_len', 64))
             wallet = WalletData(wallet_dict['name'],
                                 wallet_dict['version'], create_time,
                                 default_id, default_address, scrypt_obj,
                                 identities, wallet_dict['accounts'])
         except KeyError as e:
             raise SDKException(
                 ErrorCode.param_err(f'wallet file format error: {e}.'))
     return wallet
 def to_b58_address(hex_address: str) -> str:
     try:
         bytes_address = binascii.a2b_hex(hex_address)
     except binascii.Error as e:
         raise SDKException(ErrorCode.other_error(e.args[0]))
     address = Address(bytes_address)
     return address.b58encode()
Ejemplo n.º 28
0
 def wrapper(*args, **kwargs):
     ont_id = args[1]
     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)
Ejemplo n.º 29
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))
Ejemplo n.º 30
0
 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