Bitcoin full node and query server

March 2020

Archive of the libbitcoin Slack #general channel.

Sunday, March 1, 2020

vdeurzen23:46
In an effort to get something running while my node syncs I'm connecting with the ZMQ client (following the examples). I have everything compiling, however, interestingly I'm getting the same transaction all the time when connected to the transaction_publishing port mentioned here: https://github.com/libbitcoin/libbitcoin-server/wiki/Community-Servers
Any idea what I might be doing wrong?
I'm using v4 of the libraries
vdeurzen23:55
nvm, I'm an idiot

Monday, March 2, 2020

fpelliccioni08:06
replied to a thread: view
Hi Eric, what are the specs of this beast?
evoskuil08:19
64 core, 256 GB I think, not sure. It’s about three years old now.
fpelliccioni09:41
I buy it 😜
vdeurzen10:30
That is a beast indeed #envious
vdeurzen14:20
The block subscription on testnet seems to stall from time to time, I've not received a new block even though there are 2 new since the last one I've received. Anything I can do about that?
4 replies · neillm, vdeurzen · last Mar 03, 2020
neillm19:47
Make sure it didn't time out?
neillm19:48
They do have to be renewed, and sometimes in less time than you think since the server can drop you with its timeout before your client's.
vdeurzen21:25
I mostly copied the zmq example for the block subscription service, is there a different way I should use it?
vdeurzen12:50
Also running the python client for the block service doesn't give any blocks 😕

Tuesday, March 3, 2020

vdeurzen14:36
Are the stored database formats between v3 and v4 compatible? I'm wondering if I can use an old back-up to get my node up-to-date a bit quicker
evoskuil14:53
No
vdeurzen15:02
thx
Any ideas for the zmq subscription? I essentially want to get blocks and transactions, as long as my node is still syncing
^ two different set-ups of course, but I would like to get some data in so I can get the rest of my services working while I wait for the sync to finish 🙂
evoskuil15:06
You should be able to query while syncing.
vdeurzen15:07
I'm looking to push the latest blocks and transactions into another service, don't really have a need for older blocks or transactions
evoskuil15:08
Does getting that working require recent blocks?
vdeurzen15:08
it's just a passive view on the latest events in the blockchain, I only care that I'm not sending invalid blocks or following a completely wrong chain
evoskuil15:09
Confirmed blocks are valid, and the syncing chain in v4 is based on a current strongest header chain.
vdeurzen15:09
My code is essentially start node subscribe_blocks(my_call_back) subscribe_transactoins(my_tx_callback) in my_call_back: if node->chain()->is_blocks_stale() { return true } same for tx's when it's no longer stale I start sending data to the rest of my services
i.e. I wrap a full_node and consume new blocks and transactions, which I then transform into my internal format and send to the next service
I hope I'm making sense 😛
evoskuil15:11
No reason for wait for recent blocks, the old ones are valid on the current strong chain.
(edited)
vdeurzen15:14
I'm not sure I follow your point? The goal of this service is to show the latest events that happened so that I can have another service track deposits. I.e I'm not interested what is on the strong chain unless I'm at the head of that chain.
evoskuil15:17
But you are coding right, all you need is test data. Just increase the staleness criteria in the config.
vdeurzen15:21
This would be for a production service, most of the coding is done, just need to get synced so I can start pushing events. So, it's not really test data that I need, I would like to get up and running on mainnet as soon as I can, but syncing in a container on a VM is slow (I accept that, this is the env I have to run on for now). So, I'm looking to figure out how I can either 1) sync faster (or smarter) or 2) get the latest block and transaction events from a different source (eg. ZMQ and connecting with the public nodes) while I wait for my slow sync to finish after which I will switch to my wrapped node solution
vdeurzen16:51
For the block_service (https://github.com/libbitcoin/libbitcoin-server/wiki/Block-Service) I find that after ~2 blocks the service just doesn't return anything anymore. @neillm you suggested I need to resubscribe, but the example only shows a 'subscriber' socket in zmq and an infinite loop, should I be doing something else ?
neillm17:26
Just try again, I restarted the mainnet node, don't have time to look at at the moment, but can later
^ I ran the python client and it worked
vdeurzen17:36
It worked for a bit, but stopped after 2 blocks last time 😅
But, just to confirm, following the code in the wiki / python example should work as is, just might have a node issue?
neillm17:37
The server times out the client in 10 minutes (due to my server config). The client would have to resubscribe to keep getting more after that
vdeurzen17:41
Ok, so an implementation using zmq should reconnect after ~5-10 minutes in order to keep receiving blocks? This did not seem required for transactions btw, they've been broadcast continuously since yesterday without any reconnect
neillm18:53
Sorry, I was incorrectly thinking of the client subscribe calls, which are totally separate from the broadcast subscriptions. Should be good as-is.
vdeurzen20:24
Ok, I'll try again then 🙂
vdeurzen20:34
So, for a bit of robustness, could I use a zmq poller and then after some time out (say 11 minutes) reconnect? Or does that not make any sense?
i.e. if I haven't received a block in >10 minutes I reconnect and start waiting again
neillm20:51
No need to resubscribe for these
vdeurzen21:04
I had the python example running since 620041, it's still waiting for block 620042 using mainnet1.libbitcoin.net:9093
neillm21:04
Use mainnet, which goes to mainnet2
mainnet1 more often has issues
vdeurzen21:05
Ok 👍
Ah, I go to update it and I was actually using mainnet2 already 😕
neillm21:06
Odd, will have to look at later
vdeurzen21:07
thank you
neillm21:36
5 blocks in the last 5 minutes on mainnet. Interesting (python client has been running for a bit now)
vdeurzen22:30
that seems quick 😅
vdeurzen22:43
Regarding a v4 full node, I'm still quite consistently running into some kind of loop / lock / deadlock when shutting down, which is making it very difficult to save a snapshot of the database. Anyone else seeing this?
vdeurzen22:50
From my gdb and printf debugging I'm seeing that p2p::close() is hanging, specifically it's stuck joining all threads in the threadpool, somewhere in there something is causing some kind of deadlock. I've seen this on my production nodes, my local dev nodes on my laptop and my desktop machine, it's quite reproducible, but hard to track down
19 replies · evoskuil, vdeurzen · last Mar 04, 2020
evoskuil09:18
That’s where I would expect it. It is hard to track down and I haven’t had a chance to do it yet. One of the reasons v4 is not released.
vdeurzen09:19
I had a similar issue in v3 before, might be a different one but the behaviour ended up being about the same
vdeurzen09:21
What I'm seeing after adding a bunch of debug logs is that p2p::close is being called more than once I also see there is a potential race between threadpool::shutdown, threadpool::join and threadpool::spawn_once. The shutdown method will reset work which can be re-initialized by spawn_once and could cause join to need to wait for more work to be finished.
evoskuil10:08
Close is idempotent, it gets called more than once.
evoskuil10:10
I don’t believe you will find any actual issue in the thread pool, but I can’t comment on specifics from my phone.
evoskuil10:10
If a thread is spawned it implies there is a close outstanding.
vdeurzen10:12
The race between shutdown and spawn_once is easy to argue I think, after shutdown before close, a spawn_once will re-initialize work. However, I don't know if reinitializing work is what is causing this
evoskuil10:17
If a thread is being initialized it has a close that is registered after the initialization.
vdeurzen11:04
You mean, this is taken care of by the fact that close is called multiple times?
evoskuil11:06
It is managed by requiring a close handler to be registered upon completion of any thread spawn call.
evoskuil11:07
Calling close while spawning would be an obvious bug.
vdeurzen11:07
Ok, the spawning thread is responsible for registering that thandler?
vdeurzen11:15
Ok, so all the thread-aware elements of p2p register their stop handler
evoskuil11:16
Yes
vdeurzen11:16
Ok, clear 👍
vdeurzen22:54
Experimenting with weird ideas I changed the full_node code to close the chain first then the p2p connections, this seems to at least reduce the probability of it hanging. My guess is, without my changes, that one of the p2p connections is waiting for the chain to do something, the chain is 'stopped' and not doing much and as a result everything just hangs
vdeurzen23:26
@neillm Even connected with all 4 public servers and using a poller to check if a block has been published, I'm seeing 2 blocks and then silence 😕

Wednesday, March 4, 2020

neillm01:06
Something sounds wrong. I started the python block subscription client earlier and it's still running without issue. Is there a way to test locally against your own server (generally always recommended if possible)
I saw you had some mainnet sync wait issues, but how about trying testnet in the meantime?
(edited)
vdeurzen09:15
I had the block subscription running through the night, multiplexing all 4 servers but it stopped receiving blocks after 2AM 😕 I honest don't know what's breaking it, maybe it's a networking issue that's causing my socket to be disconnected? At least the ZMQ interface from libbitcoin-protocol doesn't seem to tell me if that is the case
5 replies · neillm, vdeurzen · last Mar 04, 2020
neillm12:53
By chance are you using any kind of VPN or anything different about your connection? If a VPN reconnects, the script will continue to run, but no more data will come in due to the connection reset. Sounds a little bit like what you're seeing, but not sure.
vdeurzen12:54
This wouldn't have been the case this night as that was running on my home machine, but could be the case on production, which is guarded by a VPN
vdeurzen12:54
Would it make sense then to just periodically reconnect?
neillm12:56
That will help if this is the case, but you may lose a broadcasted message during reconnect.
vdeurzen12:57
Using the poller and several connections, I could reconnect them at different intervals so I spread that risk 🤔
👍 1
vdeurzen09:15
testnet would be nice for testing, but I'm trying get something, anything up and running for production while mainnet is still syncing
evoskuil09:21
Well if it’s deadlocking on shutdown it may simply be the deadlock. It doesn’t generally occur on shutdown, but the failure to close the locked thread prevents the shutdown.
vdeurzen09:22
Any ideas on how to track which thread that might be? I.e. any logging or tooling already in-place that I could enable ?
I had my mainnet sync running through the night and with ~240K blocks left download speed goes down to roughly 1 block per second, sometimes slower sometimes faster
evoskuil09:24
Blocks get three orders of magnitude bigger around that point.
vdeurzen09:24
ah, ouch
that explains it then
evoskuil09:25
Actually a little earlier, around 300k
But that still seems slow. I haven’t tested on machine with your specs. But if there’s a deadlocked thread it can cause delay.
vdeurzen09:27
Yeah, I'm guessing that wouldnt help indeed
evoskuil09:27
I debug into the deadlock upon close in Visual Studio, observing the call stack of each thread. At least one will stand out.
There is really only one possible source of deadlocks in Libbitcoin, despite heavy use of critical sections. Only one has the possibility of reentering a critical section. There is a huge warning around it. But still, very hard to track.
vdeurzen09:32
Which one? I have a pretty good reproduction path so I can try and track it, see if I can contribute back a bit 👍
evoskuil09:33
That would be awesome. It’s in a libbitcoin-system class, used in subscriptions, where handlers are injected into the subscriber instance. Handlers are arbitrary code and execute under the subscriber lock. They cannot be allowed to renter the subscriber.
(edited)
vdeurzen09:35
Ok, will dig into that while I switch to v3 and try syncing mainnet again 🙂
evoskuil09:35
Thx!!
vdeurzen09:36
ah, because that would try to recursively lock the unique_lock?
evoskuil09:36
There are several subscriber instances, in network, node and server.
Maybe, or enter once. But our locks are intentionally not reentrant, so it will block on any such attempt.
All other critical sections can be visually verified as not reentrant.
vdeurzen09:38
I'll try to find out if any subscriber gets stuck here.
evoskuil09:39
Maybe run node only (no server). Maybe you can isolate it to server or not.
vdeurzen09:39
I've only had it happen in node so far
evoskuil09:39
Ok, well then it will happen in server eventually.
(edited)
I had this in v3 as well, tracked it down and no problems since.
Thanks for the help.
vdeurzen09:42
Happy to help. Thank you for the help explaining things 🙂
evoskuil09:42
No prob.
evoskuil10:08
replied to a thread: view
Close is idempotent, it gets called more than once.
vdeurzen10:09
Read something in the boost docs that suggested it might be an issue, but it's quite likely that was in fact talking about contexts or services
evoskuil10:10
replied to a thread: view
I don’t believe you will find any actual issue in the thread pool, but I can’t comment on specifics from my phone.
evoskuil10:10
replied to a thread: view
If a thread is spawned it implies there is a close outstanding.
fpelliccioni10:16
I made a python script that launchs and stops libbitcoin several times. I was able to probe that deadlock exist. I think I shared to Eric and Neil, about 2 years ago,...
evoskuil10:16
Yes, that helped isolate at least one of the deadlocks in v3.
fpelliccioni10:17
I don't remember where that script is. I can write it again
evoskuil10:17
replied to a thread: view
If a thread is being initialized it has a close that is registered after the initialization.
evoskuil11:06
replied to a thread: view
It is managed by requiring a close handler to be registered upon completion of any thread spawn call.

Wednesday, March 25, 2020

vdeurzen17:05
I just ran into something on my environment and I'm wondering if there is anyway of dealing with it configuration wise: Apparently (and shockinly) our environment (google cloud) doesn't allow us to connect to ipv6 addresses, but my host pool contains a whole bunch of them and this stalls the node as it's essentially going from peer to peer getting and failing to resolve them. Anything I can do here? Can I configure something to force only ipv4 addresses to be added to the host pool?

Thursday, March 26, 2020

neillm01:40
You should be able to configure ipv4 only on your system, outside of libbitcoin
neillm01:56
For example: http://terokarvinen.com/2016/prefer-ipv4-on-ubuntu-16-04-lts-xenial-etcgai-conf-precedence-ffff0096-100 (summary is to prefer ipv4 to ipv6, rather than the other way around: uncomment line "precedence ::ffff:0:0/96  100" in /etc/gai.conf, if applicable to your system). I've done that on the community servers and haven't seen any issues btw.
vdeurzen08:41
@neillm Thx, I'll give that a try

Tuesday, March 31, 2020

naezith16:05
hello
./install.sh --prefix=/home/me/myprefix --build-boost --disable-shared
I was able to build that code when I installed it like this
then I deleted that installation and reinstalled like this: ./install.sh --with-icu --build-icu --build-boost --disable-shared
now it fails like this
image.png
@here it's kinda urgent, can you check if it's a really basic thing?
neillm16:11
Odd. Try to also link -ldl
naezith16:12
my bad I showed the one without that @neillm, same result including that
it's already in pkg-config
neillm16:12
version3 or master?
neillm16:14
Add -ldl as the first listed lib, before boost
Other than that, not sure, but the order does matter
naezith16:15
image.png
neillm16:17
Something seems odd though, perhaps some environmental mismatch. -ldl shouldn't be needed on the static build actually
evoskuil16:17
So libbitcoin and tests build, just not the example code?
naezith16:17
it's that example code
neillm16:17
Add -static to the pkg-config line
N
narodnik16:18
The default config file from libbitcoin server needs to be updated (minor change): /subsidy_interval_blocks/subsidy_interval/
naezith16:19
it worked with static! @neillm
👍 1
what's my issue
evoskuil16:19
@narodnik PR?
naezith16:28
interesting --static added -lpthread -ldl -lm while -lpthread -ldl were already there it gives the same error if I remove that second -lpthread -ldl part but still keep -lm
can you explain how this works so I can at least learn instead of just being ok that it works 😄 @neillm
g++ -std=c++11 -o addresses_hd_wallets main.cpp -DWITH_ICU -I/usr/local/include -L/usr/local/lib -lbitcoin -lboost_chrono -lboost_date_time -lboost_filesystem -lboost_iostreams -lboost_locale -lboost_log -lboost_program_options -lboost_regex -lboost_system -lboost_thread -lpthread -lrt -ldl -licui18n -licuuc -licudata -lpthread -ldl -lm -lsecp256k1
this is the working line
notice that -lpthread -ldl is duplicate
neillm16:29
It's just telling pkg-config to use the static options
naezith16:30
output difference is those -lpthread -ldl -lm
but two of them are already there
neillm16:30
@pmienk may have more detail
naezith16:30
and removing those two breaks it again (keeping only -lm)
my problem is already solved though, thank you
I just wanna learn how this works
evoskuil16:44
Thx!