Bitcoin Forum
May 28, 2024, 06:24:18 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1] 2 »  All
  Print  
Author Topic: Transaction script with block height as condition  (Read 3189 times)
jl2012 (OP)
Legendary
*
Offline Offline

Activity: 1792
Merit: 1097


View Profile
October 03, 2012, 04:45:45 AM
Last edit: October 03, 2012, 05:00:52 AM by jl2012
 #1

I wonder if a transaction script like this would be allowed: If block height < x, use condition A; if block height >= x, use condition B

This could be very useful as trust-free, zero-confirmation exchange wallet

Assuming the exchange owns private key E, the user owns private key U, and x is the block height of near future (e.g. current block height + 10000), a transaction script would look like this: If block height < x, 2-by-2 multisig with E and U is required; if block height >= x, U is required. A script hash is derived

The user will comfortably send any amount of coins to this script hash. If private key E was compromised, no fund could be stolen. Even if the exchange operator disappeared (like Torwallet), the user could get the coins back after block x.

If the user wants to sell the coins before block x, he will sign a multisig transaction to send the coins to the address of key E (or any other addresses exclusively owned by the exchange). Since it is bound by the multisig requirement before block x, the user is not possible to double spend. Therefore, the BTC is readily available for trading with zero-confirmation.

To avoid the risk of double spend or Finney Attack, the multisig transaction should be signed by the user well before block x is generated, e.g. x - 10. After that, the exchange will not accept it by zero-confirmation. However, it will still accept it after 6 confirmations.

This also works for online wallet providers, stock market, marketplace, or Bitcoinica-type services. It won't totally eliminate the risk, but people could then deposit a large amount of BTC to these services and spend instantly at any time.

EDIT: For a bitcoin buyer, the exchange will send the freshly bought coins to the his script hash. Therefore, the buyer is also protected, while he could also sell the coins instantly.

Donation address: 374iXxS4BuqFHsEwwxUuH3nvJ69Y7Hqur3 (Bitcoin ONLY)
LRDGENPLYrcTRssGoZrsCT1hngaH3BVkM4 (LTC)
PGP: D3CC 1772 8600 5BB8 FF67 3294 C524 2A1A B393 6517
kjj
Legendary
*
Offline Offline

Activity: 1302
Merit: 1025



View Profile
October 04, 2012, 04:47:54 PM
 #2

As far as transactions are concerned, there are no blocks, there is no chain, there is no height.  This is not an accident or an oversight.  Please search next time.

17Np17BSrpnHCZ2pgtiMNnhjnsWJ2TMqq8
I routinely ignore posters with paid advertising in their sigs.  You should too.
jl2012 (OP)
Legendary
*
Offline Offline

Activity: 1792
Merit: 1097


View Profile
October 04, 2012, 05:25:06 PM
 #3

As far as transactions are concerned, there are no blocks, there is no chain, there is no height.  This is not an accident or an oversight.  Please search next time.

I think you totally misunderstand my proposal.

Let me explain this way: A user does not fully trust the exchange but he wants to sell his BTC through the exchange. He wants to transfer the BTC to the exchange at the last minute before he sells. However, the exchange requires 6 confirmations to prevent double-spending.

One way to do this is to have a 2-by-2 multisig account, which the exchange owns one of the keys (E), and the user owns the other key (U). The user will send his BTC to this multisig account. When the user wants to sell the BTC later, he sign a transaction by U to send the BTC in the multisig account to an account owned by the exchange exclusively. The exchange will complete the transaction by signing it with E. Since the user is not possible to double-spend, the exchange can accept it with zero confirmation and the user can sell his BTC immediately.

However, if the exchange is completely disappeared, the BTC in the multi-sig accounts will be lost forever. Therefore, we need some "emergency exit mechanism". When the multisig account is setting up, an additional condition is added: (e.g.) "After 1 Jan 2013, the coins in this account can be spent by signature of key U only". That means in the worst case, if the exchange fails tomorrow, the user can get his coins back after 1 Jan 2013.

Of course, in bitcoin world, time is measured by block height, not days. So the condition becomes "after block height > 220000, the coins in this account can be spent by signature of key U only". If the user tries to spend the coins today (block height = 201800) without involving the exchange, the transaction is considered invalid.

And the following notice explains why we need this system:

Quote
GLBSE is offline

For those worried about their bitcoin, please calm yourselves there has been no hack and your coins are safe and all accounted for.

I apologize for the lack of notice and the downtime, but there isn't much choice. We will update our users on Saturday.

Donation address: 374iXxS4BuqFHsEwwxUuH3nvJ69Y7Hqur3 (Bitcoin ONLY)
LRDGENPLYrcTRssGoZrsCT1hngaH3BVkM4 (LTC)
PGP: D3CC 1772 8600 5BB8 FF67 3294 C524 2A1A B393 6517
Pieter Wuille
Legendary
*
qt
Offline Offline

Activity: 1072
Merit: 1178


View Profile WWW
October 04, 2012, 05:43:37 PM
 #4

Transactions actually do have a rarely-used feature called nLocktime. It can be used to specify the block height or UNIX timestamp after which the transaction is allowed to become stored in the block chain.

I do Bitcoin stuff.
kjj
Legendary
*
Offline Offline

Activity: 1302
Merit: 1025



View Profile
October 04, 2012, 06:18:44 PM
 #5

I think you totally misunderstand my proposal.

No, I got it, I understand what you are saying.  You want a script that knows what time it is (or some proxy for time), and can be valid or not valid based on that time.  It is a bad idea, and there are a whole bunch of threads that explain how and why it is a bad idea.  Don't take it personally, it is a very popular idea, but still a bad one.  Smiley

And the following notice explains why we need this system:

Quote
GLBSE is offline

Your scheme probably won't help here.  If the recipient was hit by a bus, you might have a way to recall the transaction.  But if the recipient is planning to steal your money, they'll redeem the transaction first, making this pointless.

As Pieter points out, there are tools (nLockTime and P2SH) that will eventually be used to accomplish basically the same end goals, and they don't involve adding the idea of time to the script system.

17Np17BSrpnHCZ2pgtiMNnhjnsWJ2TMqq8
I routinely ignore posters with paid advertising in their sigs.  You should too.
Gavin Andresen
Legendary
*
qt
Offline Offline

Activity: 1652
Merit: 2217


Chief Scientist


View Profile WWW
October 04, 2012, 07:02:44 PM
 #6

However, if the exchange is completely disappeared, the BTC in the multi-sig accounts will be lost forever. Therefore, we need some "emergency exit mechanism". When the multisig account is setting up, an additional condition is added: (e.g.) "After 1 Jan 2013, the coins in this account can be spent by signature of key U only".

If you held a pre-signed transaction that sends the funds back to you with a lockTime of 1 Jan 2013 that would work.

Lets see... thinking out loud...

Start by asking the exchange for a brand-new public key to use for their half of the 2-of-2 transaction. Call the send-coins-into-2-of-2 transaction "F" (for Fund).

You create and sign that transaction, but don't broadcast it yet.

Use it's transaction id to create a second, one-input-two-signature, lockTime=1/1/2013 transaction that refunds the coins to you.  Call that "R" (for Refund).

Send R to the exchange and ask them to sign it using that brand-new public key they gave you. The exchange checks the lockTime and then returns R and the signature to you. You check the signature, and if it is good, broadcast F (and keep the half-signed R someplace safe).

If 1/1/2013 rolls around and you want your coins back, you sign your half of R and broadcast it.



I'd have to think a little harder than I want to right now about whether or not signing R knowing only txid==HASH(F) opens up the exchange to attacks. I can't think of any, but the exchange providing a signature when it doesn't know the details of exactly what it is signing makes me nervous.

You could send the unsigned R and the signed-but-not-broadcast F to the exchange and trust that the exchange will not broadcast F unless they agree to sign R.


I think holding on to pre-signed-but-not-broadcast-yet transactions is a technique "we" don't think about enough.

How often do you get the chance to work on a potentially world-changing project?
ByteCoin
Sr. Member
****
expert
Offline Offline

Activity: 416
Merit: 277


View Profile
October 05, 2012, 02:29:55 AM
 #7

If you held a pre-signed transaction that sends the funds back to you with a lockTime of 1 Jan 2013 that would work.
I've been out of the loop for a while.. Does lockTime work correctly nowadays? If not, when is it scheduled to be implemented?

I'd have to think a little harder than I want to right now about whether or not signing R knowing only txid==HASH(F) opens up the exchange to attacks. I can't think of any, but the exchange providing a signature when it doesn't know the details of exactly what it is signing makes me nervous.

Well, the worst case scenario (under plausible assumptions) for the exchange signing something arbitrary with some key is to lose control of (or unwittingly commit to) everything associated with that key, so it's important that the key has not been used for anything else.

Now of course if my proposal about transaction id hashes not including signatures were adopted, then the funding transaction could be sent in its unsigned form to the exchange and the exchange could verify that the refund spent the funding transaction because of course the transaction id wouldn't change on signing.

ByteCoin
jl2012 (OP)
Legendary
*
Offline Offline

Activity: 1792
Merit: 1097


View Profile
October 05, 2012, 02:53:51 AM
 #8

However, if the exchange is completely disappeared, the BTC in the multi-sig accounts will be lost forever. Therefore, we need some "emergency exit mechanism". When the multisig account is setting up, an additional condition is added: (e.g.) "After 1 Jan 2013, the coins in this account can be spent by signature of key U only".

If you held a pre-signed transaction that sends the funds back to you with a lockTime of 1 Jan 2013 that would work.

Lets see... thinking out loud...

Start by asking the exchange for a brand-new public key to use for their half of the 2-of-2 transaction. Call the send-coins-into-2-of-2 transaction "F" (for Fund).

You create and sign that transaction, but don't broadcast it yet.

Use it's transaction id to create a second, one-input-two-signature, lockTime=1/1/2013 transaction that refunds the coins to you.  Call that "R" (for Refund).

Send R to the exchange and ask them to sign it using that brand-new public key they gave you. The exchange checks the lockTime and then returns R and the signature to you. You check the signature, and if it is good, broadcast F (and keep the half-signed R someplace safe).

If 1/1/2013 rolls around and you want your coins back, you sign your half of R and broadcast it.



I'd have to think a little harder than I want to right now about whether or not signing R knowing only txid==HASH(F) opens up the exchange to attacks. I can't think of any, but the exchange providing a signature when it doesn't know the details of exactly what it is signing makes me nervous.

You could send the unsigned R and the signed-but-not-broadcast F to the exchange and trust that the exchange will not broadcast F unless they agree to sign R.


I think holding on to pre-signed-but-not-broadcast-yet transactions is a technique "we" don't think about enough.


I read the previous discussion at https://bitcointalk.org/index.php?topic=6439.0 and https://bitcointalk.org/index.php?topic=1786

Satoshi rejected the idea of OP_BLOCKNUMBER because of this:

Quote
If the script language is not stateless, if it has access to any outside information that changes or varies between nodes, attackers can use it to fork the chain.  The only exception is if it is always false before a certain time and permanently true after, which is implemented with nLockTime.

Yes, he is correct. So it is possible to incorporate the idea of nLockTime into script? For example:

1. The coin can be spent by 2-by-2 multisig with key E and key U at ANY TIME
2. If block height >= x, the coin can be spent by key U. The 2-by-2 multisig, however, is still a vaild way to spend the coin.

Therefore, the first condition is permanently true, regardless of block height. The second condition is always false before block height = x, and permanently true after.

It is better than using nLockTime because the user can deposit to the script hash at any time, without the need of sending nLockTime transaction back-and-forth and storing them. It also avoids the problem of asking the exchange to sign an unknown transaction

Donation address: 374iXxS4BuqFHsEwwxUuH3nvJ69Y7Hqur3 (Bitcoin ONLY)
LRDGENPLYrcTRssGoZrsCT1hngaH3BVkM4 (LTC)
PGP: D3CC 1772 8600 5BB8 FF67 3294 C524 2A1A B393 6517
Pieter Wuille
Legendary
*
qt
Offline Offline

Activity: 1072
Merit: 1178


View Profile WWW
October 06, 2012, 12:12:46 AM
 #9

If you held a pre-signed transaction that sends the funds back to you with a lockTime of 1 Jan 2013 that would work.
I've been out of the loop for a while.. Does lockTime work correctly nowadays? If not, when is it scheduled to be implemented?

nLocktime has ever worked since it was introduced.

What doesn't exist yet is transaction replacement (which is necessary for many, but not all, of nLocktime's applications). Thankfully, implementing transaction replacement doesn't need any protocol change or fork or miner support.

I do Bitcoin stuff.
gmaxwell
Moderator
Legendary
*
expert
Offline Offline

Activity: 4186
Merit: 8435



View Profile WWW
October 06, 2012, 02:09:10 AM
 #10

Yes, he is correct. So it is possible to incorporate the idea of nLockTime into script? For example:

1. The coin can be spent by 2-by-2 multisig with key E and key U at ANY TIME
2. If block height >= x, the coin can be spent by key U. The 2-by-2 multisig, however, is still a vaild way to spend the coin.
Validating that use of height is actually stateless in script would be horrific and more or less intractable. If script were designed so that there was a table of redemption options which had their own lock time then it could have been done... but alas.

It's no big deal in any case:

You are selling me your car. We decide to use a 2-of-2 escrow.  But I'm afraid you'll hold up the funds if the deal falls through.

I compute the payment into the escrow and sign it. But I do not announce it yet.  I also compute a transaction spending the escrow transaction and paying it all back to me with the locktime set some months from now.  I sign that transaction.  I give it to you (along with the txout its spending but not the whole payment). You can look at it and confirm that it is indeed unlocked until whenever, so sign it and give it back.  Then I announce the payment into the escrow. You don't need height in scripts to get refund timeouts. QED.
flipperfish
Sr. Member
****
Offline Offline

Activity: 350
Merit: 251


Dolphie Selfie


View Profile
October 15, 2012, 05:24:29 PM
 #11

Is there actively being worked on enabling replacement of transactions?

A great application for nLockTime would be a dead-man-switch for encrypted wallets. The main problem I see with encrypted wallets for the average user is, that if the password is lost, the coins are lost, too. I have been thinking for a long time about a solution, where to store the password (besides my brain), so that in case I suffer from amnesia, I still have access to my coins. But the best solution I can imagine, is to store a signed transaction with nLockTime set to some time in the future, which sends the coins in the encrypted wallet to some other address. The private key to this new address could be given to someone/stored somewhere you trust in the case you suffer from amnesia, but do not trust for day-to-day usage. As long as you remember the password to the wallet, the nLockTime-Transaction can be refresehed, so it never gets locked. In case you forget the password, the coins become availiable after the nLockTime-Transaction locks.

I believe this idea is not new, but it would be nice to have it implemented soon, because it helps to make bitcoin more reliable and thus more trusted by average people.
Gavin Andresen
Legendary
*
qt
Offline Offline

Activity: 1652
Merit: 2217


Chief Scientist


View Profile WWW
October 15, 2012, 06:30:19 PM
 #12

... But the best solution I can imagine, is to store a signed transaction with nLockTime set to some time in the future, which sends the coins in the encrypted wallet to some other address....

You don't need the whole network to support transaction replacement to do that; just write some code that holds a time-locked transaction, has a way of replacing it with another time-locked transaction, and have it automatically broadcast the transaction onto the network if not replaced before the time-lock expires.

It would be more convenient to have the whole network support transaction replacement, but I don't think it is reasonable for the whole network to remember everybody's dead-man-switch transactions. And even if they did, you'd run the risk that a miner eager to get an extra transaction fee would ignore a newer version of the transaction and mine the old transaction.

How often do you get the chance to work on a potentially world-changing project?
flipperfish
Sr. Member
****
Offline Offline

Activity: 350
Merit: 251


Dolphie Selfie


View Profile
October 15, 2012, 08:53:37 PM
 #13

You don't need the whole network to support transaction replacement to do that; just write some code that holds a time-locked transaction, has a way of replacing it with another time-locked transaction, and have it automatically broadcast the transaction onto the network if not replaced before the time-lock expires.

I had in mind to not broadcast the time-locked tx until it's needed. But what happens, if it gets broadcasted somehow before I can replace it? Does it get included into a block? Does it hang around in the network as some zombie-tx, which can not yet be included in a block, but is valid and can't be thrown away?

As far as I know the only way to replace such a transaction is by spending the same outputs without nLockTime set. But then the client would not relay the transaction because replacement is not enabled and it would be considered as double-spend, right?
Mike Hearn
Legendary
*
expert
Offline Offline

Activity: 1526
Merit: 1129


View Profile
October 15, 2012, 10:02:40 PM
 #14

I don't think 2-of-2 escrow buys you anything, which is why I haven't discussed it in any of my posts/talks/wiki pages.

If I want to screw the seller, then I'll just broadcast the refund transaction after driving away and it'll enter the memory pool, preventing any other transactions from spending the 2-of-2 output. I get the money back (after a few months).

If the seller wants to screw me, after creating the 2-of-2 transaction and we agree on the sale by both signing for the multisig output, he broadcasts the tx giving himself the money and then refuses to give me the car keys. He drives away and I lose the money.

In no case are we better off than just using a regular payment.

2-of-3 with a mediator doesn't have these problems, nor does a smart property construction in which the transaction making the payment also transfers control of the car atomically.

The "dead mans switch" idea doesn't work either. If the key the recovery transaction to is also encrypted then it doesn't help if you forget the password. If it's not encrypted then if somebody gains access to your wallet, they can broadcast the recovery transaction and make your wallet unspendable, then broadcast a spend of the recovery transactions output. The thief would have to wait a few months to claim the money but they'd get it eventually. Not to mention that the recovery transaction would have to be rebuilt every time the wallet contents changed!

Anyone thinking about nLockTime should remember this - a transaction that is time locked enters the memory pool and stays there until the lock time is reached. Once broadcast the inputs that transaction spends are used and double spends won't be accepted.
flipperfish
Sr. Member
****
Offline Offline

Activity: 350
Merit: 251


Dolphie Selfie


View Profile
October 17, 2012, 01:13:09 PM
 #15

a transaction that is time locked enters the memory pool and stays there until the lock time is reached. Once broadcast the inputs that transaction spends are used and double spends won't be accepted.

This could be changed by implementing transaction replacement (correct me if I'm wrong) and would make time-locked transactions (and both mentioned use cases) useful. That's why I'm asking, if there is actively being worked on this.
Mike Hearn
Legendary
*
expert
Offline Offline

Activity: 1526
Merit: 1129


View Profile
October 21, 2012, 06:39:13 PM
 #16

Replacement transactions need to have the same inputs as the transaction they are replacing, so no, it makes no difference.
flipperfish
Sr. Member
****
Offline Offline

Activity: 350
Merit: 251


Dolphie Selfie


View Profile
October 22, 2012, 09:40:14 AM
 #17

Replacement transactions need to have the same inputs as the transaction they are replacing, so no, it makes no difference.
Of course I want to replace a transaction with the same inputs. How else would it be possible to invalidate the time-locked transaction? I thought "transaction replacement" enables the replacement (or better "update") of pending transactions in the memory pool. Or is this another unlucky naming of things, which actually do something else?
Mike Hearn
Legendary
*
expert
Offline Offline

Activity: 1526
Merit: 1129


View Profile
October 22, 2012, 12:33:52 PM
 #18

Transaction replacement lets you replace transactions in the memory pool, yes. However that transaction must have the same inputs as the previous transaction. Perhaps I misunderstood what you're saying. Even with transaction replacement enabled, once broadcast some version of the transaction is in the memory pool at all times and all the inputs are marked as spent. You can't change which inputs are spent by replacing it.
flipperfish
Sr. Member
****
Offline Offline

Activity: 350
Merit: 251


Dolphie Selfie


View Profile
October 22, 2012, 01:52:15 PM
 #19

Thank you for taking your time to explain these issues to me. But unfortunateley I still can't follow you're explanaitions.

Let's leave the more advanced scenarios aside for the moment and concentrate just on replacing a single broadcasted, but time-locked transaction. With transaction replacement enabled, it seems possible to do just that, as long as the same inputs are used within the replacing transaction.

So assume this order of actions:

Pre-Conditions:
- Transaction replacement is enabled.

Invariants:
- Input A is not used in any other not explicitly listed transaction.

1.) Create and broadcast a time-locked (until t_lock) transaction with input A and Output 1
2a.) Before t_lock create and broadcast a non-time-locked transaction with input A and Output 2 (different from Output 1)
2b.) After t_lock create and broadcast a non-time-locked transaction with input A and Output 3 (different form Output 1 and 2)

What happens in 2a.) and 2b.)?

My guess:
2a.) The transaction from 1.) is replaced in the memory pool. As the time-constraint is now removed it can be included in a block. The transaction becomes valid, outputs of input A become available at Output 2.
2b.) The transaction from 1.) is included in a block because the time-constraint is met. The transaction from 2b.) will be considered invalid because the inputs have been already spent. The outputs of input A are availible at Output 1.


What happens if there is no transaction replacement (= current implementation?)?

My guess:
2a. and 2b.) The transaction from 1.) is in the memory pool and can't be replaced. It stays there until the time-constraint is met. The outputs of input A finally become availiable at Output 1.
Maged
Legendary
*
Offline Offline

Activity: 1204
Merit: 1015


View Profile
October 25, 2012, 03:51:51 AM
Last edit: October 25, 2012, 04:02:20 AM by Maged
 #20

I don't think 2-of-2 escrow buys you anything, which is why I haven't discussed it in any of my posts/talks/wiki pages.
It buys instant confirmation for the receiver if the 2-of-2 escrow with refund was staged before it was needed, since the receiver would have to know of any double-spends simply because they would have had to sign them. This is perfect for staging Bitcoins on an exchange so that you don't have to wait 6 confirmations before you can make a trade, but without the risk of them being stolen in a hack or lost due to the site going down.

The "dead mans switch" idea doesn't work either. If the key the recovery transaction to is also encrypted then it doesn't help if you forget the password. If it's not encrypted then if somebody gains access to your wallet, they can broadcast the recovery transaction and make your wallet unspendable, then broadcast a spend of the recovery transactions output. The thief would have to wait a few months to claim the money but they'd get it eventually. Not to mention that the recovery transaction would have to be rebuilt every time the wallet contents changed!

Anyone thinking about nLockTime should remember this - a transaction that is time locked enters the memory pool and stays there until the lock time is reached. Once broadcast the inputs that transaction spends are used and double spends won't be accepted.
"Once broadcast the inputs that transaction spends are used and double spends won't be accepted" ... into the memory pool. Unless I'm totally wrong, that means that all you need to do is manage to get your replacement transaction into a block before the time locked transaction can be entered into a block (which if you did it right, should be several months). For an entity like MtGox, even without transaction replacement being generally enabled on the network, this would be no problem.

Pages: [1] 2 »  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!