bitshares / python-bitshares

Fully featured client-side library for the BitShares Blockchain - written entirely in python.
http://docs.pybitshares.com/
MIT License
162 stars 167 forks source link

Need a better way to choose keys to sign transaction #46

Closed HarukaMa closed 2 years ago

HarukaMa commented 6 years ago

https://github.com/xeroc/python-bitshares/blob/c7f98992f5a275b6fb529972f8239e409f74e8c8/bitshares/transactionbuilder.py#L218-L237

In this piece of code, the library will try to add all available keys and sign using all of them later. This could cause "unnecessary signature" error from api nodes if too many keys are chosen.

xeroc commented 6 years ago

I have noticed that myself but wasnt able to reproduce just yet. Can you?

HarukaMa commented 6 years ago

I've been reproducing it in development, but will prepare a more general one soon.

HarukaMa commented 6 years ago
In [1]: from bitshares.transactionbuilder import TransactionBuilder
   ...: from bitsharesbase.operations import Transfer

In [2]: from bitshares import BitShares

In [3]: b = BitShares(node="wss://b.mrx.im/ws")

In [4]: tx = TransactionBuilder(bitshares_instance=b)
   ...: tx.appendOps(Transfer(**{
   ...:          "fee": {"amount": 0, "asset_id": "1.3.0"},  # will be filled in automatically
   ...:          "from": "1.2.422958",
   ...:          "to": "1.2.21561",
   ...:          "amount": {"amount": 1, "asset_id": "1.3.0"},
   ...:          "memo": ""
   ...:      }))
   ...:

In [5]: tx.appendSigner("1.2.422958", "active")

In [6]: tx.wifs
Out[6]:
{'5J9...',
 '5JK...'}

In [7]: tx.sign()

In [8]: tx.broadcast()
---------------------------------------------------------------------------
RPCError                                  Traceback (most recent call last)
...
UnhandledRPCError: {'id': 9, 'jsonrpc': '2.0', 'error': {'code': 1, 'message': 'irrelevant signature included: Unnecessary signature(s) detected', 'data': {'code': 3030004, 'name': 'tx_irrelevant_sig', 'message': 'irrelevant signature included', 
... 
'sigs': ['BTS7mXAGwyvvouxQ5iDUUgT9DfRBhjCjwhxwZAsVKSsTQyfH2WKjV', 'BTS888UG7kiWCDwHNFqGVxCRjWmymBxsV3rMbMaEb8m5Anh7aeyCh'], ...

In [9]: tx
Out[9]: {'expiration': '2018-02-22T10:09:18', 'ref_block_num': 2394, 'ref_block_prefix': 4183133229, 'operations': [[0, {'fee': {'amount': 1662, 'asset_id': '1.3.0'}, 'from': '1.2.422958', 'to': '1.2.21561', 'amount': {'amount': 1, 'asset_id': '1.3.0'}, 'extensions': []}]], 'extensions': [], 'signatures': ['20069d0f41530deefed4ede10b6a71e2589059841aa844ff1e09981fe9a8a3e60f0c3e207b41fc1d02b8d326ef75ba04c6e5d0757cb4d8420e6764294b71a368f4', '2061de52fa3e9ac758b77c6d62a429d79b8f19202acc7ffd3db9333bc42883860f121a51584475c22e73e8e4a7fc7f4921288e1c709c6612fbf1fc6c130e995e1b']}

In [10]: b.rpc.get_object("1.2.422958")
Out[10]:
{'active': {'account_auths': [],
  'address_auths': [],
  'key_auths': [['BTS7mXAGwyvvouxQ5iDUUgT9DfRBhjCjwhxwZAsVKSsTQyfH2WKjV', 1],
   ['BTS888UG7kiWCDwHNFqGVxCRjWmymBxsV3rMbMaEb8m5Anh7aeyCh', 1]],
  'weight_threshold': 1},
...

Apparently only one signature is enough here, but both of the pkeys are used to produce signature.