Bitcoin full node and query server

May 2021

Archive of the libbitcoin Slack #general channel.

Saturday, May 1, 2021

N
narodnik11:49
Was designing libbitcoin to use ZMQ for the blockchain API a mistake? Was it better to go with JSON since it's easier for frontend devs and less maintenance work? Originally the ZMQ choice was to reduce latency and optimize for performance.

Sunday, May 2, 2021

evoskuil22:54
No, it provides a robust internal and external framework. Not just in terms of ease and latency, but for managing high scale and/or distributed service. We've layered a light json interface over it for compat, but the http overhead is non-trivial and you lose the other benefits (though the underlying DoS management is preserved).
(edited)
👍 2👍🏾 1
It can be used in-process (which we do), oop, on a local or remote network with any transport protocol, and securely.
The http layer that @neillm built provides a simple integrated block explorer as a proof of concept direct from a configurable server port. He's adapted it to support json-rpc. The htpp implementation is our own, initially for licensing and bugginess issues with other options. But I'm planning to rebuild it on top of our boost asio (p2p network) stack, which will eliminate a lot of the code.
(edited)
👍 2👍🏾 1
Building an electrum client interface (for example) is as simple (using pyzmq) as an http/json interface, with no need for libbitcoin code.
IMO it was one of your several great architectural decisions in libbitcoin.
👍 2👍🏾 1

Monday, May 3, 2021

N
narodnik10:46
Thanks a lot!
evoskuil10:46
👍
N
narodnik10:46
@neillm did you receive my signal messages?
👍 1
invited you to the friday meeting, @evoskuil is also there.
@evoskuil also invite any of your collaborators. I think we're in a key time with Bitcoin, and it's kind of strategic to get more resources and focus put into our ecosystem
evoskuil10:48
bump @pmienk

Tuesday, May 4, 2021

P
Phil21:12
replied to a thread: view
Please give me detail cues as to which exact lines to comment out
P
Phil21:14
I understand what you are hinting at, the Node will trig the logic to get the whole block. What we will do is simply to disable the request for whole blocks. Also when a whole block is pushed from a peer, we ignore it. Also when any transaction is pushed from a peer, we ignore that too. Are those in total the three points needed to degrade to SPV?
evoskuil21:14
If you don't want blocks or transactions you shouldn't bother with libbitcoin-node. All you need is libbitcoin-network.
These are the lines that attach protocols:
void session_outbound::attach_protocols(channel::ptr channel)
{
    const auto version = channel->negotiated_version();

    if (version >= version::level::bip31)
        attach<protocol_ping_60001>(channel)->start();
    else
        attach<protocol_ping_31402>(channel)->start();

    if (version >= version::level::bip61)
        attach<protocol_reject_70002>(channel)->start();

    if (version >= version::level::headers)
        attach<protocol_header_in>(channel, chain_)->start();

    attach<protocol_block_in>(channel, chain_)->start();
    attach<protocol_transaction_in>(channel, chain_)->start();
    attach<protocol_transaction_out>(channel, chain_)->start();
    attach<protocol_address_31402>(channel)->start();

    using serve = system::message::version::service;
    const auto services = settings_.services;

    if ((services & serve::node_compact_filters) == serve::node_compact_filters)
        attach<protocol_compact_filter_out>(channel, chain_)->start();
}
These exist in each of the three session types.
There is no SPV mode in libbitcoin.

Wednesday, May 5, 2021

P
Phil13:11
But, I do want persistence for the block header downloads. That persistence is in libbitcoin-node, though? I.e. we need that = more than solely libbitcoin-network

Thursday, May 6, 2021

P
Phil12:18
Dear Eric, I am looking into the symmetry of accessing the persistence (safe_chain class), symmetrically between offline mode and online mode. I’m totally clear that I can access the chain ‘live’ from full_node.chain(). How should I access the persistence as a safe_chain instance, when I am not intending to go online? (My guesses: Either I can somehow start a full_node, but without running full_node.start() or full_node.run(), this way somehow getting the full_node.chain() but without starting any peer to peer work, OR i should separately create some kind of libbitcoin-database instance for this...) And then second question, how do I switch between that online and offline mode?
evoskuil14:58
Once you start accepting data from the network (or APIs) asynchronously you the synchronous database calls are unsafe. They are meant for startup and calls from within the asynchronous calls.
You can use libbitcoin-node and libbitcoin-store to build your own node by following the libbitcoin-node pattern, or you can derive from libbitcoin-node and attempt to just use the header sync.
3 replies · Phil, evoskuil · last May 11, 2021
P
Phil12:44
(Followup on above:) Which are the synchronous database calls? What is the failure mode of read operations to those - inconsistent view, or SIGSEGV?
evoskuil18:46
The ones with callbacks.
evoskuil18:48
If the store terminates without clearing the flush lock file, the store files are corrupt. That’s the purpose of the flush lock, to detect store corruption and prevent use of a corrupt store, which would be undefined behavior.
(edited)

Sunday, May 9, 2021

evoskuil03:39
I found BIP173 so poorly written I had to write this up. https://github.com/libbitcoin/libbitcoin-system/wiki/BIP173-For-Humans
👍 1

Monday, May 10, 2021

I have a newbie question related to Bitcoin Explorer. From what I understand, bx ec-new only accepts base16 entropy with at least 128 bits. I'm passing 1ffffffffffffffffffffffffffffffff hex which technically has 129 bits and yet bx ec-new complains that the argument is invalid. What am I missing? (I understand that we should be using bx seed but I'm just testing some features)
12 replies · neillm, Jay, evoskuil · last May 18, 2021
neillm11:39
It's not valid hex (for parsing). You could do something like this: bx ec-new 01ffffffffffffffffffffffffffffffff
(edited)
@neillm Thank you.
👍 1
evoskuil18:54
I suppose it could be considered valid, but libbitcoin always requires 2 hex digits per byte - no assumed padding.
👍 1
evoskuil18:55
Actually you should only use bx seed for testing, not for generating actual secrets.
Thanks @evoskuil When I meant testing, I was trying to test the entropy limits for bx ec-new and trying to understand the libbitcoin library. I haven't done any C++ coding in over 10 years. So, basically reading code and also testing things at terminal to learn about features and extend this for my application. If it's not too much, another quick question. I tried to generate pub addresses by passing two hexes, technically with same entropy but different strings. As in 00000000000000000000000000000000ffffffffffffffffffffffffffffffff and ffffffffffffffffffffffffffffffff. Their decimal values are one and the same but the resulting addresses are completely different. What might be happening in the background?
(edited)
evoskuil02:37
Zeros are part of the value, it’s not a “number” it’s a byte buffer. The zeroes get hashed in one case and not the other. The entropy is not the same, as the domain is different.
evoskuil02:40
Every bit can be one or zero, but if you reduce the domain there are fewer bits and therefore less entropy. A 132 bit buffer has 132 bits of entropy as entropy is not just the 1 bits. If you reduce the domain then it reduces the strength of the seed, even if the actual value was just 1. 1 out of 2^1 is 50%, 1 out of 2^132 is much smaller.
(edited)
evoskuil02:42
So bx is accepting from you both the numeric value and the domain.
evoskuil02:45
I won’t use any system that only accepts a numeric value, or requires it to be above a certain numeric value. That simply reduces the actual entropy, as the attacker does not need to search below that value. I’ve seen such implementations in bitcoin, such as a reduction from 132 bits to 121 bits by requiring a min value simply because the internals treat the entropy as a number instead of a byte buffer.
(edited)
Thank you for taking the time. Much appreciated
evoskuil08:42
👍
evoskuil08:43
Happy coding!

Tuesday, May 11, 2021

P
Phil11:28
@evoskuil Just curious, during full_node.chain().get_transaction() and .get_block() , is it ever the case that the async callback would be invoked *in the OS thread that this call is made*, i.e. **BEFORE** get_transaction/block() returns - Or instead, is the callback always run in one of LB’s worker threads? I was thinking that the optimal speed case would be dispatching the async callback within the self same OS thread as the get_transaction/block() call is made - e.g. in the situations where that transaction or block is already cached - here no work by LibBitcoin worker threads would be needed. This would be the highest possible logical speed possible. When work is passed from the calling thread to another OS thread, there is a tiny tiny bit of latency for the worker thread to wake up and the memory to move from core to core. Mostly unnoticeable though I guess if you make a billion tx/block requests in a *sequence*, that latency would add up. Anyhow this was mostly performance trivia. By the way separately, where in the code do I find how many worker threads full_node* actuall runs? My thought is, an SSD tends to have is it 32+ queue depth. When the memory mapping accesses the disk, the OS thread blocks. For this reason a full_node for maximum performace, I presume, should have at least 32 OS threads?
8 replies · evoskuil, Phil · last May 14, 2021
evoskuil18:57
Calls may return on any thread in the threadpool. Callbacks are queued and then dispatched as threads become available. Operation the node can operate on a single thread. It’s not clear what you distinction you intend by “OS thread”. All threads, with the exception of the single process thread, are logical objects created by the threadpool class. They may or may not correspond to distinct operating system threads of execution.
evoskuil19:05
This qualifies as premature optimization. Until you identify a problem, there is no problem to solve. Increasing the amount of work on a single thread reduces the availability of threads for other work. Load balancing is a performance consideration. Individual calls would certainly be more performant if executed synchronously, as you are essentially suggesting. However this simply blocks other calls, with a subsequent impact on latency of all calls. A trade off is made with consideration of the thread switching cost against the size of the work. Larger jobs are broken up into smaller jobs, and small jobs are aggregated into larger jobs. The optimal size of any job can only be determined by performance testing. Until you have measured this difference an informed decision on which trade off to make is not possible. Therefore, premature optimization.
evoskuil19:07
The number of logical threads in the node/network threadpool, the validation threadpool, and the query server threadpool, is exposed in the configuration file. You can trace this back to where they are created and used within the source.
evoskuil19:11
The optimal number of threads for any pool varies. I have found that on my 32 dual core (64) machines, 32 is more optimal than 64 for the validation threadpool. At some point the cost of fanning out the parallel jobs exceeds the benefit of parallelism. For this reason the node limits the number of threads configured to the number that are reported by the operating system, but that’s fairly arbitrary and more of a safeguard against gross misconfiguration.
(edited)
evoskuil19:19
Libbitcoin is both highly asynchrous and parallel. Many individual std library calls are parallelizable by the compiler, and expensive validation steps (such as script execution) are explicitly parallelized by the implementation. This is also why std lib calls are used when possible vs. for loops. Imposing order where it is not a logical requirement is an antipattern. The same holds for reducing asynchrony to increase individual call performance. This reduces the effectiveness of parallelization.
evoskuil19:21
Generally speaking the approach is to never impose order when it is not required. At that point performance tuning can optimize tradeoffs, but only through performance testing.
evoskuil19:28
I found at least one case where Satoshi imposed order in consensus evaluation. He requires transactions in a block to be ordered such that outputs that are spent by other txs in the block precede those other transactions. There is no reason for this except that he used a naïve implementation which queues outputs and verifies inputs against the outputs queue as it’s being built. So I retained our parallel implementation and added and explicit and otherwise entirely unnecessary rule called is-forward-reference. https://github.com/libbitcoin/libbitcoin-system/blob/master/src/chain/block.cpp#L821
(edited)
P
Phil13:55
The optimal number of threads for any pool varies. I have found that on my 32 dual core (64) machines, 32 is more optimal than 64 for the validation threadpool. At some point the cost of fanning out the parallel jobs exceeds the benefit of parallelism. For this reason the node limits the number of threads configured to the number that are reported by the operating system, but that’s fairly arbitrary and more of a safeguard against gross misconfiguration.
You mean for safety, LibBitcoin’s thread pool will be the number of CPU cores that the OS reports that the machine has? Safety as in don’t presume users will bother to set such a setting
P
Phil12:44
replied to a thread: view
(Followup on above:) Which are the synchronous database calls? What is the failure mode of read operations to those - inconsistent view, or SIGSEGV?
P
Phil12:45
If my OS process is starting just now, and want to do blockchain explorer queries to the persistence built up by LibBitcoin Node in the past - alternatively my OS process has run a full_node, but it’s offline now thanks to that I did full_node.stop() (?+ .close() i presume?), then how do I do that now? Shall I somehow run a full_node* but not, uh, run .start() on it, this way it will give me blockchain explorer queries but not do networking?
Or should I make use of some other class/LibBitcoin package altogether, e.g. LibBitcoinDatabase db = new LibBitcoinDatabase(“.\blockchain\“); which then gives me a safe_chain - where do I get the safe_chain from that I’ll make my queries too =) (Maybe a “blocks.” - i.e. of type blocks_database - is needed too for learning what’s the head block etc)
(edited)
evoskuil18:48
replied to a thread: view
If the store terminates without clearing the flush lock file, the store files are corrupt. That’s the purpose of the flush lock, to detect store corruption and prevent use of a corrupt store, which would be undefined behavior.
(edited)
evoskuil18:57
replied to a thread: view
Calls may return on any thread in the threadpool. Callbacks are queued and then dispatched as threads become available. Operation the node can operate on a single thread. It’s not clear what you distinction you intend by “OS thread”. All threads, with the exception of the single process thread, are logical objects created by the threadpool class. They may or may not correspond to distinct operating system threads of execution.
evoskuil19:05
replied to a thread: view
This qualifies as premature optimization. Until you identify a problem, there is no problem to solve. Increasing the amount of work on a single thread reduces the availability of threads for other work. Load balancing is a performance consideration. Individual calls would certainly be more performant if executed synchronously, as you are essentially suggesting. However this simply blocks other calls, with a subsequent impact on latency of all calls. A trade off is made with consideration of the thread switching cost against the size of the work. Larger jobs are broken up into smaller jobs, and small jobs are aggregated into larger jobs. The optimal size of any job can only be determined by performance testing. Until you have measured this difference an informed decision on which trade off to make is not possible. Therefore, premature optimization.
evoskuil19:07
replied to a thread: view
The number of logical threads in the node/network threadpool, the validation threadpool, and the query server threadpool, is exposed in the configuration file. You can trace this back to where they are created and used within the source.
evoskuil19:11
replied to a thread: view
The optimal number of threads for any pool varies. I have found that on my 32 dual core (64) machines, 32 is more optimal than 64 for the validation threadpool. At some point the cost of fanning out the parallel jobs exceeds the benefit of parallelism. For this reason the node limits the number of threads configured to the number that are reported by the operating system, but that’s fairly arbitrary and more of a safeguard against gross misconfiguration.
(edited)
evoskuil19:21
replied to a thread: view
Generally speaking the approach is to never impose order when it is not required. At that point performance tuning can optimize tradeoffs, but only through performance testing.
evoskuil19:28
replied to a thread: view
I found at least one case where Satoshi imposed order in consensus evaluation. He requires transactions in a block to be ordered such that outputs that are spent by other txs in the block precede those other transactions. There is no reason for this except that he used a naïve implementation which queues outputs and verifies inputs against the outputs queue as it’s being built. So I retained our parallel implementation and added and explicit and otherwise entirely unnecessary rule called is-forward-reference. https://github.com/libbitcoin/libbitcoin-system/blob/master/src/chain/block.cpp#L821
(edited)

Wednesday, May 12, 2021

Revive16:42
hey guys, looking at using cxx https://cxx.rs an rust tool to generate bindings for libbitcoin
(edited)
CXX
CXX — safe interop between Rust and C++
18 replies · evoskuil, Revive · last Jun 21, 2021
evoskuil18:28
Hopefully it’s more capable than swig.
Revive18:40
I'm working through how to use it properly. it has excellent feedback. can do c++ -> rust and rust -> c++. Declared structs, fn types etc are kept on the rust-side of things, so just by including the libbitcoin headers. I am still sorting out the best way to do things however
evoskuil18:58
Is it fully generated, and can it handle things that swig cannot, like templates.
Revive15:54
Sorry for the late reply. Just got something working yesterday lol
Revive15:55
I'm not sure what you mean by fully generated, but you have to declare (signatures they call them in rust) with matching functions, structs, etc. IE it doesnt run though the entirety of your library.
Revive15:57
They can be Opaque (pointers only), shared structs both C++ and rust have access to, and functions.
Revive15:58
so far I know that it has problems reading aliases from C++. I would like to find out if it translates templates well now. can you give me an example simple template fn?
Revive16:01
right now i'm building using cargo, and only including libbitcoin headers, and the dynamically linked libraries. but that was enough to get pseudo_random used within rust
👍 1
evoskuil10:32
How is it "generated" bindings if you have to declare them manually?
evoskuil10:33
Manual binding generation has been attempted several times. It's extremely hard to keep them in sync, and they become unreliable and unused as a result.
Revive17:38
You declare a high-level description of the language boundaries eg in "extern c++" or "extern rust" within the rust, then CXX uses static analysis of the types and function signatures to protect both Rust's and C++'s invariants. Then it "uses a pair of code generators to implement the boundary efficiently on both sides together with any necessary static assertions for later in the build process to verify correctness." As far as I have seen. python-libbitcoin and libbitcoin-c had to both be maintained as you pointed out. At least this way, the low-level FFI in C can be automated
Revive17:40
but this is for my current use case. I want to use libbitcoin within rust. I defer to you for exactly these opinions is something long-term is viable in libbitcoin itself
evoskuil04:18
Actually sounds pretty good, can you point me to your implementation?
Revive15:02
@evoskuil an update to this. been evaluating cxx and autocxx, which is a higher level generator for cxx that makes use of bindgen to generate the C++ bindings side automatically. CXX, by itself, needs definitions of boundaries and similar types in both the rust side and C++ etc as described above. For example, on the C++ side I created std::unique_ptr for libbitcoin::system::wallet::hd_private https://github.com/darkrenaissance/darkfi/blob/libbitcoin-gen/gen/libbitcoin/src/helpers.hpp#L8
Revive15:03
Here's what the implementation looks like for creating a new seed in rust, using libbitcoin + autocxx: https://github.com/darkrenaissance/darkfi/blob/libbitcoin-gen/gen/libbitcoin/src/main.rs#L43
Revive15:05
the autocxx magic is line 14-16 with the macro generate!("libbitcoin::system::pseudo_random_fill")
Revive15:26
that file generates bindings that looks like this: what autocxx generates (uses cxx library for you) - https://paste.dark.fi/~janus/c2d5a52cc52d96cd43b98d6c6b5539461dcd80bf#rust-autocxxgen-demo-L64 what cxx generates from this - https://paste.dark.fi/~janus/cda4b2ad0a99c701726bac3fdc5fb2e7ac2d936a#cxx-gen-L84 autocxx + bindgen generated c++ side https://paste.dark.fi/~janus/ad72b45c573cf9b27cd6d04fd718789cc4837dd9
(edited)

Thursday, May 13, 2021

evan17:51
Libbitcoin is in outer space
Image from iOS
🙂 2🤣 1

Friday, May 14, 2021

N
narodnik06:10
That's excellent
@evoskuil there is so much weird cruft and validation stuff in Bitcoin, I don't even know where to begin. When people start calling satoshi a great programmer, I'm shaking my head. Obv worked very hard and smart guy, not def not a software developer.
(edited)
Still weirder that they haven't managed to refactor the code after so many years. It's just kinda solidified and become more unwieldy.
evoskuil06:42
Yup, it’s a house of cards. That’s one of the several reasons it can’t change much at all. I still have a large amount to do on our code, but it’s really fun to work in.
Eventually we’ll be able to pass them up. They are calcified and we are accelerating.
P
Phil13:55
replied to a thread: view
The optimal number of threads for any pool varies. I have found that on my 32 dual core (64) machines, 32 is more optimal than 64 for the validation threadpool. At some point the cost of fanning out the parallel jobs exceeds the benefit of parallelism. For this reason the node limits the number of threads configured to the number that are reported by the operating system, but that’s fairly arbitrary and more of a safeguard against gross misconfiguration.
You mean for safety, LibBitcoin’s thread pool will be the number of CPU cores that the OS reports that the machine has? Safety as in don’t presume users will bother to set such a setting
evoskuil14:30
Not safety. Any number of threads is safe.
It was based on performance testing.

Monday, May 17, 2021

P
Phil15:31
@evoskuil I’m not being able to find the definition of header_const_ptr_list_const_ptr using grep. I can only find usage of it. Where/how is it defined?
(edited)
4 replies · jungly, Phil, evoskuil · last May 17, 2021
jungly15:58
In /libbitcoin-system/include/bitcoin/system/message/messages.hpp There's all these DECLARE_MESSAGE_POINTER_TYPE macros.
🙌 1
P
Phil16:52
Awesome! Thank you!
evoskuil18:28
This is why I use an IDE :).
💥 1
evoskuil18:29
Right click, go to definition/declaration. It’s 2021 :)
🤣 1
P
Phil17:57
When I subscribe to header reorganizations, get branch/height, does LB have a guarantee that as long as you have **not returned** the reorg callback, that during that time frame, it wil *NOT* make another reorg callback for a reorg that happened AFTER that reorg ??
evoskuil18:28
No, if that was the case your handling of that callback would block the entire node.
P
Phil19:19
Are there any synchronicity guarantees? Or otherwise some way for me as api user to index the reorgs so i can sort and process them in a sequence?
evoskuil19:31
The guarantee is that it is asynchronous and that callbacks are invoked in the order that events happen. You have to write asynchronous code to use it. You could of course run it on one thread, and it will still be asynchronous, but given only one thread it would not be parallel. You could also just block every callback thread and starve the network pool (to the same effect). But these are poor choices. If you require order you impose it using critical sections of your own.
For example, your handler can block on a mutex until it's complete. That will cause it to process callbacks in order. Just be careful, this type of programming requires a pretty good understanding of parallelism. Code under mutex must have a no-reentrance guarantee or you will most likely deadlock yourself. It's very hard to provide that guarantee except for noting visually that there is a direct path through the critical section.
You can see this pattern in place in the libbitcoin network/server/node code. Critical sections are offset by obvious comment sections, and all but one provide this visual guarantee. The one that doesn't (in bc::system) is the source of deadlocks that we sometimes experience. I'll be resolving that shortly.
(edited)
P
Phil20:22
full_node has a block_chain typed object and when I call node->chain() it returns a safe_chain& typed object. Is it safe for me to typecast the outcome of node->chain() back to block_chain? I wanna poll for what’s the head block’s hash & height, which I cannot get with a `safe_chain` typed object. These are available on `block_chain` only:
    /// Get highest confirmed or candidate header.
    bool get_top(system::chain::header& out_header, size_t& out_height,
        bool candidate) const;

    /// Get highest confirmed or candidate checkpoint.
    bool get_top(system::config::checkpoint& out_checkpoint,
        bool candidate) const;

    /// Get height of highest confirmed or candidate header.
    bool get_top_height(size_t& out_height, bool candidate) const; 
pmienk20:36
might want to consider polling fetch_last_height
it and fetch_block_header accomplish what you want without trying to bypass the abstraction provided. Alternatively you're implementing a server and should derive to get access.
(edited)
👍 1
evoskuil20:45
If a cast was possible it wouldn’t be necessary. The reason you get a safe_chain is because block_chain is unsafe and cannot be used except at startup or under internal locks.
block_chain queries are used internally by safe_chain under lock. You must adhere to the asynchronous programming paradigm. Most of your questions seem to imply you are trying to avoid this. That’s not a good approach.
P
Phil20:49
oh I see. So I’ll just use what @pmienk suggested. Thank you both for answering!
👍 1
pmienk20:50
just as long as it isn't the derivation approach, that requires you to adhere to the same paradigm or seriously shoot yourself in the foot
P
Phil21:02
The reorg listener, does it invoke the callback ONCE at startup?? Thus functioning as a poll/‘fetch’ operation (I.e. in addition to trigging when an actual reorg happened thanks to network input, subsequently) I am trying to figure how to poll my full_node. for what height it is at
evoskuil21:10
Nodes aren’t query servers. If you want general purpose query you should build on server.
Otherwise you use the safe_chain interface to effectively build your own server. That’s how server is implemented on top of node.
Nothing happens once except for start methods (stops are idempotent and get invoked more than once).
evoskuil21:20
The reorg callback is fired when a reorg happens. If you have derived from or contained node you have access to safe_chain as a property of node, so you can access any chain state. However, all calls are asynchronous. A reorg may happen while you are fetching height, at which point height may have changed by the time your fetch call returns. So you would only want to initialize height before starting node.
This is how blockchain tracks node height internally. Init before start and maintain by reorg handler
evoskuil21:32
It is possible that you could get two reorgs very close together, and end up completing the processing of the first one sent after competing processing of the second. This should be considered normal behavior and would simply appear like a reorg in the other direction. It’s even possible that the tracked chain could get shorter under this circumstance, and that a block you believe to be confirmed is actually unconfirmed. this would be resolved by the next reorg and is normal behavior, despite being rare. Race conditions are the nature of asynchronous programming.
While the reorg events are sent in order, the node does not wait on each callback to process them. All of your questions regarding ordering guarantees are a little bit concerning, as it implies you may be creating dependencies on order, where it is not guaranteed.
Even critical sections within your own handlers cannot impose this order, since it is still a race to get to the lock. The operating system may preempt the first thread and not the second, causing the second to arrive at the lock first.
(edited)
Ordering is the death of parallelism. In order to write performant concurrent code it must be asynchronous and avoid unnecessary ordering constraints.

Tuesday, May 18, 2021

evoskuil02:40
replied to a thread: view
Every bit can be one or zero, but if you reduce the domain there are fewer bits and therefore less entropy. A 132 bit buffer has 132 bits of entropy as entropy is not just the 1 bits. If you reduce the domain then it reduces the strength of the seed, even if the actual value was just 1. 1 out of 2^1 is 50%, 1 out of 2^132 is much smaller.
(edited)
evoskuil02:42
replied to a thread: view
So bx is accepting from you both the numeric value and the domain.

Monday, May 31, 2021

P
Phil17:36
Dear Eric, here is GDB’s backtrace of all threads of a full_node that I have running on OpenBSD, embedded in my custom process - really just running a full_node, very basic, like LibBitcoin’s “bn”. After running for a long time, the reception of blocks suddenly stops. According to the log this is the last block it received: https://0bin.net/paste/Syl1pi1m#H5XeVZh6aCTk4CWevFO28L6Y9WDVYbbIP419dGfA-df On Linux curiously the exact same program works. So weird. As you see, threads 15 and 16 are doing an operation at 0xda33452f878 , some kind of contention i guess. And, threads 17 and 14 are doing a mutex op on 0xda2a38a0a50. I presume this is a locking related bug, that for some magic reason only appears in this particular environment, i have no idea why =))) What do you think of the issue?
0bin.net
0bin is a client-side-encrypted alternative pastebin. You can store code/text/images online for a set period of time and share with the world. Featuring burn after reading, history, clipboard.
evoskuil17:38
Version?
P
Phil17:42
This error is reproducible, it kicks in after about 9 minutes. The reproducibility is 100%, it happens every single time in openbsd
evoskuil17:46
Didn’t we discuss this? V4, not production, known issue.
P
Phil17:50
hm ok. What is the timeline for V4 to be useful?
So the V4 bug only appears on OpenBSD. Next handful months I can be based totally in Linux as the bug did not surface there. Should I?
evoskuil18:42
It will appear on any platform. The implementation of the node/server is incomplete
P
Phil19:07
I see. bn seems to work fine, though. This issue is not present on bn. Do you know when bn is expected to be solid?
evoskuil19:09
Believe me, it’s present
No timeline, but I’m working toward it.
I've been studying this class of crypto algorithms. The most basic oblivious transfer (OT), allows the sender S to have 2 secrets x_0, and x_1 and the receiver R has a selection bit b, which depending whether b is 0 or 1 will select x_0 or x_1 without S knowing which one was retrieved by R
Has applications to private wallets
"A CPIR (Computationally Private Information Retrieval) protocol is similar to a PIR protocol: the receiver retrieves an element chosen by him from sender's database, so that the sender obtains no knowledge about which element was transferred"