These control the number of jobs that may be enqueued before error, and
the number of concurrent threads to process jobs, respectively.
Also renamed 'misc' subdir to 'doc'
Also added some /stats: show all the configured global Options as they
came in from conf file/CLI. ("Config" subdict in /stats JSON).
The DoS protection added is against unlikely and hard-to-pull-off memory
exhaustion attacks whereby clients fill our receive buffers with data
without sending newlines. If we detect our receive buffer (default 4MB
buffer size) is starting to fill, we time clients out quickly if no
newline arrives within 5 seconds.
Per-IP connection limit defaults to 12, but is configurable from the
config file.
Also added exlusion sets for subnets for this (and any future per-IP
limits).
By default localhost-originating connections are excluded.
Also in this commit:
- Replaced some usages of QMap with QHash for data items where order is
not important -- QHash is faster.
- Made the global 'id' type from IdMixin be IdMixin::Id (type alias for
quint4). This way code using this data item is cleared/easier to read
and more explicit in what it's doing.
Config variables added:
- hostname
- public_tcp_port
- public_ssl_port
These are used by server.features. They will also go towards the peer
discovery/peering subsystem when that is implemented.
Also added a mechanism to query peer port, peer address, etc from
AbstractConnection instances.
Added genesisHash() public thread-safe function to Storage.
Also in this commit various nits and subtle bugs prevented.
Refactored the 'Stats' mechanism to return a generic QVariant rather
than QVariantMap, which is more flexible.
Misc. other nits.
Set maxcur to 16, spinning up 3 bitcoind threads.
Seems to have brought header synch down from 170s to 71s on my mainnet
node here locally. Not bad!
Also fixed a bug where selecting bitcoind nodes was failing if >2 nodes.
Finally, after 20 years, I figured out how to do this. Diamond-patter
multiple inheritence is tricky. Downcasting from a Base to a Derived
must be unambiguous, for one (thus you need virtual when inheriting the
base).
Secondly -- it must all be public all the way down to the concrete
class!
This is subtle. I suppose the Base cannot see the Derived class
inherits it per C++ rules if not publicly inherited. TIL.
https://en.cppreference.com/w/cpp/language/dynamic_cast#Explanation
Also wrote a virtual methd 'getStats()' for AbstractConnection which
puts some basic stats into a QVariantMap for the /stats endpoint.
Subclasses can call the base implementation and add their own stats to
the returned map.
Also in this commit: misc refactoring and nits
Basically it's not called on app exit. We made it so it's not so crucial
it be called for cleanup.
Also added some preliminary stats to the http /stats endpoint for the
BitcoinD instances.
This is to prevent memory exhaustion attacks from peers and enforce the
MAX_BUFFER we already defined for the clss.
Also added the EXPECT macro for clang's __builtin_expect for some branch
prediction to make some unlikely checks we make not be terribly costly
on the processor.
It works! I still haven't figured out how to provoke the dreaded
"Workdepth exceeded" error .. but we pretty much drop the connection
anyway on anything too unexpected from bitcoind.
When the bitcoind manager class is written it will back off and try
again if too many disconnects happen.
For now though, the code we have is fast and works well against
bitcoind.
Now we can re-use the RPC method<->result code in the TcpServer side
which will face wallets. Phew! Took me long enough!
It's a minimal JSON-RPC protocol impl.. but it'll do.
The 1 nice bit is the Schema spec I came up with which more-or-less
works well enough as a first-pass validatior.
Further passes are needed in interested client code, but the initial
pass validation can be done in a thread so as to not waste the main
thread's time validating json or dict key presence/absense. Yay.