Archive of the libbitcoin Slack #general channel.



assumevalid , but still confirmation. Otherwise you are not comparing apple to apple with Core.strong_tx records in the thread where downloads are stored. This allows that to be performed concurrently, which is a material savings depending on platform. For checkpoints these records are logically irreversible. Milestone block validity is logically irreversible, but a milestone chain (or part of it) may not be a strong chain. So the reorganization of a milestone block reverses the strong_tx association.
Since milestone block validity is irreversible, the status as a milestone is stored with the block header. Checkpoints don't require this storage, since they are identifiable by height alone (once headers have been validated, which precedes any storage). Consequently it is the case that a milestone block may end up in a branch that does not actually contain the configured milestone (though must have at one point). In other words, a block that is valid under milestone necessarily remains valid in any other context. This observation simplifies the reorg of a milestone branch, since blocks below the fork point are unaffected by the reorg (i.e. do not have to be validated).strong_tx is associated for a block before the confirmability checks for that block occur. This allows the block to be identified as part of the candidate chain under check without identifying the candidate blocks above it as so. But confirmation is the process of reorganizing a confirmable candidate chain into the confirmed height index. Not until that point is any block in the candidate chain considered confirmed (despite being and "strong" and "confirmable"). Confirmable (unlike the strong association) is a terminal state. So a confirmable block never needs to be revalidated (i.e. for reorganization). The final step of confirmation is not necessary (or even used) for validating subsequent blocks, as that is all performed in the candidate chain, and organizing an entire 850k blocks as confirmed (push_confirmed) under milestone takes only a couple seconds.assumevalid to genesis. I set dbcache to the max value documented in the config file (this is a 256GB RAM machine). BN was configured to maintain 200 connections, but I don't think that setting that above the default of 125 for BN would be helpful for it, possibly detrimental - so left that. txindex is on and listening, txs, wallet are all off (same as BN). There's no way to get BN's level of indexation out of BC (I don't think "coins" is comparable, have to look into that). Also on this machine the hardware is not shani and is limited to av2, so that results in the same capability for both BN and BC.
#genesis assumevalid=000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f blocksonly=1 dbcache=16384 txindex=1 listen=0 #maxconnections=125 (default) disablewallet=1
strong_tx records in the thread where downloads are stored. This allows that to be performed concurrently, which is a material savings depending on platform. For checkpoints these records are logically irreversible. Milestone block validity is logically irreversible, but a milestone chain (or part of it) may not be a strong chain. So the reorganization of a milestone block reverses the strong_tx association.
Since milestone block validity is irreversible, the status as a milestone is stored with the block header. Checkpoints don't require this storage, since they are identifiable by height alone (once headers have been validated, which precedes any storage). Consequently it is the case that a milestone block may end up in a branch that does not actually contain the configured milestone (though must have at one point). In other words, a block that is valid under milestone necessarily remains valid in any other context. This observation simplifies the reorg of a milestone branch, since blocks below the fork point are unaffected by the reorg (i.e. do not have to be validated).strong_tx is associated for a block before the confirmability checks for that block occur. This allows the block to be identified as part of the candidate chain under check without identifying the candidate blocks above it as so. But confirmation is the process of reorganizing a confirmable candidate chain into the confirmed height index. Not until that point is any block in the candidate chain considered confirmed (despite being and "strong" and "confirmable"). Confirmable (unlike the strong association) is a terminal state. So a confirmable block never needs to be revalidated (i.e. for reorganization). The final step of confirmation is not necessary (or even used) for validating subsequent blocks, as that is all performed in the candidate chain, and organizing an entire 850k blocks as confirmed (push_confirmed) under milestone takes only a couple seconds.assumevalid configuration, and it's not. Then I located this line in the debug.log:
2024-11-02T03:22:55Z Config file: M:\Core\Data\bitcoin.conf (not found, skipping)
assumevalid). I suspect the lack of concurrency combined with the lack of shani is what's making this materially worse than the $350 mini (also Windows).assumevalid for all), on:
Dell, Windows 10 32 Dual 2.1GHz cores 256GB 2400MHz RAM 4TB 7,450 MB/s SSD PCIe3 AVX2, no SHANI 2.3Gps down / 40Mbps up Internet (measured)
txindex enabled, and 25 GB higher without it. BN with database.minimize enabled is another 50GB smaller (through input point consolidation), though neither were enabled in these runs.assumevalid run, given that there are at least 63 free threads to validate. My theory is that it won't take much longer.
2024-11-03T12:57:37Z Using data directory M:\Core\Validate 2024-11-03T12:57:37Z Config file: M:\Core\Validate\bitcoin.conf 2024-11-03T12:57:37Z Config file arg: assumevalid="000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f" 2024-11-03T12:57:37Z Config file arg: blocksonly="1" 2024-11-03T12:57:37Z Config file arg: dbcache="16384" 2024-11-03T12:57:37Z Config file arg: disablewallet="1" 2024-11-03T12:57:37Z Config file arg: listen="0" 2024-11-03T12:57:37Z Config file arg: txindex="1" 2024-11-03T12:57:37Z Using at most 125 automatic connections (2048 file descriptors available) 2024-11-03T12:57:37Z Wallet disabled!(edited)
assumevalid) 500,000 blocks in 4.5 hours. At that rate it would complete at a total of 32.7 hours. Even with full blocks it's only using ~15% CPU. So I'm going to stop this run, reset the automatically-determined validation thread count from 16 (15 additional) to 64 (63 additional), and restart.# Set the number of script verification threads (0 = auto, up to 15, <0 = # leave that many cores free, default: 0) #par=<n>
2024-11-03T21:57:03Z UpdateTip: new best=00000000000000000071ef0363647bbfb591b04ee268642060596ca21b7671d7 height=500298 version=0x20000000 log2_work=87.697860 tx=284383466 date='2017-12-20T18:03:47Z' progress=0.257010 cache=7979.4MiB(62457317txo) 2024-11-03T21:57:03Z opencon thread exit 2024-11-03T21:57:03Z Shutdown: In progress... 2024-11-03T21:57:03Z addcon thread exit 2024-11-03T21:57:03Z msghand thread exit 2024-11-03T21:57:03Z net thread exit 2024-11-03T21:57:03Z DumpAnchors: Flush 2 outbound block-relay-only peer addresses to anchors.dat started 2024-11-03T21:57:03Z DumpAnchors: Flush 2 outbound block-relay-only peer addresses to anchors.dat completed (0.00s) 2024-11-03T21:57:04Z scheduler thread exit 2024-11-03T21:57:04Z Writing 0 mempool transactions to file... 2024-11-03T21:57:04Z Writing 0 unbroadcast transactions to file. 2024-11-03T21:57:04Z Dumped mempool: 0.000s to copy, 0.005s to dump, 27 bytes dumped to file 2024-11-03T22:03:27Z Shutdown: done
# Set the number of script verification threads (0 = auto, up to 15, <0 = # leave that many cores free, default: 0) #par=<n>
2024-11-04T14:22:07Z Config file: M:\Core\Validate\bitcoin.conf
2024-11-04T14:22:07Z Config file arg: assumevalid="000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
2024-11-04T14:22:07Z Config file arg: blocksonly="1"
2024-11-04T14:22:07Z Config file arg: dbcache="16384"
2024-11-04T14:22:07Z Config file arg: disablewallet="1"
2024-11-04T14:22:07Z Config file arg: listen="0"
2024-11-04T14:22:07Z Config file arg: par="-1" <<<<<<==========
2024-11-04T14:22:07Z Config file arg: txindex="1"
2024-11-04T14:22:07Z Using at most 125 automatic connections (2048 file descriptors available)
2024-11-04T14:22:07Z Wallet disabled!
2024-11-04T14:22:07Z scheduler thread start
2024-11-04T14:22:07Z GUI: "registerShutdownBlockReason: Successfully registered: Bitcoin Core didn't yet exit safely…"
2024-11-04T14:22:07Z Using /16 prefix for IP bucketing
2024-11-04T14:22:07Z init message: Loading P2P addresses…
2024-11-04T14:22:07Z Creating peers.dat because the file was not found ("M:\Core\Validate\peers.dat")
2024-11-04T14:22:07Z init message: Loading banlist…
2024-11-04T14:22:07Z Recreating the banlist database
2024-11-04T14:22:07Z SetNetworkActive: true
2024-11-04T14:22:07Z Script verification uses 15 additional threads <<<<<<==========2024-11-04T14:25:24Z Config file arg: par="7" <<<<<<==========
2024-11-04T14:25:24Z Config file arg: txindex="1"
2024-11-04T14:25:24Z Using at most 125 automatic connections (2048 file descriptors available)
2024-11-04T14:25:24Z Wallet disabled!
2024-11-04T14:25:24Z scheduler thread start
2024-11-04T14:25:24Z Using /16 prefix for IP bucketing
2024-11-04T14:25:24Z init message: Loading P2P addresses…
2024-11-04T14:25:24Z GUI: "registerShutdownBlockReason: Successfully registered: Bitcoin Core didn't yet exit safely…"
2024-11-04T14:25:24Z Creating peers.dat because the file was not found ("M:\Core\Validate\peers.dat")
2024-11-04T14:25:24Z init message: Loading banlist…
2024-11-04T14:25:24Z Recreating the banlist database
2024-11-04T14:25:24Z SetNetworkActive: true
2024-11-04T14:25:24Z Script verification uses 6 additional threads <<<<<<==========assumevalid. Validating signatures on a sufficiently fast CPU (the mini has 16 threads and SHANI) will not slow down the run much, making it bound under the same conditions as assumevalid.For one, since there is no utxo set, prevouts are verified unspent by looking up the outpoint’s spending transaction and verifying that it does not exist. This to me would seem slower than looking up the prevout from a utxo set.
Based on insights from a private conversation, Libbitcoin will also skip checking confirmability if below the milestone. This means that transactions are written in order in the confirmability thread, but their inputs are assumed to exist and be yet unspent. Skipping this check is where the real speedup lies I believe, and was not clear to me on first read. With that in mind, this approach seems more like a combination of assumevalid and assumeutxo, since the signature checks are skipped and the utxo set is assumed to be valid based on the block height.
My intuition is that the speedups are coming from the more aggressive peer utilisation during download, and the clear separation of unordered vs ordered checks to take advantage of parallelism.
I do also think this is what drives most of the IBD speedup there. And it is directly related to their architecture, doing it for Bitcoin Core wouldn’t bring much benefit since you still have to update the UTxO set
Yes although in the context of this specific benchmark it’s more about being able to skip a whole class of checks than parallelizing them, i think.
Transactions table and the ConfirmationIndex is updatedThe first observation is that serving up blocks to peers is not a performance critical operation, either for the node or its peers.
Thirdly, there are a number of significant advantages in getting to completion with a compact block. There's no reason to assume that the means of verifying confirmability will have a greater cost than a utxo model
Conceptually, this seems close to a MapReduce algorithm, where unordered checks are mapped on to each range, and then the Reduce step requires sequential ordering of each range of blocks for the confirmability checks.
Clear separation between un-ordered and fully ordered checks is what makes this possible, from what I can tell. The partially ordered checks are not done under the -assumevalid / milestone model.When a Libbitcoin node serves a block to a peer, it must reconstruct the block into its serialised representation, which will require some compute for each block request. Bitcoin Core, however, stores the blocks on disk in their serialised format and will simply read the block from disk and send it to the peer
My personal view on the role of a Bitcoin node is that its primary purpose is to validate and propagate new blocks as quickly as possible, such that all nodes and miners on the network can quickly come to agreement on what the longest/heaviest PoW chain is. This is why I favour the Block based data model.
I would say we optimize for a single miner to obtain and process new blocks as fast as possible in order to be most profitable via efficient regeneration and optimization of block templates. I don't think it will be the case that Satoshi's architecture will be shown to be more optimal at doing that, but we have a long way to go.
This isn’t so much block storage which makes a difference but how their content is indexed. In this case it would be clearer to make a distinction between a historical transactions index vs an unspent outputs index.
assumevalid. Validating signatures on a sufficiently fast CPU (the mini has 16 threads and SHANI) will not slow down the run much, making it bound under the same conditions as assumevalid.ordering problem
block_archived...... 460939 4581 block_validated..... 460040 4581 block_archived...... 465833 4581 block_confirmed..... 459131 4581 block_archived...... 460189 4581




asm optimizations, since vc++ does not implement assembly in x64 builds (optional part of the c++ standards). Also, the run is limited by confirmation, not validation. I will perform some non-confirming runs just to see what is the actual improvement.









--disable-static, though after a certain depth in the project tree only static linking is supported. On windows only static linking is supported.secp256k1 is currently running at about 83% of the time of the previous NuGet version from three years ago (old version is 1.21 x the time of the new version).secp256k1 dropped validation (only) time on the maxi (no shani) from 4.0 hours to 3.4 hours (85%). Given that there is zero network variability in these runs (all blocks pre-downloaded) this is a highly reliable distinction.secp256k1 completed on the mini in 8.6 hours. I'm doing a validation only run with the previous version for the same comparison. So far update is at about 90% of earlier version.algorithm.ipp template. As part of that I just completed a much-needed refactoring of that into 12 independent .ipp files, with some organization and comments. There are a couple of ways to do the integration and it's net yet clear which will be optimal, so I'm also doing some investigations on the side. I set up a third mini with my dev environment so that I can test/debug with SHA-NI available. Hopefully I'll have something running the next couple days.tx.hash(false) 7.4% tx.hash(true) 4.9% bk.merkle(false) 0.47% bk.merkle(true) 0.48% ====================== total hashing 13.25%
avx512 (implemented) Merkle root calculations will be cut in half. Given shani (WIP) hash computations should be reduced to 20-25% of native (even with existing optimizations). That produces:
tx.hash(false) 1.5% tx.hash(true) 1.0% bk.merkle(false) 0.23% bk.merkle(true) 0.24% ====================== total hashing 3%
shani message scheduling dropped right into the template and worked straight away, independently of the shani transformation, which I haven't added yet. While this method of pre-scheduling the full block requires more memory, it has a significant advantage in terms of simplicity, and in the normal form is faster. It also allows for vectorization of the message schedule, which we do.shani algorithm (using rotating variables as opposed to a message buffer), this vectorization is limited to 4 lanes (4 concurrent additions). This is however independent of the actual shani implementation. By separating the implementation in this manner we can take advantage of 4/8/16 lane vectorization for K additions - mixing avx512 and shani.avx2 and/or avx512 (probably not sse41) message schedule vectorization is more optimal than the hardware-implemented 4 lane message processing of shani, at least for larger data hashing, where we must iterate over 4/8/16 hash blocks. In those cases we already vectorize the message buffer, which gives us about a 30% performance boost in that aspect. So we may end up outperforming the typical native shani implementation on machines with higher level vectorization.shani message scheduling amounts to this:
else if constexpr (use_shani)
{
wbuffer[Round] = mm_sha256msg2_epu32
(
mm_add_epi32
(
mm_alignr_epi8
(
wbuffer[Round - 1], wbuffer[Round - 2], SHA::word_bytes
),
mm_sha256msg1_epu32
(
wbuffer[Round - 4], wbuffer[Round - 3]
)
),
wbuffer[Round - 1]
);
}shani transformation:
else if constexpr (use_shani)
{
state[1] = mm_sha256rnds2_epu32(state[1], state[0], wk[Round]);
state[0] = mm_sha256rnds2_epu32(state[0], state[1],
mm_shuffle_epi32(wk[Round], 0x0e));
}