algorand / py-algorand-sdk

Algorand Python SDK
MIT License
266 stars 141 forks source link

kmd.sign_transaction() fails when signing_address is specified #436

Open oysterpack opened 1 year ago

oysterpack commented 1 year ago

algosdk.kmd.sign_transaction() fails when signing_address arg is specified

Expected behaviour

Transaction should be signed using the private key corresponding to the specified signing_address

Actual behaviour

Exception is raised:

algosdk.error.KMDHTTPError: {
  "error": true,
  "message": "could not decode request body"

Steps to reproduce issue

  1. start sandbox environment
  2. Run the below code to reproduce
    
    from pprint import pprint
    from typing import cast

from algosdk import kmd from algosdk.transaction import PaymentTxn from algosdk.v2client.algod import AlgodClient

token = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' kmd_client = kmd.KMDClient(kmd_token=token, kmd_address='http://127.0.0.1:4002') algod_client = AlgodClient(algod_token=token, algod_address='http://127.0.0.1:4001')

suggested_params = algod_client.suggested_params() address = 'XDOV35UGGYEQHHN2UJSW4NQKS3IAFK2PYTGLK2CSUTDTXZ4EVRXTMEONEQ' txn = PaymentTxn(sender=address, receiver=address, amt=0, sp=suggested_params)

def unencrypted_default_wallet_id() -> str: wallets = cast(list[dict[str, str]], kmd_client.list_wallets()) for wallet in wallets: if wallet['name'] == 'unencrypted-default-wallet': return wallet['id'] raise Exception('not found')

wallet_handle = kmd_client.init_wallet_handle(id=unencrypted_default_wallet_id(), password='')

works when signing_address is None

signed_txn = kmd_client.sign_transaction(handle=wallet_handle, password='', txn=txn) print(' SUCCESSFULLY SIGNED TRANSACTION ') pprint(signed_txn.dictify())

print('*** Signing transaction with a signing_address arg fails')

fails when signing_address is specified

signed_txn = kmd_client.sign_transaction(handle=wallet_handle, password='', txn=txn, signing_address=address) # raises exception



### Your environment
py-algorand-sdk==2.0.0

./sandbox version

algod version
12885032963
3.2.3.stable [rel/stable] (commit #d2289a52)
go-algorand is licensed with AGPLv3.0
source code available at https://github.com/algorand/go-algorand

Indexer version
2.8.0-dev.unknown compiled at 2022-01-21T13:24:39+0000 from git hash cf2a3873600a95c5740f0a854ecd3e5636bb4afb (modified)

Postgres version
postgres (PostgreSQL) 13.4
bbroder-algo commented 1 year ago

when I run this test script with the address properly changed I also see the exception algosdk.error.KMDHTTPError: { "error": true, "message": "could not decode request body" }

bbroder-algo commented 1 year ago

I believe the behavior oysterpack is looking for is

import base64
bytes_data = base64.b32decode(address.encode('utf-8') + b'=' * 6)  
signed_txn = kmd_client.sign_transaction(handle=wallet_handle, password='', txn=txn, signing_address=base64.b64encode(bytes_data).decode())

which, if this is the case, should probably be performed by the sdk.

oysterpack commented 1 year ago

That hack works but is very ugly ... according to the SDK docs, a base32 encoded address should work

signing_address (str, optional): sign the transaction with SK corresponding to base32
        signing_address, if provided, rather than SK corresponding to sender

Thus, per the SDK docs, this is a bug.

oysterpack commented 1 year ago

Any updates on this?