eosnetworkfoundation / mandel

Obsolete. Use https://github.com/AntelopeIO/leap instead.
Other
87 stars 27 forks source link

Retry API response returns error message even though transaction succeeded #801

Closed aaroncox closed 2 years ago

aaroncox commented 2 years ago

It seems that if the value of retry_trx_num_blocks and the value of the transaction's expiration are close to one another, or the expiration is beyond the retry_trx_num_blocks value, the API will successfully propagate the transaction and it will succeed, but return an error message back in the API response.

This may cause some interfaces to display an error to users about a failed transaction, when in reality the transaction succeeded. The user will then potentially repeat the transaction leading to undesired results (e.g. duplicate payments).

The error response is inconsistent as well, it'll alternate between "duplicate transaction" and "transaction expired" - neither of which are true since the transaction was successful.

The error response also waits to be returned the roughly 60 seconds it takes for the 120 blocks to pass.

Some examples:


Situation: Transaction was successful, API returned error

Transaction Expire Seconds: 60 seconds retry_trx_num_blocks: 120 Error response from API: expired_tx_exception: Expired Transaction at /v1/chain/send_transaction2

Transaction: https://jungle4.eosq.eosnation.io/tx/498c3130c7763700493cd0de1e932e914f207a0c810ab6238b55c69307fb5d71


Situation: Same parameters as above, different error response. Transaction was successful, API returned error

Transaction Expire Seconds: 60 seconds retry_trx_num_blocks: 120

Error response from API: tx_duplicate: Duplicate transaction at /v1/chain/send_transaction2

Transaction: https://jungle4.eosq.eosnation.io/tx/ce982ea70d1c4e8c7cb2b6a9adf2cccfd1ee5616fe330b271c43cac8ab33407a


Ideally, two changes to how the retry feature works would be good here:

If it's helpful, I do have a reproducible version of this issue in our core TypeScript library. Here's how you can run one of our unittests against Jungle4 which creates the issue:

git clone https://github.com/greymass/eosio-core.git
cd eosio-core
git checkout retry-bug-example
yarn install --force --frozen-lockfile
MOCK_RECORD=overwrite grep="retry" make test

This will perform the unittest located here:

https://github.com/greymass/eosio-core/blob/c39a1644aca03e7d9052bb7a7f346d8873e4df23/test/api.ts#L306-L309

Against EOS Nations Jungle4 API (https://jungle4.api.eosnation.io), which is running the default values for the new retry feature.

The transaction its submitting is being generated with a 60 second expiration here:

https://github.com/greymass/eosio-core/blob/c39a1644aca03e7d9052bb7a7f346d8873e4df23/test/utils/mock-transfer.ts#L16

aaroncox commented 2 years ago

Just as a note, I edited the original issue to update the reproduction steps using our unit tests, so it includes a git checkout retry-bug-example. Omitting that wouldn't do anything, since that test isn't in the master branch, and I just caught that today upon reviewing what I submitted 😅

Full instructions using our JS lib are now:

git clone https://github.com/greymass/eosio-core.git
cd eosio-core
git checkout retry-bug-example
yarn install --force --frozen-lockfile
MOCK_RECORD=overwrite grep="retry" make test
heifner commented 2 years ago

This turned out to be a mis-configured nginx proxy causing transactions to be re-sent after a timeout generating misleading responses.