Bitcoin full node and query server

March 2021

Archive of the libbitcoin Slack #general channel.

Sunday, March 7, 2021

evoskuil00:23
Who runs bitcoin.it?
evan00:27
Someone going by ccedk
Lol no that’s not it
evoskuil00:28
Looking for admin contact info. My password expired and their reset doesn't work.
evan00:28
Ahah
evoskuil00:28
I think I know him, just can't remember who it is.
Contact info
evoskuil00:30
Hm, saw that page but missed the IRC, thx.
👍 1
neillm00:30
Not super useful, but a channel is specified
evan00:30
Yup irc
evoskuil00:31
looks good, thx
looks like ICU is up to 68.2 and we are on 55.2 🙂
😮 1
neillm00:34
I noticed the deps lagging a bit
evoskuil00:34
This dependency work is a rabbit hole
I hate dependencies, as you know 🙂.
neillm00:35
Maybe we can add openssl back in someday ...
evoskuil00:35
I removed like 10, and you added three.
😅 1
Jesus no
OpenSLL was a nightmare, especially with GMP/MPIR.
(edited)
Boost with ICU is still a nightmare.
neillm00:37
Yeah, that's probably the single biggest pain point
evoskuil00:38
We've got several hacks to make boost with ICU compile, since they don't use package config to discover it (we do it for them), and boost itself is a completely non-standard build that doesn't export package config.
evoskuil00:45
Unfortunately ICU is required for normalization, except in win32, where I wrote it in win32 natively (as normalization is native to the OS and boost doesn't link ICU statically in Win32). Boost also fails to link statically on Linux/macOS, but we work around that with a hack. They explicitly don't like static linkage for ICU, which is stupid. https://svn.boost.org/trac10/ticket/9685
And the reason we need this is because you again @neillm 🙄
neillm00:47
I didn't write the BIP!
evoskuil00:47
Dragging ICU into a BIP had to be the one of the dumbest things I've seen.
neillm00:48
If there are other normalization options, I think we should be able to use them (like win32).
evoskuil00:49
We do, but as far as I know nothing on linux/osx. Please feel free to find something!
ICU is a massive dependency.
neillm00:50
I'll add it to the list for when I have time 😅 Been fried on weekends lately. Hoping it gets better later this year
evoskuil01:19
👍
evoskuil01:47
looks like belcher has bitcoin.it
👍 1
1 reply · evoskuil · last Mar 09, 2021
evoskuil00:31
Actually Kalle is the overall admin on bitcoin.it.

Wednesday, March 10, 2021

P
Phil14:12
Hello! Guys I see write_reverse() defined in some places in the sourcecode, but it is actually never used. what is it meant for?
evoskuil14:24
I believe it writes bytes to a stream in reverse order.
Did you look at all repos?
P
Phil14:41
To the best of my C++ skills it looks like write_reverse() is not used in any LB repo. Is there oe call to write_reverse() potentially being made by boost or by libstdc++, I presume not, or ??? At least there is no explicit call to write_reverse() anywhere in LibBitcoin
(edited)
evoskuil14:43
🤷🏻‍♂️
It’s a library.
👍 1
P
Phil15:06
Is libbitcoin-system’s bitcoin/..../serializer intended to ever be used from outside of LibBitcoin? to my best awareness there is no legitimate usecase when a user of LibBitcoin would access the blockchain file directly, so therefore write_reverse() should never be used, because write_reverse() in LibBitcoin is always a write to the blockchain file?

Monday, March 15, 2021

evoskuil08:23
The use is for writing bytes in reverse order. It's a common scenario when dealing with endianess issues. For example, bitcoin deals with hashes in both orders. And of course libbitcoin reads and writes blockchain data directly, we implement a full node.
Why is this a concern for you?

Tuesday, March 16, 2021

Milosz Muszynski19:50
hi, I switched from version 3 to 4 recently, and I replaced, say, bx fetch-balance msWHhBL1vLycmZtQ5M1j7xWuUYvienydfq with bx address-to-key msWHhBL1vLycmZtQ5M1j7xWuUYvienydfq | bx fetch-balance , also changed servers in bx.cfg to version 4 servers. Issue is balance shown is now different than what Electrum is showing. Before, in version 3, it was always agreeing with Electrum, tried 3 different addresses, they all show different balances than Electrum. Could you advise what I am doing wrong? Also, are there any mainnet libbitcoin version 4 servers?
neillm19:51
No public ones other than an unofficial testnet server (as of yet). I believe a v4 mainnet server will be coming online at some point in the near future though. The balance indexing is different in v3/v4, with v4 having the more complete history
Milosz Muszynski19:56
Thank you for your answer. Does it mean that Electrum shows correct balance for the entire wallet, but incorrect balances for particular addresses?
neillm19:57
Unfortunately, I don't know much about electrum indexing at the moment, but heard it was supposed to be changing to the same kind we use in v4
evoskuil19:58
Given v4 server isn’t complete (or hosted) it’s not surprising. Did you build and sync your own?
Milosz Muszynski20:04
I see, makes sense. I was thinking about running my own soon, yet in version 3 didn't feel urgent need. Now I think I will do it.
👍 1
evoskuil20:05
Note that v3 cannot index for Electrum
neillm20:05
Got a testnet v4 up for testing: http://testnet2.libbitcoin.net:29071/ (endpoint ports are 29091/29092/29093/29094)
evoskuil20:06
If there are issues in v4 testnet it’s worth looking into, since it does sync. Tho there is no indexation of the tx pool, so only confirmed txs.
Milosz Muszynski20:08
My addresses were confirmed few days ago, I could give some examples with possibly wrong balances
I am using testnet2.libbitcoin.net:29091
mpS14bFCZiHFRxfNNbnPT2FScJBrm96iLE gives 3916000, electrum shows 1958000
address miJNzPfaB6buRjTzr1RDaR2uNjbHhfneX4 shows something very weird
bx address-to-key miJNzPfaB6buRjTzr1RDaR2uNjbHhfneX4 | bx fetch-balance
balance
{
    key 1681de56d73e2824e47973ff36ae628b41e2d11990f1448e022186bbf3bdd456
    received 18446744073709551615
    spent 18446744073709551615
}
electrum shows just 8000 satoshis for this address
neillm20:19
There could be an error in the indexed data (database) or the client (where the results are processed/accumulated). See if you can find where the problem originates
Milosz Muszynski20:20
ok, looks like other addresses have similar issues, strange though that in version 3 I did not have any discrepancies for same addresses
neillm20:20
^ Also to avoid another potential problem, best to try it on your own sync'd server
v4 isn't finished
Milosz Muszynski20:21
yes, I will do that, I see
thanks for your help
evoskuil20:29
V4 is good for resting the new interface, but blockchain/store is unfinished.
Milosz Muszynski20:49
reason I switched to V4 was that V3 does not have electrum.cpp in wallet, only mnemonic.cpp, so I could not find working code for electrum mnemonic seed, only BIP39, in V4 both electrum and BIP39 work fine, so I am kind of reluctant to go back to V3
but maybe I could have compiled V3 with WITH_ICU ? would this help? I compiled V4 with WITH_ICU instead
evoskuil21:00
That won’t affect the change. You could run v3 bx for Electrum and v4 for client server work. If you need them integrated you could backport the Electrum command to v3 bx.
Milosz Muszynski21:03
I see, I need it integrated, so I think I will backport
evoskuil21:05
If you make the necessary PR to v3 libbitcoin-system I will do the code generation for libbitcoin-explorer and drop in the src and test changes.
Milosz Muszynski21:10
ok, thanks, I'll try to do that
evoskuil21:14
Note that v3 or v2 had bx Electrum wallet support. It was prematurely dropped in favor of BIP39 and then restored in v4. You might be able to rebase the old code.
But also Electrum updated their format, so it may have been the older original format
Milosz Muszynski21:20
yes, that's what I thought, that it was there before, I'll try to dig it up, also will look if and how Electrum updated their format since then
neillm21:52
If I recall correctly, the old electrum code is unrelated to the new electrum code
v1 support was removed and v2 support was added: https://electrum.readthedocs.io/en/latest/seedphrase.html
evoskuil22:02
Better to backport then.
Milosz Muszynski22:06
I see, ok

Thursday, March 18, 2021

Milosz Muszynski10:23
Please have a look, the change works fine for me so far..
1 reply · evoskuil · last Mar 18, 2021
evoskuil13:05
Thanks, I’ll give it a good look in the next couple of days
👍 1
evoskuil12:07
I've completed the removal of qrencode, png and zlib external dependencies. Implemented our own two-color uncompressed tiff encoder from spec, with support for all possible size and shape images. Incorporated qrencode into our sources and redesigned the encoding conversion using our bit writer/reader classes. Added a complete set of tests, generated all manner of images, scanned them for verification and parsed some using online readers. So... the failing test has been repaired 🙂. And we now have full cross platform support for all features, and are back to just boost, secp256k1 and zeromq (for client-server libs).
👍 3
neillm12:54
Can png files still be output?
evoskuil12:57
Nope, but you can trivially convert tiff to png.
And at this point I also think it would be trivial to implement a png and/or jpeg encoder.
2 replies · evoskuil · last Mar 18, 2021
evoskuil13:10
Also, I removed the raw output format. The uncompressed TIFF output is sufficient to obtain the logical pixel data in a reliable manner, just using margin 0 and module pixels 1. I placed the image at the end of the file at a fixed offset, with the offset published from the tiff class header. Of course one can also use the API directly as well.
evoskuil13:13
I chose tiff because it was an old common format, and pretty simple. But I read that png was designed to be simpler, so I might give it a shot and if it works out we can just and an image type enumeration class to the command line parser to support various formats.
evoskuil13:05
replied to a thread: view
Thanks, I’ll give it a good look in the next couple of days
👍 1
evoskuil13:10
replied to a thread: view
Also, I removed the raw output format. The uncompressed TIFF output is sufficient to obtain the logical pixel data in a reliable manner, just using margin 0 and module pixels 1. I placed the image at the end of the file at a fixed offset, with the offset published from the tiff class header. Of course one can also use the API directly as well.
evoskuil18:42
I didn’t check, but I believe the qrencode test was failing after upgrading qrencode because its output is a private format. It includes metadata that can change without affecting the module (visual) presentation. This is a good reason to not publish it from bx. The TIFF format (or any uncompressed image format), without margin or scaling, is a strict binary representation of the matrix of modules.
(edited)
👍 1
This had been the problem with a test against libsecp256k1 a while back, which failed under big-endian architecture.
neillm18:54
Thanks for looking into this.
Only reason I was wondering about png format specifically is because there may be some wallet code out there that relies on rendering those output files -- but it seems that TIFF is also supported by Qt, so likely a non-issue (cc: @gh).
evoskuil19:11
👍 — master subject to interface changes.

Friday, March 19, 2021

evoskuil18:18
Upgrade to boost 1.72, current secp256k1, zeromq and consensus sources, as well as removal of qrencode, png and zlib dependencies has been merged. NuGet packages for secp256k1 have been uploaded, though I'm not intending to update NuGet for zeromq. Instead I'm planning to move to vcpkg, which is c++ oriented and includes more current boost packages, and includes well-maintained zeromq packages. secp256k1 packaging continues to be a problem as the library is not versioned, so I'll end up building (only) and maintaining a package for it. Once this is complete I will create vs2019 project files and remove generation and testing of vs2013 (vc120/c++11 CTP). There are Travis breaks on all macOS builds due to a Travis change affecting boost installation. I'm going to resolve this next, and add builds for the Travis big-endian and Windows platforms. Also on the build roadmap is generation for mingw builds and VS code projects for all three platforms.
👍🏾 1
neillm18:37
Nice work, will kick off new local builds this weekend to give it a go!
👍 1

Tuesday, March 23, 2021

L
lucaferr10:55
Why is the scriptsig field when spending p2sh-pwpkh input prefixed twice with a data push?
(edited)
2 replies · lucaferr · last Mar 23, 2021
L
lucaferr10:56
I thought it was supposed to be ”0x160014<pkh>”
L
lucaferr10:57
But looking at a bitcoin core transaction it’s actually ”0x17160014<pkh>” why is that? Something to do with bip16?
(edited)
evoskuil10:56
link?
evoskuil11:05
segwit scripts can be embedded in p2sh scripts.
L
lucaferr11:09
// Embedded script must be at the top of the stack (bip16). script embedded_script(input.pop(), false);
So maybe this is the reason. Just seems odd with 17160014 as the witness program itself (hashed data) is done without 16 prefix
evoskuil11:11
Dunno, I don't look to much at the bytes.
L
lucaferr11:11
Ok, thanks - just asking out of curiosity
👍 1
evoskuil11:15
In segwit the signature script is in the witness.

Wednesday, March 24, 2021

P
Phil21:58
Hello guys! I’d like to understand how can I add listener hooks and how to poll for the block hash and the block height in respect of the block header syncing process and block body syncing process, respectively. I’ll use these two datums (/data streams) to produce a 0-100% progress bar of the syncing process (a la the one in Bitcoin Core’s UI).

Thursday, March 25, 2021

vdeurzen09:29
You can register callbacks for blocks and transactions (and headers I think too?) You can see this in the node implementation code (libbitcoin-node). At least that is what I did to get a stream of blocks / transactions to process 🙂
evoskuil09:29
blocks are headers
IIRC the subscriptions are for txs and headers.
Are we talking about server endpoint subscription or c++ API subscription (via node)?
node provides two subscriptions, reorganization (a list of blocks) and transaction (pool acceptance).
🙌 1
vdeurzen09:38
I was talking about the C++ API and indeed I meant reorganization and transaction
evoskuil09:39
Server (zeromq) provides broadcast block and transaction subscription endpoints (which can also be accessed directly via the C++ API): https://github.com/libbitcoin/libbitcoin-server/wiki/Transaction-Service https://github.com/libbitcoin/libbitcoin-server/wiki/Block-Service
But looks like I was mistaken. The subscriptions are full data. Some of the ZMQ queries return block header and tx list only, vs full block.
evoskuil09:51
The block objects are already in memory during the reorg, so there's only a performance hit in recreating the blocks as headers. You just read the header out of the block pointer.
And of course, every organization is a reorg.
The reorg subscriber provides a list of block in and blocks out. Out will usually be empty.
P
Phil12:13
Blocks are headers
Well but in the header-first sync part of the sync, a header is not a block yet right - so there are two phases of the sync?
evoskuil12:18
There’s one continuous phase. Headers are always being requested and downloaded and blocks are being filled in behind them in parallel. We notify only when we’ve organized a validated block.
And v3 doesn’t operate on headers.
Block requesting is delayed until a configurable time gap prior to current time, to make sure we have a strong enough chain, and enough hashes to warrant starting parallel block download, but that time gap is the only distinction
What I meant by blocks are headers is that in the server query model you query for a block by getting the header and a tx hash list and then requesting transactions.
(edited)
But in broadcast the block is already constructed, so we push it out.
P
Phil12:48
I see. Actually I’m using v4. I wish to get reports of block header sync aspect too. This will help me produce a better 0-100% progress bar to illustrate the sync status to the user in an UI
P
Phil13:22
ah - for clarity: currently what do you use, what is the recommended way, to estimate the % sync status of of the blockchain?
evoskuil18:15
Confirmed height relative to some target. The reorg message included fork height.
We could emit a similar message for headers, as they reorg into their own chain in the same way.
We maintain a candidate index index and a confirmed index. The candidate chain is the next strongest relative to the confirmed. When it becomes stronger it’s reorged into the confirmed chain. At equilibrium they are the same. Lesser branches are maintained in an in memory tree relative to the candidate index and are purged based on configurable max confirmable depth.
(edited)
evoskuil18:25
Valid headers, and txs valid relative to the confirmed chain (neither have to be in a confirmed block), are stored once in the header table and tx table, never moved or purged. We download unpopulated candidate blocks in parallel when the candidate chain is stronger. Txs are stored in parallel when blocks arrive, then validated and confirmed in block order.
So you have a few indications of completeness.
The console puts out a good amount of information.
P
Phil18:43
What do you mean by “We download unpopulated candidate blocks .. when the candidate chain is stronger”>
evoskuil19:00
An unpopulated block is one where we have its header only and are missing txs.
Once you know a block you want there is no need to download it in order, so parallel. We store in parallel as well, marking the block confirmed at the point where it’s validated in the strong chain. Every new strong block is a reorg, even if the weaker branch is empty.
(edited)
P
Phil19:05
Is the log output configurable? My node instance prints me a lot of ‘Reject duplicate’ messages. I wonder, does this show that something is broken under the hood in my LibBitcoin setup, OR is this only LibBitcoin telling me that a block I already received from one peer LibBitcoin now received from another peer too, and that is supposed to happen all the time always right so it is not an error? I guess the latter applies, please confirm however as I did some deep plumbing in my LibBitcoin and wish to confirm to myself that my LibBitcoin works, I did not break it.
evoskuil19:09
Yes, see config settings.
Are you running v4?
P
Phil19:09
yes
evoskuil19:11
v3 produces a lot of block duplicate messages, IIRC that’s not common in v4.
V3 is requests the same blocks across peers. V4 doesn't, it only competes on headers.
P
Phil19:17
So you say the header-sync-first is implemented within LibBitocoin’s design of internally tracking a candidate chain and a confirmed chain. When you say “We download unpopulated candidate blocks in parallell when the candidate chain is stronger” - are you saying that the headers-first sync ONLY downloads block headers into the candidate chain, or that it downloads then into the candidate or confirmed chain depending on situation; Does “confirm chain” have the notion to it that all transactions have been downloaded already? To get the supposed total height of the Bitcoin blockchain during sync, should I use as data source, listening/polling for the height of the candidate chain?
Wait just so I understand the “lesser branches are maintained in an inmemory tree relative to the candidate index and are purged ..” So: LibBitcoin has one “current chain” called “confirmed chain”, which can grow, and then at a time it’s exploring only one alternative chain at most - that is like, in case of a reorg - and that one is called the “candidate chain”. So the in-ram tree you are talking about now is for tracking third, fourth etc. chain options - and you’re saying those chain structures are only in RAM, also as they shouldn’t really be of any significant size anyhow?
evoskuil19:33
Bitcoin is a tree index of headers, and blocks are indexes of txs per header. The data all has two levels of validation. Static validation is structural, and independent of any external state. Contextual validation is relations to other elements. The tree can be built with static and limited contextual validation (blocks to each other and txs to blocks). This relies on work to give storage a cost.
Transaction points (ins and outs) form a DAG. This is contextual but does not require headers/blocks. The blocktree is a tree that points to elements of this DAG.
Txs rely on fees to give storage a cost. Population of the full data structure is not necessary in order to answer certain questions.
A “chain” is a linked list that relies on natural (internal) keys. This is merely an index of a path through the tree.
A “memory pool” (we don’t use RAM this way, it’s all on “disk”) is a subset (index) of the DAG.
(edited)
We let the OS decide what to keep in RAM, that’s its job.
Indexes are search optimizations. They aren’t necessary from a logical standpoint.
Based on static and contextual validation each header and tx has a state. Each can be populated, or not, each can be validated or not, each can be confirmed, or not.
Inputs also have states, as they can be spent, or not.
(edited)
Notably these states are contextual. It depends on which chain you are considering. A header or tx can be valid in one or more chains but not another. An input can be spent in one or more headers, but not another.
(edited)
In order to answer the question of whether one chain (tree branch) is “stronger” than another, one must maintain at least two chain indexes.
Logically each leaf in the tree represents a candidate or confirmed chain. The confirmed chain is merely the strongest.
evoskuil19:55
As an optimization we maintain an index of the confirmed branch and the next strongest branch, as more than one competitive candidate is extremely unlikely. A 51% attack is two competing chains. Furthermore, maintaining weak branches incurs almost no storage cost, so a decision to preclude weak branches below some arbitrary depth becomes important, though arbitrary.
evoskuil20:02
So the full tree is a pruned (based on configured max reorg depth) memory structure of headers. Similarly, the tx DAG is limited to sufficient fee against currently confirmed ancestor tx outputs (or currently confirmed).
So when you query this structure, you gotta think about what question you are asking.
P
Phil20:07
I am in v4 (master chain). I do indeed get a lot of [2021-03-24 15:24:15.729142] [0x000007cdc65cda40] [info] Rejected duplicate header [0000000064fc01456747cf00e6f9dd25cbdd3d444823c54e94cbed3681d9909a] from [24.222.43.8:8333] Does this hint at any problem? Is it just a coincidence, due to my Internet connection and proximity to peers such, that I get extra copies of same block from different peer such?
evoskuil20:15
Oh, headers... yeah. As I said, v4 competes on headers, v3 on blocks. These are expected and necessary.
evoskuil20:21
When you build the tree you ask each peer for its headers using an exponentially backed-off index of your own. The peer will send its headers starting at the highest known common block. This is standard p2p behavior. We do not want to allow a subset of peers determine the chain, so these requests are promiscuous. And there is no prioritization but response time (unlike block download) apart from the configured peer timeouts, since we also don’t want to let fast peers determine the chain. All peers compete to built the tree, and the set of headers that a peer has is not knowable until they are received. So if all peers are in sync there will be up to N times duplicate headers. This doesn’t always happen in practice since the fastest responder causes subsequent requests to have higher common points.
P
Phil20:21
The longest header chain available in a Node, how do I poll for it, given LB’s persistence format?
evoskuil20:22
You use the zmq interface.
You can request by height or hash. You can also request top height, so you can walk backwards. Or just start at zero and walk forward. But when walking forward you should ensure that each block is a child of the previous, as reorgs can happen.
Hashes are natural keys, heights are foreign keys.
P
Phil20:27
wait wait, i meant block header sync only i guess LB Node’s normal metric of block height is blocks that have been downloaded and verified in full so that should be that the ZMQ RPC reflects - fully downloaded and verified blocks, isn’t it - so aside from that how do I get the highest header-only chain that the Node knows of?
evoskuil20:32
Height is an index of confirmation. While headers in weak branches all have height, we would have to identify the branch to make the information meaningful. So we don’t have a height query for unconfirmed blocks. But if you know the hash you can query. Though we may not currently support emission of unpopulated or unconfirmed blocks. That’s a fairly trivial distinction tho, can easily be updated. Same for txs. If you have the hash you can request it.
We could certainly provide a query to respond on the candidate chain, and to subscribe/broadcast. Once they are candidates they are queryable. These are just lower priority than completing the actual blockchain implementation.
There are material performance optimizations remaining, and at least one deadlock, and at least one store corruption issue in v4. I’m working my way through a long backlog right now. But when that’s done I’ll be back to the blockchain/store work necessary to get v4 released.
P
Phil21:07
So you are saying that LibBitcoin is not really indexing the block headers and not counting the height of the highest ‘block headers chain’ found. What about instead then that from my program I construct that counter function myself, by starting from the genesis block and then asking the LB Blockchain persistence, which child block headers it has - and then ask those block headers which children they have - etc - and this way i traverse the whole tree, would that make sense?
4 replies · evoskuil · last Mar 25, 2021
evoskuil21:18
We don’t index children of blocks. Blocks point to their parents and there’s no optimization in pointing to children.
(edited)
evoskuil21:19
And given that you may not be seeing all branches, it’s not authoritative information.
evoskuil21:19
It’s maintained so that we can optimize discovery of the strongest chain we can see.
(edited)
evoskuil21:21
Children lists are variable length, so they increase complexity and storage cost materially.
P
Phil21:07
What do you mean by emission, you mean queryability in the LB blockchain query api?
👍 1
evoskuil21:16
The only real reason to maintain a height index is so that people may query by it. There is one optimization in validation (coinbase depth), but we store height with the block header, so the index is not actually necessary.
Note that more than one header can have the same height.
evoskuil21:31
We should step back and start with your objectives. As I understand it you want to provide UI feedback regarding chain state, including currency.
And that application is intended to operate over a v4 node or server for blockchain and maybe tx pool queryability. I don’t recommend node for anything apart from building a replacement for server. bc::server is a very thin layer over bc::node (it’s a derived c++ bc::node).
(edited)
There is a modest perf advantage in terms of object serialization of deriving your own server, but then it’s locked into an in-process model, which is not at all ideal for most scenarios. The only reason for such tight perf considerations is validation, which is completely internal to bc::node.
The server’s zmq interface supports in-process, oop, network and internet communication (with client and/or server security) at very high scale, with inherent protocol optimization for each scenario. It really cannot be beat.
It provides for single worker thread per endpoint (asynchronously) with a configurable number of threads for the query service. It manages slow and fast clients rationally, so it cannot be overflowed or locked by misbehavior on any endpoint, even on a single thread.
(edited)
bc::node does not have all of these characteristics. Its in-process clients are trusted.
(edited)
So the zmq interface is where you should be looking. The query endpoint is very flexible. It can be easily modified to support any query/information exposed though bc::blockchain or bc::node.
If I was trying to show currency in a UI I would not count blocks or headers.
Currency is a probabilistic relation to time.
Headers do not prove either their tx count or their byte size, so you don’t know size until you have the block, and you don’t know validation cost until you validate, which both matter a lot to speed. Below about 300k BTC screams, after that it slows by 3 orders of magnitude.
(edited)
So you are better off using a time-based heuristic to provide a histogram for UI completeness feedback.
With knowledge of chain history, you can factor in time cost in certain well-known ranges. You know the time of block zero, checkpoints, and you know the current time. You also have a very reliable probabilistic and historical average block time of somewhere less than 10 minutes. That’s really good information, much better than linear block height.
Furthermore, since bip90 and the bip16 “buried deployments” hard forks, you have additional information at much greater heights. Though checkpoints are soft forks, the chain must pass through them. Though BD are hard forks, the chain does not have to pass through them. But you can reasonably rely on the probability of that happening (hitting them in both cases) for histogram purposes.
(edited)
evoskuil22:07
As for unconfirmed header state, and unconfirmed block download state. These are not currently broadcast but could be. There is logically a pool of peers with header list requests outstanding, a pool of unique blocks requested (by header) but not received (unpopulated blocks of unknown size in the strong chain), knowledge of the top confirmed and top candidate block (therefore times and heights), a config (time) setting that determines when the stronger candidate chain is current enough to start downloading.
evoskuil22:48
Builds are all back up to snuff on master, with updated/dropped dependencies and Travis config. Version3 is also updated, but I still have to work through warnings. I'm also in the process of completing the Electrum backport for version3 and will be backporting qrencode and tiff integration after that. The current version3 now has a common file system configuration (in -system) and the -build support for version3 and master has been consolidated to just a different generate.xml for each branch. Both branches now have the same set of dependencies and Travis builds, with the exception of mbedtls on master.
🙌🏾 1

Friday, March 26, 2021

P
Phil11:15
> The only real reason to maintain a height index is so people can query by it Querying by height is a disaster recipe, you want to query by block hash always, though sure keeping hammering the function “give me the block hash of the highest block you have” is core agrede.
3 replies · evoskuil · last Mar 26, 2021
evoskuil18:46
Not sure I follow.
evoskuil18:51
But yes, a top query is useful and doesn’t require a height query.
evoskuil18:55
The confirmed height index is mostly used to quickly identify the path through the strong branch for internal purposes, such as for generating a block requestor message.
mileschet11:22
Hi @evoskuil i have watched today this video that you mention about decentralization of mining pool, this something of my personal interest i would like to learn more on possible paths in order to make it happen.
3 replies · evoskuil, jungly, mileschet · last Mar 27, 2021
evoskuil18:47
Cool, @jungly is heading up this effort right now.
👍 1
jungly07:41
Hi @mileschet awesome to hear you are interested in the project too. I am trying to wrap up a draft proposal I have so that it can be effectively reviewed. Will take another few days. Will definitely ping you when it's ready.
mileschet10:02
thank you ! looking forward to it!
P
Phil11:30
> I don’t recommend node for anything else than a replacement for server. Yeah that’s kind of what we do, we’re running our own Node instance inside our own C++ program which then does blockchain explorer operations etc. on the Node. So kind of “embedded Bitcoin Core” usecase kinda you see what i mean
1 reply · evoskuil · last Mar 26, 2021
evoskuil18:49
Ok, as long as you aren’t trying to scale that out, it’s optimal for a single host. Likewise Core isn’t much of a scale server.
evoskuil18:46
replied to a thread: view
Not sure I follow.
evoskuil18:47
replied to a thread: view
Cool, @jungly is heading up this effort right now.
👍 1
evoskuil18:49
replied to a thread: view
Ok, as long as you aren’t trying to scale that out, it’s optimal for a single host. Likewise Core isn’t much of a scale server.
evoskuil18:51
replied to a thread: view
But yes, a top query is useful and doesn’t require a height query.
evoskuil18:55
replied to a thread: view
The confirmed height index is mostly used to quickly identify the path through the strong branch for internal purposes, such as for generating a block requestor message.
P
Phil22:00
@evoskuil Thank you for all this information and all your effort to contribute to my learning!
evoskuil22:16
👍 thanks for being a libbitcoiner
👍 1
P
Phil22:17
> it’s optimal for scaling out. also Core doesn’t scale Yeah. I’ll implement some Bitcoin indexing a la colored coins, query service, RPC that kind of thing on top of Node
(btw what do you mean scale out, anyhow i guess i see what you mean)
1 reply · evoskuil · last Mar 27, 2021
evoskuil22:11
I mean that if you want it to operate at scale you will end up reproducing the server code. If you want extend query it might be worth considering deriving from server and adding queries and/or another endpoint.
evan22:19
I think that was rule #2 when Amir first built it

Monday, March 29, 2021

P
Phil11:48
@evoskuil just to confirm, LB uses bind() for callbacks rather than C++11 lambdas, because code conciseness is higher with bind() than with lambdas, right?
evoskuil17:59
Yes

Wednesday, March 31, 2021

P
Phil19:48
Hello guys! So I was checking bn’s code and I noticed that `close()` needs to be called from the main thread. Inside full_node’s code it leads me to check “join”. But I don’t understand what is “join” a reference to. Could you help me understand that?
// Close must be called from main thread.
if (node_->close())

// This must be called from the thread that constructed this class (see join).
bool full_node::close()
(edited)
evoskuil19:50
Join refers to the thread join. The process cannot terminate until threads are all coalesced, which join waits on.
A threadpool thread cannot call close, since it will then deadlock as it is waiting on itself. That’s why the comment is there.