substrate icon indicating copy to clipboard operation
substrate copied to clipboard

Timelock support for transactions

Open nazar-pc opened this issue 3 years ago • 8 comments

Currently Substrate doesn't seem to support notion that is equivalent to Bitcoin's timelock, meaning preventing transaction from being included in the block until certain block height. Transaction can only be valid (and included in the block) or not valid (and removed from transaction pool).

Would be handy to have such support for certain edge-cases though. Some dependencies can be expressed with provides/requires, but if the only dependency is block number then suddenly it is not possible to express.

nazar-pc avatar May 16 '22 08:05 nazar-pc

Would this not bloat the tx-pool? This would also not guarantee that your TX gets included in that block, in case the block is already full.
I think the best solution currently is to use the scheduler schedule call, which takes a when: BlockNumber argument and executes your TX not before that block.

ggwpez avatar May 16 '22 09:05 ggwpez

I don't get this, you can just send the transaction after the required block? Than you ensure that it isn't included before.

bkchr avatar May 16 '22 09:05 bkchr

Would this not bloat the tx-pool?

Not more than any other transaction, also longevity is still a thing.

This would also not guarantee that your TX gets included in that block, in case the block is already full.

Of course, it is fine.

I think the best solution currently is to use the scheduler schedule call, which takes a when: BlockNumber argument and executes your TX not before that block.

It doesn't work if we're talking about unsigned extrinsics that might become invalid by the time BlockNumber is actually reached.

I don't get this, you can just send the transaction after the required block? Than you ensure that it isn't included before.

I'd really like the transaction to be propagated across network in the meantime or else if the delay is just one block, there is a pretty good chance it will not reach next block author in time.

More specifically if current block is N I'd like to submit an unsigned extrinsic that will be valid for block N+2 only (if it fits in the block of course).

nazar-pc avatar May 16 '22 09:05 nazar-pc

In sassafras, we envision users sending tx directly to the slot where they want the tx posted.

As a similar aurababe hack, users could send a tx directly to the node with the aura secondary slot they like along with a "do not gossip until height N" message, so then they've a 75% chance the aura secondary slot occurs, and if the arua secondary slot gets replaced by a babe primary slot then the aura node could gossip the tx.

In this form, we've no assurances the tx occurs only after this height, but it avoids memepool bloat and even saves memepool size 75% of the time.

We could separately do an on-chain limiter like proposed here, which yes improves things, but if were worried about memepool bloat then we could simply choose to do the off-chain part first.

We're starting sassafras spec work soon-ish so this could be bumped up earlier in the pipeline, and maybe generalized to aurababe although not sure about that part.

burdges avatar May 16 '22 12:05 burdges

Would be handy to have such support for certain edge-cases though. Some dependencies can be expressed with provides/requires, but if the only dependency is block number then suddenly it is not possible to express.

We could probably support custom "provides". Maybe provided by the runtime. So, it could then for example return encode("block_number") ++ encode(current_block_number). In your signed extension you could then support this custom provides and insert it as required.

bkchr avatar May 16 '22 19:05 bkchr

We could probably support custom "provides". Maybe provided by the runtime.

Yeah, I thought that might be the most natural way of doing it.

nazar-pc avatar May 17 '22 06:05 nazar-pc

A custom signed extension can certainly achieve this, either in a more rudimentary way, or by using the existing providers method.

By rudimentary, I mean, you can simply have a an extra BlockNumber in your transaction and if this is not met, TransactionValidity::Future (IIRC) is returned.

This basically makes a subset of what scheduler does available to all accounts.

I am not entirely sure if allowing this is safe.

kianenigma avatar Oct 14 '22 16:10 kianenigma

Would this not bloat the tx-pool? This would also not guarantee that your TX gets included in that block, in case the block is already full. I think the best solution currently is to use the scheduler schedule call, which takes a when: BlockNumber argument and executes your TX not before that block.

scheduler is not really meant to be used by any origin IMO and is only for special origins.

kianenigma avatar Oct 14 '22 16:10 kianenigma