Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: piotr_n on May 18, 2021, 01:27:49 PM



Title: Taproot implementation questions
Post by: piotr_n on May 18, 2021, 01:27:49 PM
I'm starting this new topic because I'm trying to implement the taproot functionality in my code.
I hope people can help me to understand some of the taproot technicalities.

So my first question:

How does the new verify_script function use the spend_scripts of the inputs that it is spending?

When I will verify a specific input of a transaction, will I need to have amounts and spend scripts for all the inputs, or will it be enough to have just the one at a time?


Title: Re: Taproot implementation questions
Post by: achow101 on May 18, 2021, 05:31:49 PM
The new Sighash algorithm (https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#Common_signature_message) includes all of the values and output scripts of the UTXOs being spent in the transaction.


Title: Re: Taproot implementation questions
Post by: piotr_n on May 18, 2021, 05:35:11 PM
Thank you.

May I ask, out of curiosity, what purpose does it serve?
It kind of makes the taproot implementation quite much harder to make.


Title: Re: Taproot implementation questions
Post by: achow101 on May 18, 2021, 05:53:04 PM
May I ask, out of curiosity, what purpose does it serve?
It kind of makes the taproot implementation quite much harder to make.
Requiring all UTXO amounts is there to allow for offline signers to be guaranteed that the amount they are sending is correct. There have been some theorized situations where an offline signer could be tricked into sending more or less Bitcoin to fees than they expect to, which could result either in the loss of funds, or in the transaction not confirming in a timely manner.

Trezor described a potential attack (https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd) that involve the uncertainty of the amounts in other inputs. This attack could result in the loss of funds by causing an increasing the transaction fee.

So this change to the sighash algorithm resolves such attacks. If the offline signer is lied to about the amount of other inputs, it will produce an invalid signature and so the transaction becomes invalid. Thus it doesn't matter if it is lied to, no funds can be lost.

For requiring all the output scripts, this is again for offline signers, particularly in coinjoins. In this scenario, the offline signer needs to be able to prove that all of the other inputs in the transaction do not belong to it. Otherwise it could lose funds. By requiring all of the scriptPubKeys for the other inputs, the offline signer can be safe to sign even if it is being lied to. Like with the amounts, if it is lied to, it will make an invalid signature and so the transaction is invalid. There is some more information about this on the bitcoin-dev mailing list (https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2020-April/017801.html).


Title: Re: Taproot implementation questions
Post by: piotr_n on May 18, 2021, 06:00:59 PM
Thank you, it helps me a lot.

Call me stupid, but I'm not quite enlightened by the way the BIP docs are explaining themselves. :)

So: try to collect the outputs being spent first and verify the scripts later - I'm on it.. thanks!


Title: Re: Taproot implementation questions
Post by: piotr_n on May 19, 2021, 10:38:47 AM
Are there any test vectors, but only for the new sighash algorithm?



Title: Re: Taproot implementation questions
Post by: achow101 on May 19, 2021, 04:35:51 PM
Are there any test vectors, but only for the new sighash algorithm?
I don't think so.


Title: Re: Taproot implementation questions
Post by: NotATether on June 07, 2021, 05:09:12 PM
Are there any test vectors, but only for the new sighash algorithm?
I don't think so.

It just occurred to me that you can reuse the test vectors of BIP341 https://raw.githubusercontent.com/bitcoin-core/qa-assets/main/unit_test_data/script_assets_test.json and to make the unit test, instead of using VerifyScript you could instead construct a CScript out of the script bytes and construct a uint256 hash like this:

Code:
            exec_script = CScript(script_bytes.begin(), script_bytes.end());
            uint256 hash_exec_script;

And then memcmp() the script hash to its expected value.