Discussion:
[bitcoin-dev] BIP draft: OP_CHECKBLOCKATHEIGHT
Luke Dashjr via bitcoin-dev
2016-09-23 09:57:01 UTC
Permalink
This BIP describes a new opcode (OP_CHECKBLOCKATHEIGHT) for the Bitcoin
scripting system to address reissuing bitcoin transactions when the coins they
spend have been conflicted/double-spent.

https://github.com/luke-jr/bips/blob/bip-cbah/bip-cbah.mediawiki

Does this seem like a good idea/approach?

Luke
Russell O'Connor via bitcoin-dev
2016-09-23 13:43:15 UTC
Permalink
I believe Bitcoin currently enjoys the property that during an "innocent"
re-org, i.e. a reorg in which no affected transactions are being double
spent, all affected transactions can always eventually get replayed, so
long as the re-org depth is less than 100.

My concern with this proposed operation is that it would destroy this
property.

On Fri, Sep 23, 2016 at 5:57 AM, Luke Dashjr via bitcoin-dev <
Post by Luke Dashjr via bitcoin-dev
This BIP describes a new opcode (OP_CHECKBLOCKATHEIGHT) for the Bitcoin
scripting system to address reissuing bitcoin transactions when the coins they
spend have been conflicted/double-spent.
https://github.com/luke-jr/bips/blob/bip-cbah/bip-cbah.mediawiki
Does this seem like a good idea/approach?
Luke
_______________________________________________
bitcoin-dev mailing list
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
Gregory Maxwell via bitcoin-dev
2016-09-23 18:57:57 UTC
Permalink
On Fri, Sep 23, 2016 at 1:43 PM, Russell O'Connor via bitcoin-dev
Post by Russell O'Connor via bitcoin-dev
I believe Bitcoin currently enjoys the property that during an "innocent"
re-org, i.e. a reorg in which no affected transactions are being double
spent, all affected transactions can always eventually get replayed, so long
as the re-org depth is less than 100.
My concern with this proposed operation is that it would destroy this
property.
The reorg safety impact of this proposal could be eliminated and the
mempool handling complexity greatly reduced if the transaction was
required to be locktimed at least 100 blocks after the block its
referencing.

This would also resolve a rather severe DOS weakness that the spec has
with the suggestion that nodes would relay this rule without
validating it. With the depth restriction nodes could relay one (or a
couple) blocks early without creating a situation where someone can
consume relay resources with near zero odds of paying a fee for them.

Irritatingly, applications of this rule would really want to be
applied at signing time (like locktime is), not as part of a
scriptpubkey. With it part of a scriptpubkey two moves are required. I
think solving this is important.

FWIW, this scheme more has been proposed before for another reason--
effectively allowing users to 'vote against' long reorgs by making
sure their transactions can't be included in them. Though for that
application it was only needed to use 32 bits of the block hash.
Peter Todd via bitcoin-dev
2016-09-23 20:02:23 UTC
Permalink
Post by Gregory Maxwell via bitcoin-dev
On Fri, Sep 23, 2016 at 1:43 PM, Russell O'Connor via bitcoin-dev
Post by Russell O'Connor via bitcoin-dev
I believe Bitcoin currently enjoys the property that during an "innocent"
re-org, i.e. a reorg in which no affected transactions are being double
spent, all affected transactions can always eventually get replayed, so long
as the re-org depth is less than 100.
My concern with this proposed operation is that it would destroy this
property.
The reorg safety impact of this proposal could be eliminated and the
mempool handling complexity greatly reduced if the transaction was
required to be locktimed at least 100 blocks after the block its
referencing.
However, by doing that we'd also make the functionality not all that useful for
this application; by the time you waited 100 blocks for the tx to be minable,
the chance of a reorg happening is low enough that I can't imagine many - if
any - wallets would bother using the opcode in the first place, and would
instead just rely on the fact that a reorg that deep which resulted in the
double-spent transaction ending up back in the chain is very unlikely.

Specifically I'm referring to the following scenario:

1) Alice pays Bob with tx1a
2) tx1a gets N confirmations, where N is some small number of confirmations.
2) Bob pays Charlie from tx1a's output in tx2a
3) A reorg eliminates the block that tx1a existed, and a conflicting tx1b is
mined instead, making tx1a and tx2a invalid.
4) Bob pays Charlie again with tx2b, whose inputs do not conflict with tx2a
5) Another reorg eliminates tx1b, allowing tx1a, tx2a, and tx2b to all be
mined.
6) Charlie has now been paid twice.

Since you need _two_ reorgs for this scenario to be applicable, it's much
easier to just wait for tx1b to be confirmed suffiently deeply in the chain
that a reorg undoing it - thus allowing tx1a and tx2a to exist - is
sufficiently unlikely; 100 blocks is a lot more than most wallets are going to
consider "sufficiently unlikely", so the featureu just won't get used (assuming
wallets even bother to handle this case of course!).

Unfortunately I think this is an inherent catch-22 of the idea.
--
https://petertodd.org 'peter'[:-1]@petertodd.org
Luke Dashjr via bitcoin-dev
2016-09-23 22:20:39 UTC
Permalink
In the innocent use case of this opcode, a double-spend has already occurred,
and this should be a strict improvement. In the non-innocent abuse of this
opcode, I don't see that it's any worse than simply double-spending.

Would this proposal be better or otherwise more acceptable, if a specified
height more recent than 100 blocks deep causes the script to fail? This would
increase delays in recovering the double-spend situation of course... but less
than 24h.

Luke
Post by Russell O'Connor via bitcoin-dev
I believe Bitcoin currently enjoys the property that during an "innocent"
re-org, i.e. a reorg in which no affected transactions are being double
spent, all affected transactions can always eventually get replayed, so
long as the re-org depth is less than 100.
My concern with this proposed operation is that it would destroy this
property.
On Fri, Sep 23, 2016 at 5:57 AM, Luke Dashjr via bitcoin-dev <
Post by Luke Dashjr via bitcoin-dev
This BIP describes a new opcode (OP_CHECKBLOCKATHEIGHT) for the Bitcoin
scripting system to address reissuing bitcoin transactions when the coins they
spend have been conflicted/double-spent.
https://github.com/luke-jr/bips/blob/bip-cbah/bip-cbah.mediawiki
Does this seem like a good idea/approach?
Luke
_______________________________________________
bitcoin-dev mailing list
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
Gregory Maxwell via bitcoin-dev
2016-09-23 23:43:49 UTC
Permalink
On Fri, Sep 23, 2016 at 10:20 PM, Luke Dashjr via bitcoin-dev
Post by Luke Dashjr via bitcoin-dev
In the innocent use case of this opcode, a double-spend has already occurred,
and this should be a strict improvement. In the non-innocent abuse of this
opcode, I don't see that it's any worse than simply double-spending.
There is a fungibility hit... right now, absent double spends (and
privacy issues), every coin you might get paid is equal.

With this script feature as described, you could get paid a coin which
has one of these in its recent past, pinning the block immediately
before it. A reorg long enough to remove that block-- due to an
attack, or an ordinary block race, or some kind of consensus glitch
(like we had in March 2013 or around the activation of BIP65)-- is
_guaranteed_ to invalidate those coins, even without any double spend.

If the scheme doesn't do as I suggest and prevent over-eager usage
(perhaps 100 is too much, I just decided to match coinbases); then it
should probably have a consensus enforced explicit "maximum survivable
reorg" that is traced along with the outputs, so that someone who
received exposed coins could handle it sensibly.

Just for plain engineering reasons, I still think it is important to
now allow overly short back references. If the reference has to be a
few blocks back we don't need to worry about short forks breaking
propagation, and simple mempool handling like purging all CBAH
transactions on a large reorg would work fine. It need not be so long
as to implicate Petertodd's concern that you could only use it where
it wouldn't matter. (Though I also disagree that a depth of 100
achieves that, consider persistent chain forks).
Tom via bitcoin-dev
2016-09-23 14:37:39 UTC
Permalink
Post by Luke Dashjr via bitcoin-dev
This BIP describes a new opcode (OP_CHECKBLOCKATHEIGHT) for the Bitcoin
scripting system to address reissuing bitcoin transactions when the coins
they spend have been conflicted/double-spent.
https://github.com/luke-jr/bips/blob/bip-cbah/bip-cbah.mediawiki
Can you walk us through a real live usecase which this solves? I read it and
I think I understand it, but I can't see the attack every giving the attacker
any benefit (or the attacked losing anything).
Luke Dashjr via bitcoin-dev
2016-09-23 22:34:41 UTC
Permalink
Joe sends Alice 5 BTC (UTXO 0).
Fred sends Alice 4 BTC (UTXO 1).
Alice sends Bob 4 BTC using UTXO 1 (creating UTXO 2).
Fred double-spends UTXO 1 with UTXO 1-B. This invalidates Alice's transfer to
Bob.
Alice has UTXO 0 which she can send to Bob (UTXO 3), but if she does so, it is
possible that UTXO 0 could be mined, and then both UTXO 2 and UTXO 3 which
would result in her giving Bob a total of 8 BTC rather than merely 4 BTC.
Even if Alice waits until Fred's UTXO 1-B confirms 10 blocks deep, it is not
impossible for a reorganization to reverse those 10 blocks and confirm UTXO 1
again.
Using OP_CHECKBLOCKATHEIGHT, however, Alice can create UTXO 3 such that it is
valid only in the blockchain where Fred's UTXO 1-B has confirmed. This way, if
that block is reorganized out, UTXO 3 is invalid, and either Bob receives only
the original UTXO 2, or Alice can create a UTXO 3-B which is valid in the
reorganized blockchain if it again confirms the UTXO 1-B double-spend.

Luke
Post by Tom via bitcoin-dev
Post by Luke Dashjr via bitcoin-dev
This BIP describes a new opcode (OP_CHECKBLOCKATHEIGHT) for the Bitcoin
scripting system to address reissuing bitcoin transactions when the coins
they spend have been conflicted/double-spent.
https://github.com/luke-jr/bips/blob/bip-cbah/bip-cbah.mediawiki
Can you walk us through a real live usecase which this solves? I read it
and I think I understand it, but I can't see the attack every giving the
attacker any benefit (or the attacked losing anything).
_______________________________________________
bitcoin-dev mailing list
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
Dave Scotese via bitcoin-dev
2016-09-24 00:08:24 UTC
Permalink
If Alice knows enough to see that she needs CHECKBLOCKATHEIGHT to avoid
paying Bob twice, then she also knows that Fred owes her 4BTC. If Bob
complains about getting paid faster, Alice can let him know that Fred
essentially stole his coins and that when she is certain he (and she) can't
get them back, she will send a different four coins to Bob. If she can
establish trust with Bob (She'd trust Bob to pay her back if he gets back
the coins Fred stole), then she can pay him again. Bob could also make a
transaction to send the first input from Alice back to her (since he
doesn't have those coins anyway), sign it, and send that to her. She can
then keep it instead of having to use the new opcode.

Or she can let her wallet use the new opcode so that the logic is built in,
if we add this opcode. Wallet makers who want to help solve this problem
can either implement the new opcode, or they can offer people like Bob the
ability to refund orphaned transactions so that they can be duplicated in
the valid chain without any risk to the original sender.

With the opcode, Alice can solve the problem by herself. Without it, Bob
can solve it for Alice.

While the opcode adds complexity, it enables victims of double-spends to
pay untrusted creditors (Bob) without the risk that orphaned chains create
of paying them twice. I'm not sure the added complexity is worth the
reward. The reward is to protect Bitcoiners (Alice) from people we'd call
"untrusted creditors" (Bob) and I think that might be a mistake. Getting a
refund transaction signed and sent back to Alice is similar to how the LN
will work (where wallets hold transactions that they don't broadcast).

Am I understanding this correctly?

On Fri, Sep 23, 2016 at 3:34 PM, Luke Dashjr via bitcoin-dev <
Post by Luke Dashjr via bitcoin-dev
Joe sends Alice 5 BTC (UTXO 0).
Fred sends Alice 4 BTC (UTXO 1).
Alice sends Bob 4 BTC using UTXO 1 (creating UTXO 2).
Fred double-spends UTXO 1 with UTXO 1-B. This invalidates Alice's transfer to
Bob.
Alice has UTXO 0 which she can send to Bob (UTXO 3), but if she does so, it is
possible that UTXO 0 could be mined, and then both UTXO 2 and UTXO 3 which
would result in her giving Bob a total of 8 BTC rather than merely 4 BTC.
Even if Alice waits until Fred's UTXO 1-B confirms 10 blocks deep, it is not
impossible for a reorganization to reverse those 10 blocks and confirm UTXO 1
again.
Using OP_CHECKBLOCKATHEIGHT, however, Alice can create UTXO 3 such that it is
valid only in the blockchain where Fred's UTXO 1-B has confirmed. This way, if
that block is reorganized out, UTXO 3 is invalid, and either Bob receives only
the original UTXO 2, or Alice can create a UTXO 3-B which is valid in the
reorganized blockchain if it again confirms the UTXO 1-B double-spend.
Luke
Post by Tom via bitcoin-dev
Post by Luke Dashjr via bitcoin-dev
This BIP describes a new opcode (OP_CHECKBLOCKATHEIGHT) for the Bitcoin
scripting system to address reissuing bitcoin transactions when the
coins
Post by Tom via bitcoin-dev
Post by Luke Dashjr via bitcoin-dev
they spend have been conflicted/double-spent.
https://github.com/luke-jr/bips/blob/bip-cbah/bip-cbah.mediawiki
Can you walk us through a real live usecase which this solves? I read it
and I think I understand it, but I can't see the attack every giving the
attacker any benefit (or the attacked losing anything).
_______________________________________________
bitcoin-dev mailing list
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
_______________________________________________
bitcoin-dev mailing list
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
--
I like to provide some work at no charge to prove my value. Do you need a
techie?
I own Litmocracy <http://www.litmocracy.com> and Meme Racing
<http://www.memeracing.net> (in alpha).
I'm the webmaster for The Voluntaryist <http://www.voluntaryist.com> which
now accepts Bitcoin.
I also code for The Dollar Vigilante <http://dollarvigilante.com/>.
"He ought to find it more profitable to play by the rules" - Satoshi
Nakamoto
Tom via bitcoin-dev
2016-09-24 09:37:52 UTC
Permalink
Thank you Luke, this makes it clearer.

It doesn't change that this scenario is an attack that doesn't give the
attacker any benefit and the attacked doesn't loose anything either (as
Dave pointed out).

This is a completely academical problem that assumes so many stupid
mistakes from software and from people that its very unlikely. On top of
that it assumes a rather lengthy 51% attack in concert with this already
extremely unlikely usecase.

In the scenario you assume stupid people and then you solve it by requiring
the victim to suddenly be super smart and use a solution specifically
designed for this super unlikely usecase that probably will never actually
happen...

I don't buy it.
Post by Luke Dashjr via bitcoin-dev
Joe sends Alice 5 BTC (UTXO 0).
Fred sends Alice 4 BTC (UTXO 1).
Alice sends Bob 4 BTC using UTXO 1 (creating UTXO 2).
Fred double-spends UTXO 1 with UTXO 1-B. This invalidates Alice's
transfer to Bob.
Alice has UTXO 0 which she can send to Bob (UTXO 3), but if she does so,
it is possible that UTXO 0 could be mined, and then both UTXO 2 and UTXO
3 which would result in her giving Bob a total of 8 BTC rather than
merely 4 BTC. Even if Alice waits until Fred's UTXO 1-B confirms 10
blocks deep, it is not impossible for a reorganization to reverse those
10 blocks and confirm UTXO 1 again.
Using OP_CHECKBLOCKATHEIGHT, however, Alice can create UTXO 3 such that
it is valid only in the blockchain where Fred's UTXO 1-B has confirmed.
This way, if that block is reorganized out, UTXO 3 is invalid, and
either Bob receives only the original UTXO 2, or Alice can create a UTXO
3-B which is valid in the reorganized blockchain if it again confirms
the UTXO 1-B double-spend.
Luke
Post by Tom via bitcoin-dev
Post by Luke Dashjr via bitcoin-dev
This BIP describes a new opcode (OP_CHECKBLOCKATHEIGHT) for the Bitcoin
scripting system to address reissuing bitcoin transactions when the
coins they spend have been conflicted/double-spent.
https://github.com/luke-jr/bips/blob/bip-cbah/bip-cbah.mediawiki
Can you walk us through a real live usecase which this solves? I read
it and I think I understand it, but I can't see the attack every
giving the attacker any benefit (or the attacked losing anything).
_______________________________________________
bitcoin-dev mailing list
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
Peter Todd via bitcoin-dev
2016-09-23 16:18:17 UTC
Permalink
Post by Luke Dashjr via bitcoin-dev
This BIP describes a new opcode (OP_CHECKBLOCKATHEIGHT) for the Bitcoin
scripting system to address reissuing bitcoin transactions when the coins they
spend have been conflicted/double-spent.
https://github.com/luke-jr/bips/blob/bip-cbah/bip-cbah.mediawiki
Does this seem like a good idea/approach?
Your BIP is a bit confusing: you say "In some circumstances, users may wish to
spend received bitcoins before they have confirmed on the blockchain", but what
you're really referring to isn't spending unconfirmed outputs - which
OP_CHECKBLOCKATHEIGHT can't protect - but rather spending outputs with a small
number of confirmations.

In the existing ecosystem, if multi-block reorgs were a regular event Bitcoin
would be in a lot of trouble; since they're rare, advising wallet authors to
simply refuse to make transactions for some time after such a reorg may be a
better solution. After all, a multi-block reorg is a strong indication that
there's somehting very wrong with the network, and it'd be safer to stop using
Bitcoin for awhile until things settle down.
--
https://petertodd.org 'peter'[:-1]@petertodd.org
Rusty Russell via bitcoin-dev
2016-10-01 04:01:04 UTC
Permalink
Post by Luke Dashjr via bitcoin-dev
This BIP describes a new opcode (OP_CHECKBLOCKATHEIGHT) for the Bitcoin
scripting system to address reissuing bitcoin transactions when the coins they
spend have been conflicted/double-spent.
https://github.com/luke-jr/bips/blob/bip-cbah/bip-cbah.mediawiki
Does this seem like a good idea/approach?
Prefer a three-arg version (gbits-to-compare, blocknum, hash):
- If <bits> is 0 or > 256, invalid.
- If the hash length is not (<bits> + 7) / 8, invalid.
- If the hash unused bits are not 0, invalid.
- Otherwise <bits> of hash is compared to lower <bits> of blockhash.

This version also lets you play gambling games on-chain!

Or maybe I've just put another nail in CBAH's coffin?

Cheers,
Rusty.
Luke Dashjr via bitcoin-dev
2016-10-01 05:02:09 UTC
Permalink
Post by Rusty Russell via bitcoin-dev
- If <bits> is 0 or > 256, invalid.
- If the hash length is not (<bits> + 7) / 8, invalid.
This means zero padding on-chain, which would be undesirable.
Rather "at most" and have the consensus implementation do the padding.
Post by Rusty Russell via bitcoin-dev
- If the hash unused bits are not 0, invalid.
Why?
Post by Rusty Russell via bitcoin-dev
- Otherwise <bits> of hash is compared to lower <bits> of blockhash.
Lower in what endian? Why only that endian? Why only lower? I can see a
possible use case where one wants to look at only the high bits to ensure
their transaction is only valid in a block with at least a certain
difficulty...
Post by Rusty Russell via bitcoin-dev
This version also lets you play gambling games on-chain!
Or maybe I've just put another nail in CBAH's coffin?
Or maybe resurrected it...

Luke
Nathan Cook via bitcoin-dev
2016-10-05 02:15:36 UTC
Permalink
On 1 October 2016 at 08:02, Luke Dashjr via bitcoin-dev <
Post by Luke Dashjr via bitcoin-dev
Post by Rusty Russell via bitcoin-dev
- Otherwise <bits> of hash is compared to lower <bits> of blockhash.
Lower in what endian? Why only that endian? Why only lower? I can see a
possible use case where one wants to look at only the high bits to ensure
their transaction is only valid in a block with at least a certain
difficulty...
Why not use segwit versioning for all this stuff? That lets you re-enable
the bitwise operations like OP_AND, permitting arbitrary bit-masks.
Further, the "at least a certain difficulty" problem suggests a solution by
extending the validity of opcodes like OP_LESSTHAN etc. to 256-bit inputs.
Loading...