Return-Path: Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 728AAB9E for ; Fri, 28 Jun 2019 09:49:47 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from azure.erisian.com.au (cerulean.erisian.com.au [139.162.42.226]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id C8A3013A for ; Fri, 28 Jun 2019 09:49:46 +0000 (UTC) Received: from aj@azure.erisian.com.au (helo=sapphire.erisian.com.au) by azure.erisian.com.au with esmtpsa (Exim 4.89 #1 (Debian)) id 1hgnVm-0006J9-HE; Fri, 28 Jun 2019 19:49:44 +1000 Received: by sapphire.erisian.com.au (sSMTP sendmail emulation); Fri, 28 Jun 2019 19:49:37 +1000 Date: Fri, 28 Jun 2019 19:49:37 +1000 From: Anthony Towns To: Russell O'Connor , Bitcoin Protocol Discussion Message-ID: <20190628094937.u5zisdhdyfc6g5ts@erisian.com.au> References: MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: NeoMutt/20170113 (1.7.2) X-Spam-Score: -1.9 X-Spam-Score-int: -18 X-Spam-Bar: - X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org X-Mailman-Approved-At: Fri, 28 Jun 2019 14:40:14 +0000 Cc: Pieter Wuille Subject: Re: [bitcoin-dev] Taproot proposal X-BeenThere: bitcoin-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Bitcoin Protocol Discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 Jun 2019 09:49:47 -0000 On Wed, Jun 26, 2019 at 08:08:01PM -0400, Russell O'Connor via bitcoin-dev wrote: > I have a comment about the 'input_index' of the transaction digest for taproot > signatures.  It is currently listed as 2 bytes.  I think it would be better to > expand that to 4 bytes. FWIW, I think this would be essentially free, at least for the current sighash modes, as (I think) all the non-ANYONECANPAY modes have at least 4 bytes of sha256 padding at present. In addition to (or, perhaps, as a special case of) the reasons Russell gives, I think this change would also better support proof-of-reserves via taproot signatures (cf [0] or BIP 127), as it would allow the proof tx to include more than 65k utxos with each utxo being signed with a signature that commits to all inputs including the invalid placeholder. [0] https://blockstream.com/2019/02/04/en-standardizing-bitcoin-proof-of-reserves/ If you didn't have this, but wanted to do proof-of-reserves over >65k taproot UTXOs, you could use ANYONECANPAY signatures, and use the output amounts to ensure the signatures can't be abused, something like: inputs: 0: spend from txid 0000..0000 vout 0, no witness data 1: utxo1, signed with ANYONECANPAY|ALL 2: utxo2, signed with ANYONECANPAY|ALL 3: utxo3, signed with ANYONECANPAY|ALL [etc] outputs: 0: sum(utxo1..utxoN), pay to self 1: 2099999997690001-sum(utxo1..utxo3), payable to whatever The total output value is therefore one satoshi more bitcoin than there could ever have been, so none of the utxoK signatures can be reused on the blockchain (unless there's severe inflation due to bugs or hardforks), but the values (and sums) all remain less than 21M BTC so it also won't fail the current "amount too big" sanity checks. That seems a bit more fragile/complicated than using SIGHASH_ALL for everything, though it means your cold wallet doesn't have to serialize your >65k transactions to verify it's signing what it thinks it is. > [1]The var-integer field for the number of inputs (and the number of outputs) > in a transaction looks like it should allow upto 2^64-1 inputs; however this is > an illusion.  The P2P rules dictate that these values are immediately taken > modulo 2^32 after decoding.  For example, if the number of inputs is a > var-integer encoding of 0x0100000001, it is actually just a non-canonical way > of encoding that there is 1 input.  Try this at home! Hmm? If I'm following what you mean, that's not the P2P rules, it's the Unserialize code, in particular: compat/assumptions.h:52:static_assert(sizeof(int) == 4, "32-bit int assumed"); serialize.h:289:uint64_t ReadCompactSize(Stream& is) serialize.h-679-template serialize.h-680-void Unserialize_impl(Stream& is, prevector& v, const V&) serialize.h-681-{ serialize.h-682- v.clear(); serialize.h:683: unsigned int nSize = ReadCompactSize(is); (and other Unserialize_impl implementations) However, ReadCompactSize throws "size too large" if the return value is greater than MAX_SIZE == 0x02000000 =~ 33.5M, which prior to the implicit cast to 32 bits in Unserialize_impl. And it looks like that check's been there since Satoshi... So as far as I can see, that encoding's just unsupported/invalid, rather than equivalent/non-canonical? Cheers, aj