-
Notifications
You must be signed in to change notification settings - Fork 21
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
Conversation
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.
How does this prevent creating a block that commits to two different
witnesses?
|
Never mind, I misread, that branch byte goes into the commitment. So in a future with 8 consensus-critical commitments, you would now have |
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. |
Mixing consensus-critical and non-consensus critical commitments would
significantly worsen adoption, I'm afraid, as one is influenced by the
transaction selection code, and the other chosen by miners. Combining them
means that we need protocols through the whole mining stack that pass up
the commitments to be made and combine them.
Your tree approach is close to what I implemented first, but it seems that
splitting consensus-critical commitments and non-consensus-critical ones
(using a future tree based approach, committed separately) is far simpler.
And once you drop the requirement of non-consensus critical commitments,
the advantage of using a tree disappears (except for slightly worsening
fraud proofs, but that will need a hardfork anyway to improve).
|
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. |
I know a more efficient mechanism is possible, and I'm interested in
helping develop it. But I think we need a separate, simpler, construction
for consensus-critical commitments. And for that goal, any tree is less
efficient.
|
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. |
@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. |
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. |
@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. |
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 ? |
61a90de
to
2a16578
Compare
The discussion above focusses on the distinction between two different paths to take (C = number of commitments, T = number of transactions, B = coinbase size):
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. |
909fb25
to
99c8d54
Compare
a88b686
to
38a8b36
Compare
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
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
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.