Brainstorm on default valid window length and lease

The recent zero-transaction blocks on mainnet exposed a gap in some front-ends that did not properly handle transactions taking longer than expected. This lead to end-users accidentally sending the “same” transaction twice which resulted in unintended consequences. To help mitigate this some changes to the SDK could be made

  • Make the default FirstValid/LastValid window smaller than 1000 blocks
  • Automatically generate a lease for application calls based on non-volatile fields (ie. don’t include suggestedParams)
  • Create a function for sending transactions that wait until the LastValid round is reached (in the case of group transactions, use the earliest LastValid)

Providing a function, or at least documentation, for searching the pending pool for similar transactions might also be helpful.

Twitter thread with initial discussion: https://twitter.com/joe_polny/status/1591120544623366145

1 Like

Not sure if adding a default lease would be a good idea, it could bite some people and breaks backwards compatibility. There may be situations where you would legitimately post the “same” txn within the currently “huge” default lifetime, e.g. NFT shuffles.

Changing default lifetime to something more reasonable like 80 (5 min) should be ok except for multisig txns, so this might require user input in some cases

Ultimately it is up to dApp developers to reexamine their params choices

Some notes on improving DX:

  • Add lease to all makeXXXTransaction methods

  • since it isn’t in makePayTxn, it must be added manually. If lease isn’t 32 bytes, the SDK should throw when signing the txn. Currently (with JS sdk) throws when sending txn to Algod with “At least one signature didn’t pass verification”, which is not the appropriate error message.

Not sure if adding a default lease would be a good idea, it could bite some people and breaks backwards compatibility. There may be situations where you would legitimately post the “same” txn within the currently “huge” default lifetime, e.g. NFT shuffles.

Yeah good point, ideally I think we optimize for best user protection in the most common scenarios (ie. DeFi app calls) but realistically I think we should preserve backwards compatibility. Although to be fair, this is a change at the SDK level and not API level. As long as the Dapp doesn’t update their SDK then they won’t be affected.

Edit: And if we did change this it wouldn’t just be a sudden change. Proper deprecation warnings should exist.

since it isn’t in makePayTxn, it must be added manually. If lease isn’t 32 bytes, the SDK throw when signing the txn. Currently (with JS sdk) throws when sending txn to Algod with “At least one signature didn’t pass verification”, which is not the appropriate error message.

To me this is really a bug. That error message is terrible. Can you create an issue on the GitHub?

1 Like

I like reducing the first and third options together:

  1. reducing first/last valid by default or have examples in the documentation doing so at least (reducing by default may break compatibility so maybe the best is to just have very clear examples in documentation)
  2. have a function like waitForConfirmation that distinguishes between “failed for sure and safe to retry with new transaction” and “not yet committed but don’t retry until the end of the last valid”. And have documentation examples on how to properly handle this in the frontend.

If you just have the first, then even with 80 rounds validity, there is a risk people would retry and the issue would still arise.
If you just have the third, then people would need to wait 1h for retrying.

I think this is potentially dangerous: this assumes that the user would redo exactly the same operation if the first one failed. I’m not sure more users do. At least, I know I tend not to, because I think: maybe some parameters I chose are wrong, let me test with others.
So this would not protect me.

Now, I think we may want to provide documentation on how advanced frontends can use leases in the above case. The idea would be that the frontend would ask the user whether the new action requested must be executed in addition to the previous one or not, if you try a new action while another one is pending.

3 Likes

Opened issue on js-algorand-sdk!

2 Likes