Tribler / anydex-core

The Universal Decentralized Exchange
GNU Lesser General Public License v3.0
9 stars 6 forks source link

Cannot trade dummy coins #40

Closed rahimklaber closed 4 years ago

rahimklaber commented 4 years ago

I am trying to trade dummy coins between two computers. Every time I try, I get one of these two errors. I tried trading between a windows and an ubuntu machine and between a windows and arch machine.

INFO:MarketTestnetCommunity:Inserting tick <Ask P: 1.000000, Q: 10 DUM1, O: 8a0e5a3cb1cfa273111bfae72950c651ddfc4abe.2> from 8a0e5a3cb1cfa273111bfae7295
0c651ddfc4abe.2, asset pair: 10 DUM1 10 DUM2
INFO:MarketTestnetCommunity:Sending match message for order id 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14.1 and tick order id 8a0e5a3cb1cfa273111bfae72950
c651ddfc4abe.2 to trader 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14
INFO:MarketTestnetCommunity:Sending match message for order id 8a0e5a3cb1cfa273111bfae72950c651ddfc4abe.2 and tick order id 6b218e7fd93c78d3bf7bb43c4f79
25e8fa2f2e14.1 to trader 8a0e5a3cb1cfa273111bfae72950c651ddfc4abe
INFO:TrustChainCommunity:Received crawl request from node b'f9379cf2' for range -1--1
INFO:TrustChainCommunity:Sent 1 blocks
ERROR:MarketTestnetCommunity:Task resulted in error: '>=' not supported between instances of 'Price' and 'Price'
INFO:TrustChainCommunity:Signed block to b'30303030' (Block b'7902134c' from ...b'f0fd55f8':1 links ...b'30303030':0 for {'tick': {'trader_id': 'ac1f1500a78cd34818befe97e658a11495928ef9', 'order_number': 1, 'assets': {'first': {'amount': 10, 'type': 'DUM1'}, 'second': {'amount': 10, 'type': 'DUM2'}}, 'timeout': 3600, 'timestamp': 1589812211204, 'traded': 0}, 'version': 4} type b'bid') validation result (<function ValidationResult.partial_next at 0x7f02591d30e0>, [])
INFO:MarketTestnetCommunity:Bid created with asset pair 10 DUM1 10 DUM2
INFO:MarketTestnetCommunity:Sending match message for order id ac1f1500a78cd34818befe97e658a11495928ef9.1 and tick order id 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14.1 to trader ac1f1500a78cd34818befe97e658a11495928ef9
INFO:MarketTestnetCommunity:We received a match message from 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14 for order ac1f1500a78cd34818befe97e658a11495928ef9.1 (matched against 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14.1)
INFO:MatchCache:Scheduling batch match of order ac1f1500a78cd34818befe97e658a11495928ef9.1
INFO:MatchCache:Processing incoming matches for order ac1f1500a78cd34818befe97e658a11495928ef9.1
INFO:MarketTestnetCommunity:We received a match message from ac1f1500a78cd34818befe97e658a11495928ef9 for order ac1f1500a78cd34818befe97e658a11495928ef9.1 (matched against 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14.1)
INFO:SingleTradeClearingPolicy:Starting crawl of chain of trader 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14
INFO:TrustChainCommunity:Requesting crawl of node b'b5bfecff' (blocks -1 to -1) with id 57829
INFO:TrustChainCommunity:Block validation result <function ValidationResult.partial_next at 0x7f02591d30e0>, [], (Block b'579e5da4' from ...b'b5bfecff':1 links ...b'30303030':0 for {'tick': {'trader_id': '6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14', 'order_number': 1, 'assets': {'first': {'amount': 10, 'type': 'DUM1'}, 'second': {'amount': 10, 'type': 'DUM2'}}, 'timeout': 3600, 'timestamp': 1589812077520, 'traded': 0}, 'version': 4} type b'ask')
INFO:TrustChainCommunity:Received crawl request from node b'b5bfecff' for range -1--1
INFO:TrustChainCommunity:Sent 1 blocks
ERROR:MarketTestnetCommunity:Task resulted in error: 'b"b\'DUM1\'"'
devos50 commented 4 years ago

That's weird, given that I have this exact test as unit test (test_e2e_trade), and there I cannot reproduce this. There's not much information here but I'm suspecting it might be something related to matchmaking. Could you reveal the whole stack trace by editing this line in IPv8, change the self._logger.error to self._logger.exception, and try again?

rahimklaber commented 4 years ago

I changed the line in IPv8 and got these stack traces.

INFO:MarketTestnetCommunity:We received a match message from a654707e2cbae2313ada9caa2cc947bcca022342 for order 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14.6 (matched a
gainst a654707e2cbae2313ada9caa2cc947bcca022342.1)
INFO:MatchCache:Scheduling batch match of order 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14.6
INFO:MatchCache:Processing incoming matches for order 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14.6
INFO:SingleTradeClearingPolicy:Starting crawl of chain of trader a654707e2cbae2313ada9caa2cc947bcca022342
INFO:TrustChainCommunity:Requesting crawl of node b'da5cf256' (blocks -1 to -1) with id 9188
INFO:TrustChainCommunity:Block validation result <function ValidationResult.partial_next at 0x000002A86710CE58>, [], (Block b'd14ad923' from ...b'da5cf256':7 links .
..b'30303030':0 for {'tick': {'trader_id': 'a654707e2cbae2313ada9caa2cc947bcca022342', 'order_number': 5, 'assets': {'first': {'amount': 10, 'type': 'DUM1'}, 'second
': {'amount': 10, 'type': 'DUM2'}}, 'timeout': 3600, 'timestamp': 1589882687662, 'traded': 0}, 'version': 4} type b'ask')
INFO:TrustChainCommunity:Received crawl request from node b'da5cf256' for range -1--1
INFO:TrustChainCommunity:Sent 1 blocks
ERROR:MarketTestnetCommunity:Task resulted in error: 'b"b\'DUM1\'"'
Traceback (most recent call last):
  File "C:\Users\Rahim\Miniconda3\envs\anydex-core\lib\site-packages\pyipv8-2.0.0-py3.7.egg\ipv8\taskmanager.py", line 123, in done_cb
    future.result()
  File "C:\Users\Rahim\Desktop\anydex-core\anydex\core\community.py", line 1618, in received_accept_trade
    incoming_address, outgoing_address = self.get_order_addresses(order)
  File "C:\Users\Rahim\Desktop\anydex-core\anydex\core\community.py", line 594, in get_order_addresses
    return (WalletAddress(self.wallets[order.assets.first.asset_id].get_address()),
KeyError: 'b"b\'DUM1\'"'
INFO:MarketTestnetCommunity:Sending match message for order id a654707e2cbae2313ada9caa2cc947bcca022342.2 and tick order id 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14.
1 to trader a654707e2cbae2313ada9caa2cc947bcca022342
INFO:TrustChainCommunity:Received crawl request from node b'da5cf256' for range -1--1
INFO:TrustChainCommunity:Sent 1 blocks
ERROR:MarketTestnetCommunity:Task resulted in error: '<=' not supported between instances of 'Price' and 'Price'
Traceback (most recent call last):
  File "C:\Users\Rahim\Miniconda3\envs\anydex-core\lib\site-packages\pyipv8-2.0.0-py3.7.egg\ipv8\taskmanager.py", line 123, in done_cb
    future.result()
  File "C:\Users\Rahim\Desktop\anydex-core\anydex\core\community.py", line 1436, in received_proposed_trade
    result = await self.should_accept_propose_trade(peer, proposed_trade, order)
  File "C:\Users\Rahim\Desktop\anydex-core\anydex\core\community.py", line 1467, in should_accept_propose_trade
    elif not my_order.has_acceptable_price(proposed_trade.assets):
  File "C:\Users\Rahim\Desktop\anydex-core\anydex\core\order.py", line 293, in has_acceptable_price
    my_price <= other_price or abs(float(my_price.frac - other_price.frac)) < 0.0001)) or (
TypeError: '<=' not supported between instances of 'Price' and 'Price'

I changed the __le__ method of Price to:

    def __le__(self, other):
        if isinstance(other, Price) and self.num_type == other.num_type and self.denom_type == other.denom_type:
            return self.amount <= other.amount
        else:
            print(self) #line i added
            print(other) #line i added
            return NotImplemented

and got this back :

1 b'b"b\'DUM2\'"'/b'b"b\'DUM1\'"'
1 b'DUM2'/b'DUM1'

I also tried placing an order and then retrieving it via the api and got this:

{
   "orders":[
      {
         "trader_id":"6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14",
         "order_number":1,
         "assets":{
            "first":{
               "amount":10,
               "type":"b'DUM1'"
            },
            "second":{
               "amount":10,
               "type":"b'DUM2'"
            }
         },
         "reserved_quantity":0,
         "traded":0,
         "timeout":3600,
         "timestamp":1589884778564,
         "completed_timestamp":null,
         "is_ask":true,
         "cancelled":false,
         "status":"open"
      },
      {
         "trader_id":"6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14",
         "order_number":2,
         "assets":{
            "first":{
               "amount":10,
               "type":"b'DUM1'"
            },
            "second":{
               "amount":10,
               "type":"b'DUM2'"
            }
         },
         "reserved_quantity":0,
         "traded":0,
         "timeout":3600,
         "timestamp":1589884812204,
         "completed_timestamp":null,
         "is_ask":true,
         "cancelled":false,
         "status":"open"
      }
   ]
}

The type here also contains b so I have a feeling that somewhere bytes are not being decoded correctly.

rahimklaber commented 4 years ago

I also tried running the test_e2e_trade and it passed, so that's weird.

devos50 commented 4 years ago

It seems indeed to be an encoding issue of the asset type. Are you placing your order using the REST API? If so, how are you doing that?

rahimklaber commented 4 years ago

Yes i am using the REST API. I was using Advanced rest client (api testing tool) to make the requests. I also tried making the requests using these two curl commands : curl -X PUT http://localhost:8090/asks --data "first_asset_amount=10&second_asset_amount=10&first_asset_type=DUM1&second_asset_type=DUM2" curl -X PUT http://localhost:8090/bids --data "first_asset_amount=10&second_asset_amount=10&first_asset_type=DUM1&second_asset_type=DUM2" but the problem persists.

devos50 commented 4 years ago

Ok, I think the issue is then related to the REST API, which would explain why the issue does not trigger in the tests (since the tests are not using the REST API). IIRC, the POST request parameters are parsed by asyncio as bytes, see here. So, if first_asset_type turns out to be bytes, could try to decode the assets type at the code that I linked (both the first one and the second one), and try again?

rahimklaber commented 4 years ago

It seems to be fine there. I tried to decode first_asset_type and second_asset_type, but it turns out that they are strings. I also tried printing them and they seemed fine. The AssetAmount class also checks if asset_id is a string, so the problems seems to originate form somewhere else.

rahimklaber commented 4 years ago

Apperently the asset_type is returned as bytes from the database. The from_database function of the order class seems to be the problem.str(asset1_type)) and str(asset2_type)) convert the bytes to string without decoding them, which results in the b prefix. I decoded asset1_type and asset2_type and I get the asset_type in the correct format (without b) when making a request to the orders endpoint.

This didn't fix the entire issue though, I now get this error when trying to trade:

INFO:MarketTestnetCommunity:Received wallet info from trader 6b218e7fd93c78d3bf7bb43c4f7925e8fa2f2e14
INFO:MarketTestnetCommunity:Wallet info exchanged for transaction 42dd3762146ff1441f065fa8296c99062da3ae39382601e648dab4a6f31bf7aa - starting payments
ERROR:asyncio:Exception in callback TaskManager.register_task.<locals>.done_cb(<Task finishe...or("b'DUM2'")>) at /usr/local/lib/python3.7/dist-packages/pyipv8-2.1.0-py3.7.egg/ipv8/taskmanager.py:120
handle: <Handle TaskManager.register_task.<locals>.done_cb(<Task finishe...or("b'DUM2'")>) at /usr/local/lib/python3.7/dist-packages/pyipv8-2.1.0-py3.7.egg/ipv8/taskmanager.py:120>
Traceback (most recent call last):
  File "/usr/lib/python3.7/asyncio/events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
  File "/usr/local/lib/python3.7/dist-packages/pyipv8-2.1.0-py3.7.egg/ipv8/taskmanager.py", line 123, in done_cb
    future.result()
  File "/home/ubuntu/anydex-core/anydex/core/community.py", line 1714, in send_payment
    wallet = self.wallets[asset_id]
KeyError: "b'DUM2'"

I find this weird as the send_payment function uses the database to find a order and the database uses the from_database function of the order class (which I fixed) to return an order object, see here and here

devos50 commented 4 years ago

Good find! The asset_type is stored as TEXT in the sqlite database, so it will return a string indeed in Python 3. This might be something we missed when migrating from Python 2 to Python 3 recently.

One thing you could try is to hook up a real database in test_e2e_trade and see if you can reproduce it + fix it. See here how to do so. Unfortunately, I don't have much time to help you further with this currently, but a PR for what you found would be greatly appreciated! 👍

rahimklaber commented 4 years ago

Allright I will try to figure it out.

devos50 commented 4 years ago

Managed to reproduce this issue with a unit test! Debugging...

devos50 commented 4 years ago

Should be fixed by #42 , please let me know if it isn't.

rahimklaber commented 4 years ago

I haven't gotten trades to work between dummy wallets. I assume this is a problem on my end and that it should work since I got trades to work between stellar and ethereum. While the trade goes through and the funds are transferred, I did get this error:

ERROR:asyncio:Exception in callback MarketCommunity.process_tx_payment_block.<locals>.on_tx_done_signed(<Task finishe...public_key'")>) at C:\Users\Rahim\Desktop\anydex-core\anydex\core\community.py:703
handle: <Handle MarketCommunity.process_tx_payment_block.<locals>.on_tx_done_signed(<Task finishe...public_key'")>) at C:\Users\Rahim\Desktop\anydex-core\anydex\core\community.py:703>
Traceback (most recent call last):
  File "C:\Users\Rahim\Miniconda3\envs\anydex-core\lib\asyncio\events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
  File "C:\Users\Rahim\Desktop\anydex-core\anydex\core\community.py", line 707, in on_tx_done_signed
    block = future.result()
  File "C:\Users\Rahim\Desktop\anydex-core\anydex\core\community.py", line 1106, in create_new_tx_done_block
    blocks = await self.trustchain.sign_block(peer, peer.public_key.key_to_bin(),
AttributeError: 'NoneType' object has no attribute 'public_key'
rahimklaber commented 4 years ago

I will try to get trades between dummy wallets to work and see if I also get the error then.