예제 #1
0
 def test_wallet_data_clone(self):
     ont_id = 'test_ont_id'
     w = WalletData(default_id=ont_id)
     clone_wallet = w.clone()
     self.assertEqual(clone_wallet.__dict__['default_ont_id'], ont_id)
예제 #2
0
class WalletManager(object):
    def __init__(self, scheme=SignatureScheme.SHA256withECDSA):
        self.scheme = scheme
        self.wallet_file = WalletData()
        self.wallet_in_mem = WalletData()
        self.wallet_path = ""

    def open_wallet(self, wallet_path: str):
        self.wallet_path = wallet_path
        if is_file_exist(wallet_path) is False:
            # create a new wallet file
            self.wallet_in_mem.createTime = datetime.today().strftime(
                "%Y-%m-%d %H:%M:%S")
            self.save()
        # wallet file exists now
        self.wallet_file = self.load()
        self.wallet_in_mem = self.wallet_file
        return self.wallet_file

    def load(self):
        f = open(self.wallet_path, "r")
        r = json.load(f,
                      object_hook=lambda d: namedtuple('X', d.keys())
                      (*d.values()))
        f.close()
        scrypt = Scrypt(r.scrypt.n, r.scrypt.r, r.scrypt.p, r.scrypt.dk_len)

        identities = []
        for index in range(len(r.identities)):
            control = [
                Control(id=r.identities[index].controls[0].id,
                        algorithm=r.identities[index].controls[0].algorithm,
                        param=r.identities[index].controls[0].parameters,
                        key=r.identities[index].controls[0].key,
                        address=r.identities[index].controls[0].address,
                        salt=r.identities[index].controls[0].salt,
                        enc_alg=r.identities[index].controls[0].enc_alg,
                        hash_value=r.identities[index].controls[0].hash,
                        public_key=r.identities[index].controls[0].publicKey)
            ]
            temp = Identity(r.identities[index].ontid,
                            r.identities[index].label,
                            r.identities[index].lock, control)
            identities.append(temp)

        accounts = []
        for index in range(len(r.accounts)):
            temp = AccountData(label=r.accounts[index].label,
                               public_key=r.accounts[index].publicKey,
                               sign_scheme=r.accounts[index].signatureScheme,
                               is_default=r.accounts[index].isDefault,
                               lock=r.accounts[index].lock,
                               address=r.accounts[index].address,
                               algorithm=r.accounts[index].algorithm,
                               param=r.accounts[index].parameters,
                               key=r.accounts[index].key,
                               enc_alg=r.accounts[index].enc_alg,
                               salt=r.accounts[index].salt,
                               hash_value=r.accounts[index].hash)
            accounts.append(temp)

        res = WalletData(r.name, r.version, r.createTime, r.defaultOntid,
                         r.defaultAccountAddress, scrypt, identities, accounts)
        return res

    def save(self):
        f = open(self.wallet_path, "w")
        json.dump(self.wallet_in_mem,
                  f,
                  default=lambda obj: obj.__dict__,
                  indent=4)
        f.close()
        # f = open(wallet_path, 'r+')
        # s = f.read()
        # while "enc_alg" in s:
        #     s = s.replace("enc_alg", "enc-alg")
        # f.seek(0)
        # f.write(s)
        # f.close()

    def get_wallet(self):
        return self.wallet_in_mem

    def write_wallet(self):
        self.save()
        self.wallet_file = self.wallet_in_mem
        return self.wallet_file

    def reset_wallet(self):
        self.wallet_in_mem = self.wallet_file.clone()
        return self.wallet_in_mem

    def get_signature_scheme(self):
        return self.scheme

    def set_signature_scheme(self, scheme):
        self.scheme = scheme

    def import_identity(self, label: str, encrypted_privkey: str, pwd: str,
                        salt: bytes, address: str):
        private_key = Account.get_gcm_decoded_private_key(
            encrypted_privkey, pwd, address, salt,
            Scrypt().get_n(), self.scheme)
        info = self.__create_identity(label, pwd, salt, private_key)
        private_key = None
        for index in range(len(self.wallet_in_mem.identities)):
            if self.wallet_in_mem.identities[index].ontid == info.ontid:
                return self.wallet_in_mem.identities[index]
        return None

    def create_identity(self, label: str, pwd: str):
        priv_key = get_random_bytes(32)
        salt = get_random_bytes(16)
        return self.__create_identity(label, pwd, salt, priv_key)

    def __create_identity(self, label: str, pwd: str, salt: bytes,
                          private_key: bytes):
        acct = self.__create_account(label, pwd, salt, private_key, False)
        info = IdentityInfo()
        info.ontid = did_ont + acct.get_address_base58()
        info.pubic_key = acct.serialize_public_key().hex()
        info.private_key = acct.serialize_private_key().hex()
        info.prikey_wif = acct.export_wif()
        info.encrypted_prikey = acct.export_gcm_encrypted_private_key(
            pwd, salt,
            Scrypt().get_n())
        info.address_u160 = acct.get_address().to_array().hex()
        return self.wallet_in_mem.get_identity_by_ontid(info.ontid)

    def create_identity_from_prikey(self, label: str, pwd: str,
                                    private_key: bytes):
        salt = get_random_bytes(16)
        identity = self.__create_identity(label, pwd, salt, private_key)
        private_key = None
        return identity

    def create_account(self, label: str, pwd: str) -> AccountData:
        priv_key = get_random_bytes(32)
        salt = get_random_bytes(16)
        account = self.__create_account(label, pwd, salt, priv_key, True)
        return self.wallet_file.get_account_by_address(
            account.get_address_base58())

    def __create_account(self, label: str, pwd: str, salt: bytes,
                         priv_key: bytes, account_flag: bool):
        account = Account(priv_key, self.scheme)
        # initialization
        if self.scheme == SignatureScheme.SHA256withECDSA:
            acct = AccountData()
        else:
            raise ValueError("scheme type is error")
        # set key
        if pwd != None:
            acct.key = account.export_gcm_encrypted_private_key(
                pwd, salt,
                Scrypt().get_n())
            pwd = None
        else:
            acct.key = account.serialize_private_key().hex()

        acct.address = account.get_address_base58()
        # set label
        if label == None or label == "":
            label = str(uuid.uuid4())[0:8]
        if account_flag:
            for index in range(len(self.wallet_in_mem.accounts)):
                if acct.address == self.wallet_in_mem.accounts[index].address:
                    raise ValueError("wallet account exists")

            if len(self.wallet_in_mem.accounts) == 0:
                acct.isDefault = True
                self.wallet_in_mem.defaultAccountAddress = acct.address
            acct.label = label
            acct.salt = base64.b64encode(salt).decode()
            acct.publicKey = account.serialize_public_key().hex()
            self.wallet_in_mem.accounts.append(acct)
        else:
            for index in range(len(self.wallet_in_mem.identities)):
                if self.wallet_in_mem.identities[
                        index].ontid == did_ont + acct.address:
                    raise ValueError("wallet identity exists")
            idt = Identity()
            idt.ontid = did_ont + acct.address
            idt.label = label
            if len(self.wallet_in_mem.identities) == 0:
                idt.isDefault = True
                self.wallet_in_mem.defaultOntid = idt.ontid
            ctl = Control(id="keys-1",
                          key=acct.key,
                          salt=base64.b64encode(salt).decode(),
                          address=acct.address,
                          public_key=account.serialize_public_key().hex())
            idt.controls.append(ctl)
            self.wallet_in_mem.identities.append(idt)
        return account

    def import_account(self, label: str, encrypted_prikey: str, pwd: str,
                       base58_addr: str, salt: bytes):
        private_key = Account.get_gcm_decoded_private_key(
            encrypted_prikey, pwd, base58_addr, salt,
            Scrypt().get_n(), self.scheme)
        info = self.create_account_info(label, pwd, salt, private_key)
        private_key, pwd = None, None
        for index in range(len(self.wallet_in_mem.accounts)):
            if info.address_base58 == self.wallet_in_mem.accounts[
                    index].address:
                return self.wallet_in_mem.accounts[index]
        return None

    def create_account_info(self, label: str, pwd: str, salt: bytes,
                            private_key: bytes):
        acct = self.__create_account(label, pwd, salt, private_key, True)
        info = AccountInfo()
        info.address_base58 = Address.address_from_bytes_pubkey(
            acct.serialize_public_key()).to_base58()
        info.public_key = acct.serialize_public_key().hex()
        info.encrypted_prikey = acct.export_gcm_encrypted_private_key(
            pwd, salt,
            Scrypt().get_n())
        info.address_u160 = acct.get_address().to_array().hex()
        return info

    def create_account_from_prikey(self, label: str, pwd: str,
                                   private_key: bytes):
        salt = get_random_bytes(16)
        info = self.create_account_info(label, pwd, salt, private_key)
        for index in range(len(self.wallet_in_mem.accounts)):
            if info.address_base58 == self.wallet_in_mem.accounts[
                    index].address:
                return self.wallet_in_mem.accounts[index]
        return None

    def get_account(self, address: str, pwd: str):
        for index in range(len(self.wallet_in_mem.accounts)):
            if self.wallet_in_mem.accounts[index].address == address:
                key = self.wallet_in_mem.accounts[index].key
                addr = self.wallet_in_mem.accounts[index].address
                salt = base64.b64decode(
                    self.wallet_in_mem.accounts[index].salt)
                private_key = Account.get_gcm_decoded_private_key(
                    key, pwd, addr, salt,
                    Scrypt().get_n(), self.scheme)
                return Account(private_key, self.scheme)

        for index in range(len(self.wallet_in_mem.identities)):
            if self.wallet_in_mem.identities[index].ontid == did_ont + address:
                addr = self.wallet_in_mem.identities[index].ontid.replace(
                    did_ont, "")
                key = self.wallet_in_mem.identities[index].controls[0].key
                salt = base64.b64decode(
                    self.wallet_in_mem.identities[index].controls[0].salt)
                private_key = Account.get_gcm_decoded_private_key(
                    key, pwd, addr, salt,
                    Scrypt().get_n(), self.scheme)
                return Account(private_key, self.scheme)
        return None
class WalletManager(object):
    def __init__(self, scheme=SignatureScheme.SHA256withECDSA):
        self.scheme = scheme
        self.wallet_file = WalletData()
        self.wallet_in_mem = WalletData()
        self.wallet_path = ""

    def open_wallet(self, wallet_path: str):
        self.wallet_path = wallet_path
        if is_file_exist(wallet_path) is False:
            # create a new wallet file
            self.wallet_in_mem.createTime = datetime.today().strftime("%Y-%m-%d %H:%M:%S")
            self.save()
        # wallet file exists now
        self.wallet_file = self.load()
        self.wallet_in_mem = self.wallet_file
        return self.wallet_file

    def load(self):
        with open(self.wallet_path, "r") as f:
            fstr = f.read()
            r = json.loads(fstr.replace("enc-", "enc_"), object_hook=lambda d: namedtuple('X', d.keys())(*d.values()))
            # r = json.load(f, object_hook=lambda d: namedtuple('X', d.keys())(*d.values()))
            scrypt = Scrypt(r.scrypt.n, r.scrypt.r, r.scrypt.p, r.scrypt.dkLen)
            identities = []
            try:
                for index in range(len(r.identities)):
                    r_identities = r.identities[index]
                    control = [Control(id=r_identities.controls[0].id,
                                       algorithm=r_identities.controls[0].algorithm,
                                       param=r_identities.controls[0].parameters,
                                       key=r_identities.controls[0].key,
                                       address=r_identities.controls[0].address,
                                       salt=r_identities.controls[0].salt,
                                       enc_alg=r_identities.controls[0].enc_alg,
                                       hash_value=r_identities.controls[0].hash,
                                       public_key=r_identities.controls[0].publicKey)]
                    identities.append(Identity(r_identities.ont_id, r_identities.label, r_identities.lock, control))
            except AttributeError as e:
                pass

            accounts = []
            try:
                for index in range(len(r.accounts)):
                    temp = AccountData(label=r.accounts[index].label, public_key=r.accounts[index].publicKey,
                                       sign_scheme=r.accounts[index].signatureScheme,
                                       isDefault=r.accounts[index].isDefault,
                                       lock=r.accounts[index].lock, address=r.accounts[index].address,
                                       algorithm=r.accounts[index].algorithm, param=r.accounts[index].parameters,
                                       key=r.accounts[index].key, enc_alg=r.accounts[index].enc_alg,
                                       salt=r.accounts[index].salt)
                    accounts.append(temp)
            except AttributeError as e:
                pass
            default_ont_id = ""
            try:
                default_ont_id = r.defaultOntid
            except AttributeError as e:
                pass
            default_account_address = ""
            try:
                default_account_address = r.defaultAccountAddress
            except AttributeError as e:
                pass
            create_time = datetime.today().strftime("%Y-%m-%d %H:%M:%S")
            try:
                create_time = r.createTime
            except Exception as e:
                pass
            res = WalletData(r.name, r.version, create_time, default_ont_id, default_account_address, scrypt,
                             identities, accounts)
            return res

    def save(self):
        fstr = json.dumps(self.wallet_in_mem, default=lambda obj: obj.__dict__, sort_keys=True, indent=4)
        temp = fstr.replace("enc_", "enc-")
        f = open(self.wallet_path, "w")
        f.write(temp)
        f.close()

    def get_wallet(self):
        return self.wallet_in_mem

    def write_wallet(self):
        self.save()
        self.wallet_file = self.wallet_in_mem
        return self.wallet_file

    def reset_wallet(self):
        self.wallet_in_mem = self.wallet_file.clone()
        return self.wallet_in_mem

    def get_signature_scheme(self):
        return self.scheme

    def set_signature_scheme(self, scheme):
        self.scheme = scheme

    def import_identity(self, label: str, encrypted_pri_key: str, pwd: str, salt: str, address: str):
        pri_key = Account.get_gcm_decoded_private_key(encrypted_pri_key, pwd, address, salt,
                                                      Scrypt().get_n(), self.scheme)
        info = self.__create_identity(label, pwd, salt, pri_key)
        for index in range(len(self.wallet_in_mem.identities)):
            if self.wallet_in_mem.identities[index].ont_id == info.ont_id:
                return self.wallet_in_mem.identities[index]
        return None

    def create_identity(self, label: str, pwd: str):
        priv_key = get_random_str(64)
        salt = get_random_str(16)
        return self.__create_identity(label, pwd, salt, priv_key)

    def __create_identity(self, label: str, pwd: str, salt: str, private_key: str):
        acct = self.__create_account(label, pwd, salt, private_key, False)
        info = IdentityInfo()
        info.ont_id = did_ont + acct.get_address_base58()
        info.pubic_key = acct.serialize_public_key().hex()
        info.private_key = acct.serialize_private_key().hex()
        info.pri_key_wif = acct.export_wif()
        info.encrypted_pri_key = acct.export_gcm_encrypted_private_key(pwd, salt, Scrypt().get_n())
        info.address_u160 = acct.get_address().to_array().hex()
        return self.wallet_in_mem.get_identity_by_ont_id(info.ont_id)

    def create_identity_from_pri_key(self, label: str, pwd: str, private_key: str):
        salt = get_random_str(16)
        identity = self.__create_identity(label, pwd, salt, private_key)
        return identity

    def create_account(self, label: str, pwd: str) -> AccountData:
        pri_key = get_random_str(64)
        salt = get_random_str(16)
        account = self.__create_account(label, pwd, salt, pri_key, True)
        return self.wallet_file.get_account_by_address(account.get_address_base58())

    def __create_account(self, label: str, pwd: str, salt: str, priv_key: str, account_flag: bool):
        print(priv_key)
        account = Account(priv_key, self.scheme)
        # initialization
        if self.scheme == SignatureScheme.SHA256withECDSA:
            acct = AccountData()
        else:
            raise ValueError("scheme type is error")
        # set key
        if pwd is not None:
            acct.key = account.export_gcm_encrypted_private_key(pwd, salt, Scrypt().get_n())
        else:
            acct.key = account.serialize_private_key().hex()

        acct.address = account.get_address_base58()
        # set label
        if label is None or label == "":
            label = str(uuid.uuid4())[0:8]
        if account_flag:
            for index in range(len(self.wallet_in_mem.accounts)):
                if acct.address == self.wallet_in_mem.accounts[index].address:
                    raise ValueError("wallet account exists")

            if len(self.wallet_in_mem.accounts) == 0:
                acct.isDefault = True
                self.wallet_in_mem.defaultAccountAddress = acct.address
            acct.label = label
            acct.salt = base64.b64encode(salt.encode()).decode('ascii')
            acct.publicKey = account.serialize_public_key().hex()
            self.wallet_in_mem.accounts.append(acct)
        else:
            for index in range(len(self.wallet_in_mem.identities)):
                if self.wallet_in_mem.identities[index].ont_id == did_ont + acct.address:
                    raise ValueError("wallet identity exists")
            idt = Identity()
            idt.ontid = did_ont + acct.address
            idt.label = label
            if len(self.wallet_in_mem.identities) == 0:
                idt.isDefault = True
                self.wallet_in_mem.defaultOntid = idt.ontid
            ctl = Control(id="keys-1", key=acct.key, salt=base64.b64encode(salt.encode()).decode('ascii'),
                          address=acct.address,
                          public_key=account.serialize_public_key().hex())
            idt.controls.append(ctl)
            self.wallet_in_mem.identities.append(idt)
        return account

    def import_account(self, label: str, encrypted_pri_key: str, pwd: str, base58_addr: str, base64_salt: str):
        salt = base64.b64decode(base64_salt.encode('ascii')).decode('latin-1')
        private_key = Account.get_gcm_decoded_private_key(encrypted_pri_key, pwd, base58_addr, salt, Scrypt().get_n(),
                                                          self.scheme)
        info = self.create_account_info(label, pwd, salt, private_key)
        for index in range(len(self.wallet_in_mem.accounts)):
            if info.address_base58 == self.wallet_in_mem.accounts[index].address:
                return self.wallet_in_mem.accounts[index]
        return None

    def create_account_info(self, label: str, pwd: str, salt: str, private_key: str):
        acct = self.__create_account(label, pwd, salt, private_key, True)
        info = AccountInfo()
        info.address_base58 = Address.address_from_bytes_pubkey(acct.serialize_public_key()).b58encode()
        info.public_key = acct.serialize_public_key().hex()
        info.encrypted_pri_key = acct.export_gcm_encrypted_private_key(pwd, salt, Scrypt().get_n())
        info.address_u160 = acct.get_address().to_array().hex()
        info.salt = salt
        return info

    def create_account_from_prikey(self, label: str, pwd: str, private_key: str):
        salt = get_random_str(16)
        info = self.create_account_info(label, pwd, salt, private_key)
        for index in range(len(self.wallet_in_mem.accounts)):
            if info.address_base58 == self.wallet_in_mem.accounts[index].address:
                return self.wallet_in_mem.accounts[index]
        return None

    def get_account(self, address: str, pwd: str):
        for index in range(len(self.wallet_in_mem.accounts)):
            if self.wallet_in_mem.accounts[index].address == address:
                key = self.wallet_in_mem.accounts[index].key
                addr = self.wallet_in_mem.accounts[index].address
                salt = base64.b64decode(self.wallet_in_mem.accounts[index].salt)
                private_key = Account.get_gcm_decoded_private_key(key, pwd, addr, salt, Scrypt().get_n(), self.scheme)
                return Account(private_key, self.scheme)

        for index in range(len(self.wallet_in_mem.identities)):
            if self.wallet_in_mem.identities[index].ont_id == did_ont + address:
                addr = self.wallet_in_mem.identities[index].ont_id.replace(did_ont, "")
                key = self.wallet_in_mem.identities[index].controls[0].key
                salt = base64.b64decode(self.wallet_in_mem.identities[index].controls[0].salt)
                private_key = Account.get_gcm_decoded_private_key(key, pwd, addr, salt, Scrypt().get_n(), self.scheme)
                return Account(private_key, self.scheme)
        return None

    def get_default_identity(self) -> Identity:
        for identity in self.wallet_in_mem.identities:
            if identity.isDefault:
                return identity
        raise SDKException(ErrorCode.param_error)

    def get_default_account(self) -> AccountData:
        for acct in self.wallet_in_mem.accounts:
            if acct.isDefault:
                return acct
        raise SDKException(ErrorCode.get_default_account_err)
예제 #4
0
class WalletManager(object):
    def __init__(self, scheme=SignatureScheme.SHA256withECDSA):
        self.scheme = scheme
        self.wallet_file = WalletData()
        self.wallet_in_mem = WalletData()
        self.wallet_path = ""

    def open_wallet(self, wallet_path: str):
        self.wallet_path = wallet_path
        if is_file_exist(wallet_path) is False:
            # create a new wallet file
            self.wallet_in_mem.create_time = datetime.today().strftime("%Y-%m-%d %H:%M:%S")
            self.save()
        # wallet file exists now
        self.wallet_file = self.load()
        self.wallet_in_mem = self.wallet_file
        return self.wallet_file

    def load(self):
        with open(self.wallet_path, "rb") as f:
            content = f.read()
            if content.startswith(codecs.BOM_UTF8):
                content = content[len(codecs.BOM_UTF8):]
            obj = json.loads(content)
            try:
                create_time = obj['createTime']
            except KeyError:
                create_time = ''
            try:
                default_id = obj['defaultOntid']
            except KeyError:
                default_id = ''
            try:
                default_address = obj['defaultAccountAddress']
            except KeyError:
                default_address = ''
            try:
                identities = obj['identities']
            except KeyError:
                identities = list()
            try:
                scrypt_dict = obj['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(obj['name'], obj['version'], create_time, default_id, default_address,
                                    scrypt_obj, identities, obj['accounts'])
            except KeyError as e:
                raise SDKException(ErrorCode.param_err('wallet file format error: %s.' % e))
        return wallet

    def save(self):
        with open(self.wallet_path, "w") as f:
            json.dump(self.wallet_in_mem, f, default=lambda obj: dict(obj), indent=4)

    def get_wallet(self):
        return self.wallet_in_mem

    def write_wallet(self):
        self.save()
        self.wallet_file = self.wallet_in_mem
        return self.wallet_file

    def reset_wallet(self):
        self.wallet_in_mem = self.wallet_file.clone()
        return self.wallet_in_mem

    def get_signature_scheme(self):
        return self.scheme

    def set_signature_scheme(self, scheme):
        self.scheme = scheme

    def import_identity(self, label: str, encrypted_pri_key: str, pwd: str, salt: str,
                        b58_address: str) -> Identity or None:
        """
        This interface is used to import identity by providing encrypted private key, password, salt and
        base58 encode address which should be correspond to the encrypted private key provided.

        :param label: a label for identity.
        :param encrypted_pri_key: an encrypted private key in base64 encoding from.
        :param pwd: a password which is used to encrypt and decrypt the private key.
        :param salt: a salt value which will be used in the process of encrypt private key.
        :param b58_address: a base58 encode address which correspond with the encrypted private key provided.
        :return: if succeed, an Identity object will be returned.
        """
        scrypt_n = Scrypt().get_n()
        pri_key = Account.get_gcm_decoded_private_key(encrypted_pri_key, pwd, b58_address, salt, scrypt_n, self.scheme)
        info = self.__create_identity(label, pwd, salt, pri_key)
        for index in range(len(self.wallet_in_mem.identities)):
            if self.wallet_in_mem.identities[index].ont_id == info.ont_id:
                return self.wallet_in_mem.identities[index]
        return None

    def create_identity(self, label: str, pwd: str) -> Identity:
        """

        :param label: a label for identity.
        :param pwd: a password which will be used to encrypt and decrypt the private key.
        :return: if succeed, an Identity object will be returned.
        """
        pri_key = get_random_hex_str(64)
        salt = get_random_hex_str(16)
        return self.__create_identity(label, pwd, salt, pri_key)

    def __create_identity(self, label: str, pwd: str, salt: str, private_key: str):
        acct = self.__create_account(label, pwd, salt, private_key, False)
        info = IdentityInfo()
        info.ont_id = did_ont + acct.get_address_base58()
        info.pubic_key = acct.serialize_public_key().hex()
        info.private_key = acct.serialize_private_key().hex()
        info.pri_key_wif = acct.export_wif().encode('ascii')
        info.encrypted_pri_key = acct.export_gcm_encrypted_private_key(pwd, salt, Scrypt().get_n())
        info.address_u160 = acct.get_address().to_array().hex()
        return self.wallet_in_mem.get_identity_by_ont_id(info.ont_id)

    def create_identity_from_private_key(self, label: str, pwd: str, private_key: str) -> Identity:
        """
        This interface is used to create identity based on given label, password and private key.

        :param label: a label for identity.
        :param pwd: a password which will be used to encrypt and decrypt the private key.
        :param private_key: a private key in the form of string.
        :return: if succeed, an Identity object will be returned.
        """
        salt = get_random_hex_str(16)
        identity = self.__create_identity(label, pwd, salt, private_key)
        return identity

    def create_account(self, label: str, pwd: str) -> AccountData:
        """
        This interface is used to create account based on given password and label.

        :param label: a label for account.
        :param pwd: a password which will be used to encrypt and decrypt the private key
        :return: if succeed, return an data structure which contain the information of a wallet account.
        """
        pri_key = get_random_hex_str(64)
        salt = get_random_hex_str(16)
        account = self.__create_account(label, pwd, salt, pri_key, True)
        return self.wallet_in_mem.get_account_by_address(account.get_address_base58())

    def __create_account(self, label: str, pwd: str, salt: str, private_key: str, account_flag: bool):
        account = Account(private_key, self.scheme)
        # initialization
        if self.scheme == SignatureScheme.SHA256withECDSA:
            acct = AccountData()
        else:
            raise ValueError("scheme type is error")
        # set key
        if pwd is not None:
            acct.key = account.export_gcm_encrypted_private_key(pwd, salt, Scrypt().get_n())
        else:
            acct.key = account.serialize_private_key().hex()

        acct.address = account.get_address_base58()
        # set label
        if label is None or label == "":
            label = str(uuid.uuid4())[0:8]
        if account_flag:
            for index in range(len(self.wallet_in_mem.accounts)):
                if acct.address == self.wallet_in_mem.accounts[index].address:
                    raise ValueError("wallet account exists")

            if len(self.wallet_in_mem.accounts) == 0:
                acct.is_default = True
                self.wallet_in_mem.default_account_address = acct.address
            acct.label = label
            acct.salt = base64.b64encode(salt.encode('latin-1')).decode('ascii')
            acct.public_key = account.serialize_public_key().hex()
            self.wallet_in_mem.accounts.append(acct)
        # else:
            for index in range(len(self.wallet_in_mem.identities)):
                if self.wallet_in_mem.identities[index].ont_id == did_ont + acct.address:
                    raise ValueError("wallet identity exists")
            idt = Identity()
            idt.ont_id = did_ont + acct.address
            idt.label = label
            if len(self.wallet_in_mem.identities) == 0:
                idt.is_default = True
                self.wallet_in_mem.default_ont_id = idt.ont_id
            ctl = Control(id="keys-1", key=acct.key, salt=base64.b64encode(salt.encode()).decode('ascii'),
                          address=acct.address,
                          public_key=account.serialize_public_key().hex())
            idt.controls.append(ctl)
            self.wallet_in_mem.identities.append(idt)
        return account

    def import_account(self, label: str, encrypted_pri_key: str, pwd: str, base58_address: str,
                       base64_salt: str) -> AccountData or None:
        """
        This interface is used to import account by providing account data.

        :param label: str, wallet label
        :param encrypted_pri_key: str, an encrypted private key in base64 encoding from
        :param pwd: str, a password which is used to encrypt and decrypt the private key
        :param base58_address: str, a base58 encode  wallet address value
        :param base64_salt: str, a base64 encode salt value which is used in the encryption of private key
        :return:
            if succeed, return an data structure which contain the information of a wallet account.
            if failed, return a None object.
        """
        salt = base64.b64decode(base64_salt.encode('ascii')).decode('latin-1')
        private_key = Account.get_gcm_decoded_private_key(encrypted_pri_key, pwd, base58_address, salt,
                                                          Scrypt().get_n(), self.scheme)
        info = self.create_account_info(label, pwd, salt, private_key)
        for index in range(len(self.wallet_in_mem.accounts)):
            if info.address_base58 == self.wallet_in_mem.accounts[index].address:
                return self.wallet_in_mem.accounts[index]
        return None

    def create_account_info(self, label: str, pwd: str, salt: str, private_key: str) -> AccountInfo:
        acct = self.__create_account(label, pwd, salt, private_key, True)
        info = AccountInfo()
        info.address_base58 = Address.address_from_bytes_pubkey(acct.serialize_public_key()).b58encode()
        info.public_key = acct.serialize_public_key().hex()
        info.encrypted_pri_key = acct.export_gcm_encrypted_private_key(pwd, salt, Scrypt().get_n())
        info.address_u160 = acct.get_address().to_array().hex()
        info.salt = salt
        return info

    def create_account_from_private_key(self, label: str, password: str, private_key: str) -> AccountData or None:
        """
        This interface is used to create account by providing an encrypted private key and it's decrypt password.

        :param label: a label for account.
        :param password: a password which is used to decrypt the encrypted private key.
        :param private_key: a private key in the form of string.
        :return: if succeed, return an AccountData object.
                  if failed, return a None object.
        """
        salt = get_random_hex_str(16)
        info = self.create_account_info(label, password, salt, private_key)
        for index in range(len(self.wallet_in_mem.accounts)):
            if info.address_base58 == self.wallet_in_mem.accounts[index].address:
                return self.wallet_in_mem.accounts[index]
        return None

    def get_account(self, b58_address_or_ontid: str, password: str) -> Account or None:
        """
        :param b58_address_or_ontid: a base58 encode address or ontid
        :param password: a password which is used to decrypt the encrypted private key.
        :return:
        """
        if b58_address_or_ontid.startswith(DID_ONT):
            for index in range(len(self.wallet_in_mem.identities)):
                if self.wallet_in_mem.identities[index].ont_id == b58_address_or_ontid:
                    addr = self.wallet_in_mem.identities[index].ont_id.replace(did_ont, "")
                    key = self.wallet_in_mem.identities[index].controls[0].key
                    salt = base64.b64decode(self.wallet_in_mem.identities[index].controls[0].salt)
                    private_key = Account.get_gcm_decoded_private_key(key, password, addr, salt,
                                                                      self.wallet_in_mem.scrypt.get_n(), self.scheme)
                    return Account(private_key, self.scheme)
        else:
            for index in range(len(self.wallet_in_mem.accounts)):
                if self.wallet_in_mem.accounts[index].address == b58_address_or_ontid:
                    key = self.wallet_in_mem.accounts[index].key
                    addr = self.wallet_in_mem.accounts[index].address
                    salt = base64.b64decode(self.wallet_in_mem.accounts[index].salt)
                    private_key = Account.get_gcm_decoded_private_key(key, password, addr, salt,
                                                                      self.wallet_in_mem.scrypt.get_n(), self.scheme)
                    return Account(private_key, self.scheme)
        return None

    def get_default_identity(self) -> Identity:
        for identity in self.wallet_in_mem.identities:
            if identity.is_default:
                return identity
        raise SDKException(ErrorCode.param_error)

    def get_default_account(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 acct.is_default:
                return acct
        raise SDKException(ErrorCode.get_default_account_err)
예제 #5
0
 def test_clone(self):
     w = WalletData(default_ontid='hahaha')
     clone = w.clone()
     print(clone.__dict__)