Good morning Billy, and list,

> -   Using an opcode would greatly increase CPU usage because the script cache 
> would need to be reworked (and probably cannot be made to work).
> -   Adding a field would greatly increase the code complexity to the level of 
> SegWit, without all the important bugfixes+features (tx malleability, 
> quadratic sighash, well-defined extensible outputs) that SegWit provides.

Sometimes, the only way out is through.

A general idea to get around this would be:

* Define a "hidden" field of a transaction, which is not existent in *any* 
serialization of the transaction.
* Set a default value for this field that would be compatible with pre-softfork 
rules.
* Have an opcode that manipulates this field, carefully designed so it is 
idempotent.

The above general idea is not original to me, I believe.
I think I have seen it elsewhere on the list, possibly in discussions around 
sidechains, though my primary cache is unable to fetch and additional searches 
through unindexed storage is taking too long.

So, for this particular case, here is a (non-serious) proposal to implement a 
maximum block height on transactions.

* Create a new field `u32 nMaxHeight` on `CTransaction` that is not serialized 
in any transaction format.
  * A block is not valid if any transaction in it has an `nMaxHeight` larger 
than the block height of the block.
  * Default value is `0xFFFFFFFF`.
* Add a new opcode `OP_SETMAXHEIGHT` that replaces an existing `OP_NOP`.
  * The opcode must be followed by an `OP_PUSH` of a 32-bit value, else script 
validation fails.
    * This prevents using a computed value, instead the value must be given as 
a constant in the script text.
      This is a precaution to reduce the risk that execution of the script at a 
different time or different computer or etc will result in a different value 
that the `OP_SETMAXHEIGHT` opcode uses, which can cause consensus divergence.
      If we figure out later that this precaution is not necessary, we can just 
use another `OP_NOP` for `OP_SETMAXHEIGHTFROMSTACK`.
  * If the current `nMaxHeight` is larger than the given value, then the 
`nMaxHeight` is set to the given value.

The above avoids issues with opcodes --- the script interpreter can continue to 
be executed in the only place it is in, i.e. at entry into the mempool.
It also avoids some of the code complexity with fields, since the field is 
non-existent in any serialization of the transaction, but is instead implied by 
the scripts that the transaction causes to be executed, reducing the need to 
identify pre-softfork peers and baby-talk to them --- the baby-talk simply 
contains "parental bonuses" that are understood by upgraded nodes who are "in 
the know".

Additional complications, such as the need for an index of `nMaxHeight` for 
transactions in the mempool (to remove transactions whose `nMaxHeight` is now 
in the past), and the additional checks needed when receiving an in-block 
transaction that is not in the mempool, are left to the reader.
Similar field and opcode for `CTransactionInput` for a relative-time max height 
are also left as an exercise to the reader.

> -   You can do what you want with a second `nLockTime`d transaction that 
> spends the output anyway.

The advantage of this functionality is that you can be safely offline at the 
time the timeout occurs in any complicated timeout-based contract.

Typically, when using say an HTLC, the contractor who holds lien on the 
timelock branch, has to be online at the time the timelock becomes valid, in 
order to impose a timeout on the hashlock branch.
However, if instead the hashlock branch includes an `OP_SETMAXHEIGHT`, then the 
contractor holding lien on the timelock branch does not have this risk.

However, the contractor holding the lien on the hashlock branch now has 
increased risk.
If the timeout is approaching, and suddenly there is high mempool usage at the 
time, then a claim of the hashlock branch may fall off the mempool due to 
`nMaxHeight` violation.
But the transaction claiming the hashlock branch has been published and the 
preimage has been published in mempools all over the world, thus the contractor 
holding lien on the hashlock branch risks not being compensated for revelation 
of the preimage.

Whereas with the current way things are, the timelock-holder is at risk, and 
the hashlock-holder has reduced risk since even if the timeout arrives, there 
is still the possibility that the hashlock branch is what gets confirmed, 
whereas with `OP_SETMAXHEIGHT` the hashlock-holder has 0 chance of getting the 
hashlock branch confirmed in case of sudden spike in onchain usaage.

Thus it seems to me that this scheme does not really *improve* Bitcoin 
significantly, it only moves risks from one participant to another in a 
two-participant contract.
Thus, this proposal is not particularly serious.

Regards,
ZmnSCPxj
_______________________________________________
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev

Reply via email to