Как восстановить кошелек Algorand с помощью Python AlgoSDK?

#python #blockchain #wallet

#python #блокчейн #кошелек

Вопрос:

Хотя официальная документация algosdk (Python SDK для Algorand) предполагает, что кошелек можно восстановить, просто вызвав следующую функцию (ссылка):

 create_wallet(name, pswd, driver_name='sqlite', master_deriv_key=None)
 

с четвертым аргументом:

 master_deriv_key (str, optional) – if recovering a wallet, include
 

восстановление кошелька не работает в моем коде и также приводит к возникновению исключения. Также в официальной документации Algorand показано, как использовать вышеупомянутую функцию для восстановления кошелька (ссылка):

 # recover the wallet by passing mdk when creating a wallet
new_wallet = kcl.create_wallet("MyTestWallet2", "testpassword", master_deriv_key=mdk)
 

Ниже вы можете посмотреть мой код, очень простой фрагмент, который я закодировал для проведения некоторых тестов с помощью Algorand SDK:

 from algosdk import kmd
from algosdk import mnemonic

kmd_clt = kmd.KMDClient('855d39510cce40caf11de4c941b37632d1529ec970156214528a33a0ae8473b4', 'http://127.0.0.1:6969')
if kmd_clt:
    kmd_wlt_mdk = None
    kmd_wlt_list = kmd_clt.list_wallets()
    for kmd_wlt in kmd_wlt_list:
        kmd_name = kmd_wlt['name']
        kmd_id = kmd_wlt['id']
        if kmd_name == 'wallet_name':
            kmd_wlt_hdl = kmd_clt.init_wallet_handle(kmd_id, 'wallet_password')
            if kmd_wlt_hdl:
                kmd_wlt_mdk = kmd_clt.export_master_derivation_key(kmd_wlt_hdl, 'wallet_password')
            break
    if kmd_wlt_mdk:
        kmd_wlt = kmd_clt.create_wallet('wallet_name', 'wallet_password', master_deriv_key=kmd_wlt_mdk)
        kmd_wlt_hdl = kmd_clt.init_wallet_handle(kmd_wlt['id'], 'wallet_password')
        acc_addr_list = kmd_clt.list_keys(kmd_wlt_hdl)
        for acc_addr in acc_addr_list:
            account_address = acc_addr
            print(account_address)
            account_key = kmd_clt.export_key(kmd_wlt_hdl, 'wallet_password', account_address)
            print(account_key)
            account_mnemonic = mnemonic.from_private_key(account_key)
            print(account_mnemonic)
 

Ниже вы можете посмотреть обратную трассировку и сообщение об ошибке, возвращаемое во время выполнения:

 Traceback (most recent call last):
  File "/home/emiliano/anaconda3/lib/python3.7/site-packages/algosdk/kmd.py", line 63, in kmd_request
    resp = urlopen(req)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py", line 531, in open
    response = meth(req, response)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py", line 641, in http_response
    'http', request, response, code, msg, hdrs)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py", line 569, in error
    return self._call_chain(*args)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py", line 503, in _call_chain
    result = func(*args)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py", line 649, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 400: Bad Request

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/emiliano/anaconda3/lib/python3.7/site-packages/algosdk/kmd.py", line 67, in kmd_request
    raise error.KMDHTTPError(json.loads(e)["message"])
algosdk.error.KMDHTTPError: wallet with same name already exists

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "algorand_test.py", line 49, in <module>
    kmd_wlt = kmd_clt.create_wallet('emiliano', 'emiliano', master_deriv_key=kmd_wlt_mdk)
  File "/home/emiliano/anaconda3/lib/python3.7/site-packages/algosdk/kmd.py", line 118, in create_wallet
    return self.kmd_request("POST", req, data=query)["wallet"]
  File "/home/emiliano/anaconda3/lib/python3.7/site-packages/algosdk/kmd.py", line 69, in kmd_request
    raise error.KMDHTTPError(e)
algosdk.error.KMDHTTPError: {
  "error": true,
  "message": "wallet with same name already exists"
}
 

Кажется, ясно, как create_wallet функция является виновником такого поведения, которое приводит к возврату ошибки «кошелек с тем же именем уже существует». Внутренности Algorand SDK очень просты, API-интерфейсы являются оболочками для методов REST. Функция create_wallet выполняет просто (ссылка):

 def create_wallet(self, name, pswd, driver_name="sqlite",
                  master_deriv_key=None):
    """
    Create a new wallet.
    Args:
        name (str): wallet name
        pswd (str): wallet password
        driver_name (str, optional): name of the driver
        master_deriv_key (str, optional): if recovering a wallet, include
    Returns:
        dict: dictionary containing wallet information
    """
    req = "/wallet"
    query = {
        "wallet_driver_name": driver_name,
        "wallet_name": name,
        "wallet_password": pswd
    }
    if master_deriv_key:
        query["master_derivation_key"] = master_deriv_key
    return self.kmd_request("POST", req, data=query)["wallet"]
 

Я уверен, что главный ключ деривации, переданный при вводе, правильный, поскольку я уже проверил его с goal помощью команды из консоли.

Кто-нибудь еще сталкивался с подобной проблемой раньше?

Комментарии:

1. В вашей ошибке указано 400: Bad Request , что ваш SDK выполняет какой-то неправильный запрос к серверу. Обычно это означает, что SDK устарел. Вы проверили, был ли этот sdk недавно разработан в прошлом месяце?

2. Последняя версия. Я думаю, что неправильный запрос в гораздо большей степени связан с тем фактом, что аргумент «master_derivation_key» полностью игнорируется при разборе «запроса» на стороне сервера, что приводит к попытке создать новый кошелек вместо его восстановления, как предложено в документации.

3. Вы также пытались выполнить какую-либо нерабочую команду SDK вручную, выполнив низкоуровневый HTTP-запрос? Например, с помощью requests библиотеки. Может случиться так, что онлайн-документация об API неверна. Тогда единственный способ устранить проблему — обратиться в службу поддержки разработчиков API.

4. Еще не сделано. Допустим, эта работа сейчас не так критична, крайний срок не приближается, поэтому я предпочел сначала запросить сообщество stack-overflow, чтобы убедиться, что есть кто-то еще, кто столкнулся с такой же проблемой, и определить в primis, является ли это ошибкой в SDK. В любом случае, я обязательно сделаю эту попытку позже, чтобы я мог ответить вам и связаться с разработчиками API.

5. Если вы создали все параметры в точном соответствии с документом REST API, то, безусловно, есть ошибка либо в их документации, либо в реализации кода API. Обычно разработчики криптовалют имеют активную поддержку и часто отвечают.

Ответ №1:

Подводя итог, документация Algorand API REST не предлагает явно использовать Master-Derivation-Key для извлечения кошелька при создании POST /v1/wallet (ссылка). И наоборот, документация Algorand для Python SDK предполагает, что ключ Master-Derivation может быть передан create_wallet функции, которая затем выполняет HTTP-сообщение, указанное ранее, для восстановления существующего кошелька (ссылка).

Как объяснялось в моем вопросе выше, create_wallet не удается восстановить кошелек, потому что базовый POST /v1/wallet сбой. По предложению @Arty это было доказано следующим образом:

 curl -X POST -H "X-KMD-API-Token: <kmd-token>" -H "Content-Type: application/json" -d '{"wallet_driver_name": "sqlite", "wallet_name": <wallet-name>, "wallet_password": <wallet-password>, "master_derivation_key": <master-derivation-key>}' <kmd-address-and-port>/v1/wallet
 

который вернул

 { "error": true, "message": "wallet with same name already exists" }
 

Я уведомил об этой проблеме службу поддержки Algorand и в настоящее время жду ответа. В любом случае, чтобы придать некоторый смысл названию вопроса, я хочу поделиться другим возможным решением для восстановления кошелька, по-прежнему полагаясь на Python SDK:

 from algosdk import kmd
from algosdk import wallet
from algosdk import mnemonic

kmd_clt = kmd.KMDClient(<kmd-token>, <kmd-address-and-port>)
if kmd_clt:
    kmd_wlt_mdk = None
    kmd_wlt_list = kmd_clt.list_wallets()
    for kmd_wlt in kmd_wlt_list:
        kmd_name = kmd_wlt['name']
        kmd_id = kmd_wlt['id']
        if kmd_name == <wallet-name>:
            kmd_wlt_hdl = kmd_clt.init_wallet_handle(kmd_id, <wallet-password>)
            if kmd_wlt_hdl:
                kmd_wlt_mdk = kmd_clt.export_master_derivation_key(kmd_wlt_hdl, <wallet-password>)
            break
    if kmd_wlt_mdk:
        wlt = wallet.Wallet(<wallet-name>, <wallet-password>, kmd_clt, mdk=kmd_wlt_mdk)
        if wlt:
            acc_addr_list = wlt.list_keys()
            for acc_addr in acc_addr_list:
                account_address = acc_addr
                print(account_address)
                account_key = wlt.export_key(acc_addr)
                print(account_key)
                account_mnemonic = mnemonic.from_private_key(account_key)
                print(account_mnemonic)
 

Я надеюсь, что это будет полезно кому-то еще в будущем.