<oembed><type>rich</type><version>1.0</version><author_name>Tomas [ARCHIVE] (npub1rs…9evk4)</author_name><author_url>https://nostr.ae/npub1rsp4w56r24w3zv4xy8zfgesep45qmf9rq6aghxfw3wr7yemqnnwsf9evk4</author_url><provider_name>njump</provider_name><provider_url>https://nostr.ae</provider_url><html>📅 Original date posted:2017-04-08&#xA;📝 Original message:Thank you for your elaborate response Eric,&#xA;&#xA;On Sun, Apr 9, 2017, at 00:37, Eric Voskuil wrote:&#xA;&gt; My point was that &#34;Using a storage engine without UTXO-index&#34; has been&#xA;&gt; done, and may be a useful reference, not that implementation details&#xA;&gt; are the same.&#xA;&#xA;I haven&#39;t dived into libbitcoin V2/V3 enough to  fully grasp it and&#xA;though your comments help, I still not fully do.  I will answer below&#xA;what is related to bitcrust itself.&#xA;&#xA;My post wasn&#39;t posted to claim innovation; I merely try to explain how&#xA;Bitcrust works and why   it performs well. &#xA;&#xA;&#xA;&gt; First, I remain confused on your comments pertaining to UTXO growth&#xA;&gt; and network protocol. I followed your conversation with Greg and it&#xA;&gt; remains unclear to me. From what I understand you have isolated order&#xA;&gt; (double spend) from script validation. I think we all understand that&#xA;&gt; script validation requires inputs and outputs while double spend&#xA;&gt; detection requires correlation of inputs. What I do not understand is&#xA;&gt; your choice of optimization axis.&#xA;&gt; &#xA;&gt; Detection of double spend is not useful in isolation. One must also&#xA;&gt; validate scripts, which requires outputs. I can see that there is an&#xA;&gt; opportunity to reject blocks (within the same branch) faster by&#xA;&gt; validating for double spends before validating script. But unconfirmed&#xA;&gt; transactions do not exist in a branch, and are therefore not truly&#xA;&gt; conflicting, until they are mined. And even after they are mined&#xA;&gt; conflicting txs remain potentially valid in other branches. So&#xA;&gt; rejecting txs due to conflict comes down to a denial of service&#xA;&gt; policy, which ultimately must be based on fee increment (e.g. RBF).&#xA;&gt; But fees are based on the amount of the output value that remains&#xA;&gt; unspent in the transaction. So this in turn requires the retrieval of&#xA;&gt; outputs.&#xA;&gt; &#xA;&gt; And yet the remaining scenario of fast rejection of invalid blocks is&#xA;&gt; not a meaningful optimization. Optimizing for the case where a block&#xA;&gt; has valid and sufficient PoW and yet is invalid (for double spend) is&#xA;&gt; counterproductive. And even so, the txs within the invalid block may&#xA;&gt; be entirely valid independent of the block, so you are back to looking&#xA;&gt; up their outputs to obtain fees in the case of a double spend or to&#xA;&gt; validate script otherwise. In all cases you need to get the outputs.&#xA;&gt; &#xA;&gt; &gt; Bitcrust simply scans the tree. Although earlier designs used a &#xA;&gt; &gt; skip-list, it turns out that accompanied by a spent-index lagging a&#xA;&gt; &gt; few blocks behind, raw scanning is faster then anything even though&#xA;&gt; &gt; it needs to scan ~5 blocks times ~4000 inputs before reaching the&#xA;&gt; &gt; first spent-index,  the actual scan is highly cache efficient and&#xA;&gt; &gt; little more then a &#34;REP SCASQ&#34;, reaching sub-microsecond per input&#xA;&gt; &gt; on each core *including* the lookup in the spend index.&#xA;&gt; &#xA;&gt; I realize that you see the implementation of the ordering validation&#xA;&gt; as interesting detail, but I find it hard to justify contemplating the&#xA;&gt; implementation in isolation from the output lookup requirement. And if&#xA;&gt; one must looking up both outputs and spends for each validation, it&#xA;&gt; makes more sense to co-locate that data.&#xA;&gt; &#xA;&gt; Recovering in one step all data necessary to validate a tx has real&#xA;&gt; advantages over either interleaving queries and validation or&#xA;&gt; splitting input vs. output validation queries into two steps. It is a&#xA;&gt; significantly more test-friendly approach, has better performance&#xA;&gt; characteristics, and simplifies code. I cannot see any reason to&#xA;&gt; perform the data read for double spend validation in isolation of that&#xA;&gt; for script validation.&#xA;&#xA;&#xA;You seem to ignore here the difference between base load and peak load.&#xA;If Compact blocks/XThin with further optimizations can presync nearly&#xA;100% of the transactions, and nodes can do as much as possible when a&#xA;transaction comes in, the time spent when a block comes in can be&#xA;minimized and a lot more transactions can be handled with the same&#xA;resources.&#xA;&#xA;The reason for &#34;splitting&#34; is that for an incoming transaction the&#xA;spent-state of the outputs being spent isn&#39;t particularly relevant as&#xA;you seem to acknowledge. When the block comes in, the actual output data&#xA;isn&#39;t relevant.&#xA;&#xA;The *only* thing that needs to be checked when a block comes in is the&#xA;order, and the spend-tree approach absolves the need to access outputs&#xA;here.&#xA;&#xA;As it also absolves the need for reorgs this greatly simplifies the&#xA;design. I am not sure why you say that a one-step approach is more&#xA;&#34;test-friendly&#34; as this seems to be unrelated.&#xA;&#xA;&gt; &#xA;&gt; If by results you are referring to performance numbers, it&#39;s very hard&#xA;&gt; to draw any conclusions without a full benchmark. It&#39;s great that if&#xA;&gt; you are able to boost Core, but from my perspective the numbers aren&#39;t&#xA;&gt; especially compelling.&#xA;&gt;&#xA;&#xA;I fully agree and hopefully do not pretend to hide that my numbers are&#xA;premature without a full implementation. I just think they are promising&#xA;enough to  convince at least myself to move on with this model.&#xA; &#xA;&gt; Despite the site&#39;s explanation I cannot think of any reason to ever&#xA;&gt; validate two blocks at the same time. You would always prioritize the&#xA;&gt; block with the greatest PoW. Doing otherwise just slows down the net&#xA;&gt; validation in all but the pathological case where a miner has produced&#xA;&gt; an *invalid* block with *more* PoW than another valid block which&#xA;&gt; arrived at the node within the same second. Rejecting a *valid* block&#xA;&gt; with more PoW in favor of one with *less* &#34;processing&#34; is a hard fork,&#xA;&gt; so you probably wouldn&#39;t want to do that either. But with compact&#xA;&gt; block validation times approaching 25ms it&#39;s hard to justify stopping&#xA;&gt; a block validation for any reason.&#xA;&#xA;I don&#39;t get what you are saying. Why pick the greatest PoW of two&#xA;competing blocks? If two blocks come in, an implementation is free to&#xA;choose whichever block to build on. Choosing so is not a &#34;hardfork&#34;.&#xA;Parallel validation simply makes it easier to make an optimal choice,&#xA;for if two blocks come in, the one that is validated fastest can be&#xA;build upon without the risk of validationless mining.&#xA;&#xA;&gt; &#xA;&gt; That&#39;s not to say parallel block validation difficult to do. If you&#xA;&gt; can validate one block&#39;s full set of inputs in parallel (which is not&#xA;&gt; novel) doing the same with additional blocks has trivial additional&#xA;&gt; complexity.&#xA;&#xA;I am not trying to claim novelty here.&#xA;&#xA;&gt; I am also interested in your previous comments about soft forks. These&#xA;&gt; are material considerations that Greg touched on but it doesn&#39;t sound&#xA;&gt; like you fully appreciate just yet. When a tx is pre-validated the&#xA;&gt; rules applied must be the same rules as those of some future block.&#xA;&gt; Yet a tx can be included in more than one block (different branches).&#xA;&gt; Across branches and even in one branch, validation rules change, and&#xA;&gt; can change back. The changes are based on accumulated branch history.&#xA;&gt; Pre-validation can later become invalidated, and differently in&#xA;&gt; different branches. And maintaining proper context requires either&#xA;&gt; storing state that you are apparently not storing, or invalidating&#xA;&gt; optimizations. Based on your comments you do not seem to be accounting&#xA;&gt; for this in your storage assumptions or in your results. A recent post&#xA;&gt; by Greg highlights the complexity and consensus criticality of these&#xA;&gt; considerations.&#xA;&#xA;Frankly, I think this is a bit of an exaggeration. Soft forks are&#xA;counted on a hand, and I don&#39;t think there are many - if any -&#xA;transactions in the current chain that have changed compliance based on&#xA;height. This makes this a compliance issue and not a performance issue&#xA;and the solution I have explained, to add height-based compliance as&#xA;meta data of validation seems to &#xA;be adequate and safe.&#xA;&#xA;&#xA;&gt; The hash table store that I described can fully navigate the block&#xA;&gt; tree and transaction DAG, since the stored tx, parent and point hashes&#xA;&gt; are also natural keys and each link is navigable in constant time. It&#xA;&gt; is also lock-free, can concurrently write any number of blocks during&#xA;&gt; initial block download and supports read/write concurrency. It has&#xA;&gt; successfully indexed and stored the entire blockchain from the P2P&#xA;&gt; network in 16 minutes (locally). It also stores both confirmed and&#xA;&gt; unconfirmed transactions in the same store, so there is nothing to&#xA;&gt; write when a block is confirmed except for the block header/hashes and&#xA;&gt; updates to spender heights for any output spent by the new block&#39;s&#xA;&gt; txs. It is similarly capable of storage in the block table of weak&#xA;&gt; chain blocks...&#xA;&gt; &#xA;&#xA;I think I get the gist of your approach and it sounds very interesting&#xA;and I will definitely dive in deeper.&#xA;&#xA;It also seems sufficiently different from Bitcrust to merit competing on&#xA;(eventual) results instead of the complicated theory alone.&#xA;&#xA;Best,&#xA;Tomas</html></oembed>