Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[segnet3 hard-fork] Allow arbitrary commitment tree structure. #48

Closed
wants to merge 25 commits into from

Conversation

maaku
Copy link

@maaku maaku commented Jan 26, 2016

The witness root is allowed to be placed at an arbitrary position up to seven layers deep in a Merkle tree structure. The witness nonce is now the branch through the commitment tree to the witness root, and a single byte is added to the commitment output specifying this path in compact form. This allows other consensus commitments to be added in the future with a minimal number of bytes and without requiring a certain position for each commitment in the tree.

This hard-forks segnet3 as it changes the witness commitment structure.

sipa and others added 25 commits January 25, 2016 13:54
Contains refactorings by Eric Lombrozo.
Contains fixup by Nicolas Dorier.
Includes simplifications by Eric Lombrozo.
Includes support for pushkeyhash wit v0 by Alex Morcos.
Includes fixup by Thomas Kerin.
The witness root is allowed to be placed at an arbitrary position up to seven layers deep in a Merkle tree structure. The witness nonce is now the branch through the commitment tree to the witness root, and a single byte is added to the commitment output specifying this path in compact form. This allows other consensus commitments to be added in the future with a minimal number of bytes and without requiring a certain position for each commitment in the tree.
@sipa
Copy link
Owner

sipa commented Jan 26, 2016 via email

@sipa
Copy link
Owner

sipa commented Jan 26, 2016

Never mind, I misread, that branch byte goes into the commitment.

So in a future with 8 consensus-critical commitments, you would now have
32_3 bytes in the witness nonce, and similarly 32_3 bytes in each of the 7
other ones. Plus, you'd need to store the branch bytes for each of them
somewhere. As they're consensus critical commitments, all fully validating
nodes need all them anyway, so the tree approach is less efficient than the
chain approach (and that remains the case even when using a maximally
unbalanced tree).

@maaku
Copy link
Author

maaku commented Jan 26, 2016

This is correct. It is a tradeoff though because the tree based approach means that as the number of commitments grows the proof size does not grow linearly.

More importantly, it doesn't set in stone the position of the commitment in the tree. We are free to reorganize (as policy) the tree as we see fit going forward. Miners also are allowed to prioritize commitments as they see fit, such as merged mining commitments which benefit greatly from being near the top of the tree without having a setaside in the bitcoin consensus rules.

@sipa
Copy link
Owner

sipa commented Jan 26, 2016 via email

@maaku
Copy link
Author

maaku commented Jan 26, 2016

A more efficient tree encoding is possible that doesn't repeat hashes. I am open to implementing it if there is desire. It only comes into play if there are multiple commitments. This was just easier to implement and illustrate the point.

This may not be obvious, but not that the structure of this coinbase witness containing the hashes / nonce is protocol level, not consensus and is upgradeable.

@sipa
Copy link
Owner

sipa commented Jan 26, 2016 via email

@jl2012
Copy link

jl2012 commented Jan 27, 2016

This is more or less the original design (you can find it in the history of BIP141). Consensus critical commitment are by definition verified by every full node, even it might be obsoleted in the future. Therefore, a linear structure will guarantee the highest efficiency. It also simplifies the implementation a lot.

The only case where a tree structure might be needed is when we have 2 parallel softforks proposals with new consensus critical commitment. But we can always introduce a tree structure any time as the witness nonce is flexible.

@maaku
Copy link
Author

maaku commented Jan 27, 2016

@jl2012 I believe that to be taking too narrow a view of what these commitments are useful for. These commitments allow construction of various compact proofs of consensus state. These proofs are in turn useful for various space sensitive applications, of which I will highlight two: proofs of state for mobile wallets, and cross-chain smart contracting such as the two-way peg. Both of these applications are highly space constrained -- in the wallet case because mobile data is expensive, slow, and/or power hungry, and the cross-chain smart contracting case because these proofs must be broadcast-able on the bitcoin or bitcoin-like block chains. Using a tree structure for commitments allows tradeoffs to be made favouring smaller proofs for the more space-constrained applications, and larger proofs for those which are only checked by the consensus code or very rarely needed.

To take a concrete example, one of the very first commitments that is likely to be added is a hash of a constrained nonce + the previous block in order to prevent validationless mining. This is likely to be merged well prior to any sort of txout or block header commitment schemes. Yet because the linear structure forces an otherwise arbitrary time-based ordering of commitments, any proof using a later commitment would necessarily have to include 32 bytes of unnecessary information just to validate. And if we're talking about things like SMS fraud proof relay or on-chain two-way peg withdraw proofs, that 32 bytes could be VERY expensive.

To your other point, this is derivative of the original commitment structure indeed, because it was a suggested improvement to the original code back in December. I have only had time now to work on it and was surprised to see what was in my view a regression in functionality. This is an argument for development happening as a pull-request against the bitcoin/bitcoin repo, where the PR itself can act as a sort of mailing list for coordinating development. Right now things are not being communicated well. But that is an aside.

@sipa
Copy link
Owner

sipa commented Jan 27, 2016

Any Merkle path to a commitment will already require the full coinbase transaction (~160 bytes) and path inside the main Merkle tree (~350 bytes). Yes, a linear structure is slightly worse for proofs on further commitments, but if 32 bytes hurts them, they're likely already impossible.

@jl2012
Copy link

jl2012 commented Jan 27, 2016

@maaku If the size of SPV proof is really that critical, we probably should consider a hardfork. Coinbase tx > 5kB is not uncommon. If the required proof is in a big coinbase tx, obviously you can't use SMS to relay it.

For things like previous block proof or UTXO commitment, which do not have their own data structure, may not be able to join the witness commitment at all (no matter in a linear or a tree structure; unless they are deployed at the same time with segwit). It is because the Merkle path for such commitments will have no place to go. We need either a new witness structure just for storing a particular Merkle path (which is an overkill), or put the path in the coinbase tx. Then why don't we simply commit them directly in the coinbase tx?

This problem could be probably solved this way: instead of using 0x0000....0000 as the coinbase witness ID, we could use the hash of the coinbase witness data in the witness commitment. Therefore, we can have an arbitrary size for coinbase witness, instead of restricting it to 32 bytes. So the Merkle path of future commitments can go there.

@sipa
Copy link
Owner

sipa commented Feb 1, 2016

The ideas here interact with Peter Todd's suggestion to allow unvalidated data inside block witnesses, instead of using further P2P changes for later commitments.

If we're going to do an incompatible change, can you have a look at http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-February/012313.html ?

@sipa sipa force-pushed the segwit branch 2 times, most recently from 61a90de to 2a16578 Compare February 9, 2016 19:49
@sipa
Copy link
Owner

sipa commented Mar 12, 2016

The discussion above focusses on the distinction between two different paths to take (C = number of commitments, T = number of transactions, B = coinbase size):

  • A linear structure, which needs 32 * C full node overhead, and 32 * C + 32 * log2(T) + B worst-case fraud proof overhead.
  • A tree structure, which needs 32 * log2(C) * C full node overhead, and 32_log2(C) + 32_log2(T) + B fraud proof overhead.

For any low number of C, I don't think it matters much. The size of fraud proofs will be dominated by the coinbase transaction and transaction merkle path. We need a fundamentally different approach (and presumably a hard fork) to change that.

Also, neither choice actually forces us to keep following the same path down the line. We can add other commitment locations to the transaction tree, or add extra commitments to the existing commitment coinbase output scriptPubKey. In the linear case, we can create a tree commitment that gets stored inside the coinbase witness later (which is just p2p) and commit it elsewhere. In the tree case, we can commit to a linear sequence in one of the leaves.

@sipa sipa force-pushed the segwit branch 2 times, most recently from 909fb25 to 99c8d54 Compare March 16, 2016 17:51
@sipa sipa force-pushed the segwit branch 4 times, most recently from a88b686 to 38a8b36 Compare March 26, 2016 00:21
@sipa sipa closed this Mar 29, 2016
sipa pushed a commit that referenced this pull request Oct 1, 2021
0d624261ef Merge bitcoin-core/crc32c-subtree#2: Merge upstream
cac7ca830b Merge commit 'fa5ade41ee480003d9c5af6f43567ba22e4e17e6' into bitcoin-fork
fa5ade41ee Fix compilation warnings on ARM64 with old GCC versions. (#52)
db08d22129 Updated Travis-CI configuration. (#51)
e31619a5b7 Fix GitHub links. (#50)
7fa4c263e8 Update Travis CI config. (#49)
a3d9e6d1a4 Updated third_party/ and Travis CI config. (#48)

git-subtree-dir: src/crc32c
git-subtree-split: 0d624261ef83ab08c953c196540ed18f355add4c
sipa pushed a commit that referenced this pull request Oct 21, 2021
a44caf65fe Merge bitcoin-core/univalue-subtree#28: Import fixes for sanitizer reported issues
135254331e Import fixes for sanitizer reported issues
d5fb86940e refactor: use c++11 range based for loop in checkObject
ff9c379304 refactor: Use nullptr (c++11) instead of NULL
08a99754d5 build: use ax_cxx_compile_stdcxx.m4 to check for C++11 support
66d3713ce7 Merge bitcoin-core/univalue-subtree#29: ci: travis -> cirrus
808d487292 ci: travis -> cirrus
c390ac375f Merge bitcoin-core/univalue-subtree#19: Split sources for easier buildsystem integration
4a5b0a1c65 build: Move source entries out to sources.mk
6c7d94b33c build: cleanup wonky gen usage
a222637c6d Merge #23: Merge changes from jgarzik/univalue@1ae6a23
f77d0f718d Merge commit '1ae6a231a0169938eb3972c1d48dd17cba5947e1' into HEAD
1ae6a231a0 Merge pull request #57 from MarcoFalke/test_fix
92bdd11f0b univalue_write: remove unneeded sstream.h include
ffb621c130 Merge pull request #56 from drodil/remove_sstream_header
f33acf9fe8 Merge commit '7890db9~' into HEAD
66e0adec4d Remove unnecessary sstream header from univalue.h
88967f6586 Version 1.0.4
1dc113dbef Merge pull request #50 from luke-jr/pushKV_bool
72392fb227 [tests] test pushKV for boolean values
c23132bcf4 Pushing boolean value to univalue correctly
81faab26a1 Merge pull request #48 from fwolfst/47-UPDATE_MIT_LINK_TO_HTTPS
b17634ef24 Update URLs to MIT license.
88ab64f6b5 Merge pull request #46 from jasonbcox/master
35ed96da31 Merge pull request #44 from MarcoFalke/Mf1709-univalue-cherrypick-explicit
420c226290 Merge pull request #45 from MarcoFalke/Mf1710-univalue-revert-test

git-subtree-dir: src/univalue
git-subtree-split: a44caf65fe55b9dd8ddb08f04c0f70409efd53b3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants