Re: [bitcoin-dev] maximum block height on transaction

2021-05-02 Thread ZmnSCPxj via bitcoin-dev
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 `0x`.
* 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

Re: [bitcoin-dev] maximum block height on transaction

2021-04-15 Thread ZmnSCPxj via bitcoin-dev
Good morning Billy,


> I've come across this argument before, and it seems kind of like Satoshi's 
> word here is held as gospel. I haven't heard any deep discussion of this 
> topic, and I even asked a question on the bitcoin SE about it. Sorry to 
> hijack this conversation, but I'm very curious if there's something more to 
> this or if the thinking was simply decided that OP_BLOCKNUMBER wasn't useful 
> enough to warrant the (dubious) potential footgun of people accepting 
> sub-6-block transactions from a transaction that uses an expired spend-path?

Another argument I have encountered has to do with the implementation of 
Bitcoin Core.

As an optimization, SCRIPT is evaluated only when a transaction enters the 
mempool.
It is not evaluated at any other time.
Indeed, when accepting a new block, if a transaction in that block is in the 
mempool, its SCRIPT is not re-evaluated.

If the max-blockheight-constraint is implemented as a SCRIPT opcode, then at 
each block, every SCRIPT in every transaction in the mempool must be 
re-evaluated, as the SCRIPT might not reject.
During times of high chain bloat, there will be large numbers of transactions 
in the mempool, only a tiny fraction will be removed at each block before the 
mempool finally clears, leading to effective O(n^2) CPU time spent (n blocks 
are needed in order to empty a mempool with n transactions, each block triggers 
re-evaluation of SCRIPT of n transactions in the mempool).
That O(n^2) assumes a single SCRIPT is O(1), which is untrue as well (but is 
generally approached in practice as most transactions are simple singlesig or 
`OP_CHECKMULTISIG` affairs).

That is, the mempool assumes that once a SCRIPT accepts, it will always accept 
in the future.
Thus, any SCRIPT opcode cannot change from "accept" (because at the current 
blockheight the max-block is not yet reached) to "reject" (because the 
max-block constraint is now violated).

Thus, we cannot use an opcode to impose the max-block cosntraint.

The alternative is to add a new field `maxtime` to the transaction.
Then possibly, we can have an `OP_CHECKMAXTIMEVERIFY` opcode that checks that 
the field has a particular value.
Then the mempool can have a separate index according to `maxtime` fields, where 
it can remove the indexed transactions at each block.
The index will be likely O(log n), and the filtering at each block would be O(n 
log n), which is an improvement.
Note in particular that the index itself would require O(n) storage.

However, adding a new field to the transaction format would require techniques 
similar to what was used in SegWit, i.e. post-maxtime nodes have to "baby talk" 
to pre-maxtime nodes and pretend transactions do not have this field, in much 
the same way post-SegWit nodes "baby talk" to pre-SegWit nodes and pretend 
transactions do not have a `witness` field.
We would then need a third Merkle Tree to hold the "really real" transaction ID 
that contains the `maxtime` field as well.

Thus, it seems to me that the tradeoffs are simply not good enough, when you 
can get 99% of what you need using just another transaction with `nLockTime`:

* 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.
* You can do what you want with a second `nLockTime`d transaction that spends 
the output anyway.

Indeed, it is helpful to realize *why* `OP_CHECKLOCKTIMEVERIFY` and 
`OP_CHECKSEQUENCEVERIFY` work the way they are implemented.
They are typically discussed and described as if they were imposing time-based 
constraints, but the *real* implementation only imposes constraints on 
`nLockTime` and `nSequence` fields --- the SCRIPT interpreter itself does not 
look at the block that the transaction is in (because that is not available, as 
the SCRIPT interpreter is invoked at mempool entry, when the transaction *has* 
no block it is contained in).
There is instead a separate layer (the entry into the mempool) that implements 
the *actual* time-based cosntraints, based on the fields and not the SCRIPT 
opcodes.

Regards,
ZmnSCPxj

>
> On Fri, Apr 9, 2021 at 5:55 AM Jeremy via bitcoin-dev 
>  wrote:
>
> > You could accomplish your rough goal by having:
> >
> > tx A: desired expiry at H
> > tx B: nlocktime H, use same inputs as A, create outputs equivalent to 
> > inputs (have to be sure no relative timelocks)
> >
> > Thus after a timeout the participants in A can cancel the action using TX B.
> >
> > The difference is the coins have to move, without knowing your use case 
> > this may or may not help you. 
> >
> > On Fri, Apr 9, 2021, 4:40 AM Russell O'Connor via bitcoin-dev 
> >  wrote:
> >
> > > From https://bitcointalk.org/index.php?topic=1786.msg22119#msg22119:
> > >

Re: [bitcoin-dev] maximum block height on transaction

2021-04-12 Thread Billy Tetrud via bitcoin-dev
@Russell I think there were sound arguments against Satoshi's statement
made in that very thread. Especially that software can be written to warn
the user about edge cases.

If a person waited for the standard 6 blocks before accepting a transaction
as confirmed, there should be no significantly likely scenario where any
finalized transaction needs to be reverted. If 6 blocks is indeed a safe
threshold for finalization, then any transaction that has 5 or fewer
confirmations should be considered fair game for reversal. I don't agree
that this is "unfair". In fact, I think that's pretty standard, is it not?
Any chain of transactions that happen in the span of 5 blocks shouldn't be
doing anything that expects those transactions to become finalized until
the relevant transactions get 6 confirmations.

I don't think the possibility of buggy software is a good reason to block
an opcode. Not that I'm hankering for OP_BLOCKNUMBER specifically. However,
I think there are good use cases for spend paths that expire (eg for more
effective wallet vaults).

I've come across this argument before, and it seems kind of like Satoshi's
word here is held as gospel. I haven't heard any deep discussion of this
topic, and I even asked a question on the bitcoin SE

about it. Sorry to hijack this conversation, but I'm very curious if
there's something more to this or if the thinking was simply decided that
OP_BLOCKNUMBER wasn't useful enough to warrant the (dubious) potential
footgun of people accepting sub-6-block transactions from a transaction
that uses an expired spend-path?

On Fri, Apr 9, 2021 at 5:55 AM Jeremy via bitcoin-dev <
bitcoin-dev@lists.linuxfoundation.org> wrote:

> You could accomplish your rough goal by having:
>
>
>
> tx A: desired expiry at H
> tx B: nlocktime H, use same inputs as A, create outputs equivalent to
> inputs (have to be sure no relative timelocks)
>
> Thus after a timeout the participants in A can cancel the action using TX
> B.
>
> The difference is the coins have to move, without knowing your use case
> this may or may not help you.
>
> On Fri, Apr 9, 2021, 4:40 AM Russell O'Connor via bitcoin-dev <
> bitcoin-dev@lists.linuxfoundation.org> wrote:
>
>> From https://bitcointalk.org/index.php?topic=1786.msg22119#msg22119:
>>
>> We can't safely do OP_BLOCKNUMBER.  In the event of a block chain reorg
>>> after a segmentation, transactions need to be able to get into the chain in
>>> a later block.  The OP_BLOCKNUMBER transaction and all its dependants would
>>> become invalid.  This wouldn't be fair to later owners of the coins who
>>> weren't involved in the time limited transaction.
>>>
>>> nTimeLock does the reverse.  It's an open transaction that can be
>>> replaced with new versions until the deadline.  It can't be recorded until
>>> it locks.  The highest version when the deadline hits gets recorded.  It
>>> could be used, for example, to write an escrow transaction that will
>>> automatically permanently lock and go through unless it is revoked before
>>> the deadline.  The feature isn't enabled or used yet, but the support is
>>> there so it could be implemented later.
>>>
>>
>> Unfortunately, limiting the maximum block height for a specific
>> transaction would have exactly the same problem as cited above for
>> OP_BLOCKNUMBER.
>>
>> On Fri, Apr 9, 2021 at 7:21 AM Erik Aronesty via bitcoin-dev <
>> bitcoin-dev@lists.linuxfoundation.org> wrote:
>>
>>> is there any way to specify a maximum block height on a transaction?
>>>
>>> ie: this tx is only valid if included in a block with a certain height
>>> or less
>>>
>>> i feel like this would be useful
>>> ___
>>> bitcoin-dev mailing list
>>> bitcoin-dev@lists.linuxfoundation.org
>>> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>>>
>> ___
>> bitcoin-dev mailing list
>> bitcoin-dev@lists.linuxfoundation.org
>> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>>
> ___
> bitcoin-dev mailing list
> bitcoin-dev@lists.linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] maximum block height on transaction

2021-04-09 Thread Jeremy via bitcoin-dev
You could accomplish your rough goal by having:



tx A: desired expiry at H
tx B: nlocktime H, use same inputs as A, create outputs equivalent to
inputs (have to be sure no relative timelocks)

Thus after a timeout the participants in A can cancel the action using TX B.

The difference is the coins have to move, without knowing your use case
this may or may not help you.

On Fri, Apr 9, 2021, 4:40 AM Russell O'Connor via bitcoin-dev <
bitcoin-dev@lists.linuxfoundation.org> wrote:

> From https://bitcointalk.org/index.php?topic=1786.msg22119#msg22119:
>
> We can't safely do OP_BLOCKNUMBER.  In the event of a block chain reorg
>> after a segmentation, transactions need to be able to get into the chain in
>> a later block.  The OP_BLOCKNUMBER transaction and all its dependants would
>> become invalid.  This wouldn't be fair to later owners of the coins who
>> weren't involved in the time limited transaction.
>>
>> nTimeLock does the reverse.  It's an open transaction that can be
>> replaced with new versions until the deadline.  It can't be recorded until
>> it locks.  The highest version when the deadline hits gets recorded.  It
>> could be used, for example, to write an escrow transaction that will
>> automatically permanently lock and go through unless it is revoked before
>> the deadline.  The feature isn't enabled or used yet, but the support is
>> there so it could be implemented later.
>>
>
> Unfortunately, limiting the maximum block height for a specific
> transaction would have exactly the same problem as cited above for
> OP_BLOCKNUMBER.
>
> On Fri, Apr 9, 2021 at 7:21 AM Erik Aronesty via bitcoin-dev <
> bitcoin-dev@lists.linuxfoundation.org> wrote:
>
>> is there any way to specify a maximum block height on a transaction?
>>
>> ie: this tx is only valid if included in a block with a certain height or
>> less
>>
>> i feel like this would be useful
>> ___
>> bitcoin-dev mailing list
>> bitcoin-dev@lists.linuxfoundation.org
>> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>>
> ___
> bitcoin-dev mailing list
> bitcoin-dev@lists.linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] maximum block height on transaction

2021-04-09 Thread Russell O'Connor via bitcoin-dev
>From https://bitcointalk.org/index.php?topic=1786.msg22119#msg22119:

We can't safely do OP_BLOCKNUMBER.  In the event of a block chain reorg
> after a segmentation, transactions need to be able to get into the chain in
> a later block.  The OP_BLOCKNUMBER transaction and all its dependants would
> become invalid.  This wouldn't be fair to later owners of the coins who
> weren't involved in the time limited transaction.
>
> nTimeLock does the reverse.  It's an open transaction that can be replaced
> with new versions until the deadline.  It can't be recorded until it
> locks.  The highest version when the deadline hits gets recorded.  It could
> be used, for example, to write an escrow transaction that will
> automatically permanently lock and go through unless it is revoked before
> the deadline.  The feature isn't enabled or used yet, but the support is
> there so it could be implemented later.
>

Unfortunately, limiting the maximum block height for a specific transaction
would have exactly the same problem as cited above for OP_BLOCKNUMBER.

On Fri, Apr 9, 2021 at 7:21 AM Erik Aronesty via bitcoin-dev <
bitcoin-dev@lists.linuxfoundation.org> wrote:

> is there any way to specify a maximum block height on a transaction?
>
> ie: this tx is only valid if included in a block with a certain height or
> less
>
> i feel like this would be useful
> ___
> bitcoin-dev mailing list
> bitcoin-dev@lists.linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


[bitcoin-dev] maximum block height on transaction

2021-04-09 Thread Erik Aronesty via bitcoin-dev
is there any way to specify a maximum block height on a transaction?

ie: this tx is only valid if included in a block with a certain height or less

i feel like this would be useful
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev