<oembed><type>rich</type><version>1.0</version><author_name>npub1sgs97fe0n9wehe6zw7drcxdz4cy9yt9pfqjv8gasz5jlk4zezc0quppx3c</author_name><author_url>https://nostr.ae/npub1sgs97fe0n9wehe6zw7drcxdz4cy9yt9pfqjv8gasz5jlk4zezc0quppx3c</author_url><provider_name>njump</provider_name><provider_url>https://nostr.ae</provider_url><html>📅 Original date posted:2017-04-10&#xA;📝 Original message:-----BEGIN PGP SIGNED MESSAGE-----&#xA;Hash: SHA256&#xA;&#xA;On 04/08/2017 04:58 PM, Tomas wrote:&#xA;&gt; You seem to ignore here the difference between base load and peak &#xA;&gt; load. If Compact blocks/XThin with further optimizations can &#xA;&gt; presync nearly 100% of the transactions, and nodes can do as much &#xA;&gt; as possible when a transaction comes in, the time spent when a &#xA;&gt; block comes in can be minimized and a lot more transactions can be &#xA;&gt; handled with the same resources.&#xA;&#xA;Maybe it&#39;s an issue of terminology. I have never used the terms&#xA;base/peak load. However I&#39;ve been trying to get across, poorly I&#xA;suppose, that this is actually implemented in libbitcoin. I generally&#xA;refer to it as tx pre-validation. I&#39;ve also tried to relate that you&#xA;are unnecessarily relating pre-validation to compactness. These are&#xA;unrelated ideas and better considered independently. One can get&#xA;nearly all of the benefit of pre-validation while still receiving&#xA;blocks (vs. compact blocks). The advantage of compactness is reduced&#xA;latency of the block announcement. The reason for pre-validation is&#xA;amortization of the validation and/or storage cost of a block.&#xA;&#xA;&gt; The reason for &#34;splitting&#34; is that for an incoming transaction the&#xA;&gt;  spent-state of the outputs being spent isn&#39;t particularly&#xA;&gt; relevant as you seem to acknowledge. When the block comes in, the&#xA;&gt; actual output data isn&#39;t relevant.&#xA;&#xA;As I understand it you would split tx inputs and outputs and send them&#xA;independently, and that you intend this to be a P2P network&#xA;optimization - not a consensus rule change. So my comments are based&#xA;on those inferences. If we are talking about consensus changes this&#xA;conversation will end up in an entirely different place.&#xA;&#xA;I don&#39;t agree with the input/output relevance statements above. When a&#xA;tx is announced the entire tx is relevant. It cannot be validated as&#xA;outputs only. If it cannot be validated it cannot be stored by the&#xA;node. Validating the outputs only would require the node store invalid&#xA;transactions.&#xA;&#xA;I do accept that a double-spend detection is not an optimal criteria&#xA;by which to discard a tx. One also needs fee information. But without&#xA;double-spend knowledge the node has no rational way to defend itself&#xA;against an infinity of transactions that spend the minimal fee but&#xA;also have conflicting inputs (i.e. risking the fee only once). So tx&#xA;(pool) validation requires double-spend knowledge and at least a&#xA;summary from outputs.&#xA;&#xA;&gt; The *only* thing that needs to be checked when a block comes in is &#xA;&gt; the order, and the spend-tree approach absolves the need to access &#xA;&gt; outputs here.&#xA;&#xA;Inputs that are already valid against prevouts remain valid assuming&#xA;consensus rules have not changed. But any input that spends a coinbase&#xA;must be validated for prevout height once there is a block context for&#xA;validation. Additionally the set of txs must be validated for total&#xA;size, sigops, and fee claim. So it&#39;s not true that conflict detection&#xA;alone is sufficient. Yet one can cache a tx&#39;s size, sigops, fee and&#xA;minimum height in a graph so that when a block appears that contains&#xA;that tx the input validation can be skipped.&#xA;&#xA;Ignoring the (actual) requirement for the full tx on the pool&#xA;validation, the required &#34;order&#34; validation at (compact or other)&#xA;block arrival basically consists of traversing each tx, ensuring none&#xA;are confirmed in a block below the fork point; traversing each each of&#xA;its confirmed inputs, ensuring that none are spent in a block below&#xA;the fork point; and ensuring the block&#39;s set of transactions do not&#xA;contain missing inputs and do not double spend internal to the block.&#xA;&#xA;This and the above-mentioned other required per-transaction block&#xA;validation data can be cached to an in-memory structure as a potential&#xA;optimization over navigating the store, and as you say, does not&#xA;therefore require the actual outputs (script/value). But the original&#xA;issue of needing full transactions for independent transaction&#xA;validation remains.&#xA;&#xA;&gt; As it also absolves the need for reorgs this greatly simplifies the&#xA;&gt; design.&#xA;&#xA;A reorg is conceptual and cannot be engineered out. What you are&#xA;referring to is a restructuring of stored information as a consequence&#xA;of a reorg. I don&#39;t see this as related to the above. The ability to&#xA;perform reorganization via a branch pointer swap is based not on the&#xA;order or factoring of validation but instead on the amount of&#xA;information stored. It requires more information to maintain multiple&#xA;branches.&#xA;&#xA;Transactions have confirmation states, validation contexts and spender&#xA;heights for potentially each branch of an unbounded number of&#xA;branches. It is this requirement to maintain that state for each&#xA;branch that makes this design goal a very costly trade-off of space&#xA;and complexity for reorg speed. As I mentioned earlier, it&#39;s the&#xA;optimization for this scenario that I find questionable.&#xA;&#xA;&gt; I am not sure why you say that a one-step approach is more &#xA;&gt; &#34;test-friendly&#34; as this seems to be unrelated.&#xA;&#xA;Full separation of concerns allows all validation to be performed in&#xA;isolation from the store. As such validation state can be faked and&#xA;provided to a tx, block or chain, for the purpose of test. Validation&#xA;that interacts with a complex store during validation is harder to&#xA;fake and tests can be hard to verify.&#xA;&#xA;It&#39;s not really the &#34;one-step&#34; approach that make this possible. In&#xA;fact that&#39;s not an accurate description. Validation and storage of txs&#xA;and blocks consists of four steps:&#xA;&#xA;(1) context free&#xA;(2) contextual (chain-based)&#xA;(3) expensive (script eval)&#xA;(4) storage and notification&#xA;&#xA;So we have:&#xA;&#xA;tx.check()&#xA;tx.accept(state)&#xA;tx.connect(state)&#xA;chain.organize(tx)&#xA;&#xA;block.check()&#xA;block.accept(state)&#xA;block.connect(state)&#xA;chain.organize(block)&#xA;&#xA;...where &#34;chain&#34; is the store, from which &#34;state&#34; is derived. The&#xA;state for an unconfirmed tx is based on the presumption that the tx&#xA;would be mined in the next block. If that is not the case then its&#xA;pre-validation can become invalidated. So from my perspective, this&#xA;discussion is all about populating state. Anything that cannot be&#xA;placed into that pattern would complicate both the conceptual model&#xA;and testing. We&#39;ve also seen that this isolation also has performance&#xA;advantages, as it facilitates optimizations that are otherwise&#xA;challenging.&#xA;&#xA;&gt;&gt; Despite the site&#39;s explanation I cannot think of any reason to &#xA;&gt;&gt; ever validate two blocks at the same time. You would always &#xA;&gt;&gt; prioritize the block with the greatest PoW. Doing otherwise just &#xA;&gt;&gt; slows down the net validation in all but the pathological case &#xA;&gt;&gt; where a miner has produced an *invalid* block with *more* PoW &#xA;&gt;&gt; than another valid block which arrived at the node within the &#xA;&gt;&gt; same second. Rejecting a *valid* block with more PoW in favor of &#xA;&gt;&gt; one with *less* &#34;processing&#34; is a hard fork, so you probably &#xA;&gt;&gt; wouldn&#39;t want to do that either. But with compact block &#xA;&gt;&gt; validation times approaching 25ms it&#39;s hard to justify stopping&#xA;&gt;&gt; a block validation for any reason.&#xA;&gt; &#xA;&gt; I don&#39;t get what you are saying. Why pick the greatest PoW of two &#xA;&gt; competing blocks?&#xA;&#xA;Because choosing the lesser amount of work is non-consensus behavior.&#xA;Under the same circumstances (i.e. having seen the same set of blocks)&#xA;two nodes will disagree on whether there is one confirmation or no&#xA;confirmations for a given tx. This disagreement will persist (i.e. why&#xA;take the weaker block only to turn around and replace it with the&#xA;stronger block that arrives a few seconds or minutes later). It stands&#xA;to reason that if one rejects a stronger block under a race condition,&#xA;one would reorg out a stronger block when a weaker block arrives a&#xA;little after the stronger block. Does this &#34;optimization&#34; then apply&#xA;to chains of blocks too?&#xA;&#xA;&gt; If two blocks come in, an implementation is free to choose &#xA;&gt; whichever block to build on.&#xA;&#xA;Implementations are free to choose no blocks. That&#39;s not really the issu&#xA;e.&#xA;&#xA;&gt; Choosing so is not a &#34;hardfork&#34;.&#xA;&#xA;Accepting a block that all previous implementations would have&#xA;rejected under the same circumstance could be considered a hard fork,&#xA;but you may be right.&#xA;&#xA;Yet the classification is not essential to my point. Nor is any&#xA;material change required to validate blocks in parallel. We can do it&#xA;using current design, but it doesn&#39;t make sense to do so.&#xA;&#xA;&gt; Parallel validation simply makes it easier to make an optimal &#xA;&gt; choice, for if two blocks come in, the one that is validated &#xA;&gt; fastest can be build upon without the risk of validationless &#xA;&gt; mining.&#xA;&#xA;This is not an optimization, since it should always be optimal to&#xA;validate blocks independently. Performing multiple together inherently&#xA;slows both of them. And the advantage to not validating *either* would&#xA;remain.&#xA;&#xA;&gt;&gt; I am also interested in your previous comments about soft forks. &#xA;&gt;&gt; These are material considerations that Greg touched on but it &#xA;&gt;&gt; doesn&#39;t sound like you fully appreciate just yet. When a tx is &#xA;&gt;&gt; pre-validated the rules applied must be the same rules as those &#xA;&gt;&gt; of some future block. Yet a tx can be included in more than one &#xA;&gt;&gt; block (different branches). Across branches and even in one &#xA;&gt;&gt; branch, validation rules change, and can change back. The&#xA;&gt;&gt; changes are based on accumulated branch history. Pre-validation&#xA;&gt;&gt; can later become invalidated, and differently in different&#xA;&gt;&gt; branches. And maintaining proper context requires either storing&#xA;&gt;&gt; state that you are apparently not storing, or invalidating&#xA;&gt;&gt; optimizations. Based on your comments you do not seem to be&#xA;&gt;&gt; accounting for this in your storage assumptions or in your&#xA;&gt;&gt; results. A recent post by Greg highlights the complexity and&#xA;&gt;&gt; consensus criticality of these considerations.&#xA;&gt; &#xA;&gt; Frankly, I think this is a bit of an exaggeration. Soft forks are &#xA;&gt; counted on a hand, and I don&#39;t think there are many - if any - &#xA;&gt; transactions in the current chain that have changed compliance &#xA;&gt; based on height.&#xA;&#xA;Hope is a bug.&#xA;&#xA;&gt; This makes this a compliance issue and not a performance issue&#xA;&#xA;You cannot have a useful performance measure without full compliance.&#xA;&#xA;&gt; and the solution I have explained, to add height-based compliance &#xA;&gt; as meta data of validation seems to be adequate and safe.&#xA;&#xA;If you intend this to be useful it has to help build the chain, not&#xA;just rely on hardwiring checkpoints once rule changes are presumed to&#xA;be buried deeply enough to do so (as the result of other implementations&#xA;).&#xA;&#xA;I understand this approach, it was ours at one time. There is a&#xA;significant difference, and your design is to some degree based on a&#xA;failure to fully consider this. I encourage you to not assume any&#xA;consensus-related detail is too small.&#xA;&#xA;&gt;&gt; The hash table store that I described can fully navigate the &#xA;&gt;&gt; block tree and transaction DAG, since the stored tx, parent and &#xA;&gt;&gt; point hashes are also natural keys and each link is navigable in &#xA;&gt;&gt; constant time. It is also lock-free, can concurrently write any &#xA;&gt;&gt; number of blocks during initial block download and supports &#xA;&gt;&gt; read/write concurrency. It has successfully indexed and stored &#xA;&gt;&gt; the entire blockchain from the P2P network in 16 minutes &#xA;&gt;&gt; (locally). It also stores both confirmed and unconfirmed &#xA;&gt;&gt; transactions in the same store, so there is nothing to write&#xA;&gt;&gt; when a block is confirmed except for the block header/hashes and&#xA;&gt;&gt;  updates to spender heights for any output spent by the new &#xA;&gt;&gt; block&#39;s txs. It is similarly capable of storage in the block &#xA;&gt;&gt; table of weak chain blocks...&#xA;&gt; &#xA;&gt; I think I get the gist of your approach and it sounds very &#xA;&gt; interesting and I will definitely dive in deeper.&#xA;&#xA;It&#39;s worth noting that many of your stated objectives, including&#xA;modularity, developer platform, store isolation, consensus rule&#xA;isolation (including optional use of libbitcoinconsensus) are implemente&#xA;d.&#xA;&#xA;It seems like you are doing some good work and it&#39;s not my intent to&#xA;discourage that. Libbitcoin is open source, I don&#39;t get paid and I&#39;m&#xA;not selling anything. But if you are going down this path you should&#xA;be aware of it and may benefit from our successes as well as some of&#xA;the other stuff :). And hopefully we can get the benefit of your&#xA;insights as well.&#xA;&#xA;e&#xA;-----BEGIN PGP SIGNATURE-----&#xA;Version: GnuPG v2.0.22 (GNU/Linux)&#xA;&#xA;iQEcBAEBCAAGBQJY7DUUAAoJEDzYwH8LXOFOTB0H/jDtfnC6B9CtGrCTPtET+dDx&#xA;r0uQ0SXo40AUTplyKQ228rVkjmZyczTOtIP5uNvKpvlr9wW8TyYzFzNW4RNCNtdP&#xA;xZ9OjrfC24J2n+m1b9z9+CA85qAQxzLztBybDYzXCJG/dQ+y++7BR+rILGiRWUhs&#xA;lROeaEMqlDl0fy5J3dlpe0RGZJPSRqlxW7EBNHYc3IEDNL+j5m80/tWb6H5a3Mv8&#xA;7GTr6ulZef/04u/hRTXQ0ONy0MAIoi63HNHQuR0wF70ewGVmtFY4RHXEnNi+ucIG&#xA;w3QZuNTPtjqIS+ZbpFuqBop+L3CtId9+jxaBAao2tEieoIUl/faLjdTPP+r0n6A=&#xA;=5mz8&#xA;-----END PGP SIGNATURE-----</html></oembed>