Skip to content

Conversation

jordanlewis
Copy link
Contributor

This patch set updates bitcoin's RPC server to use boost::asio's async_read, _write, etc instead of their non-asynchronous versions.

The server still exists as a single separate thread, but the async calls should greatly improve performance under high load. The next step in robustifying the RPC server is to create a pool of threads for the RPC server, each of which handle a number of asynchronously reading and writing connections.

@jrmithdobbs
Copy link
Contributor

This works great for me as is and is a good first step to fixing this.

@shanew
Copy link
Contributor

shanew commented May 29, 2011

Can you rebase? This doesn't apply to current tree.

Properly does ASIO for both SSL and non-SSL cases if SSL is enabled, and
also if SSL is disabled.

Next steps: attempt to non-block on the actual RPC call.
            make the whole thing a thread pool
@jordanlewis
Copy link
Contributor Author

Rebased to current tree.

@shanew
Copy link
Contributor

shanew commented Jun 7, 2011

Using this patch on a heavily loaded bitcoind, I am getting quite a few:
reservekeyfromkeypool(): read failed
from send transactions.

I backed out the patch and so far so good but time will tell. Are you aware of any wallet locking issues with this async code?

@dlancer
Copy link

dlancer commented Jun 10, 2011

Can you rebase with latest version? With transaction fee 0.0005 ?
Why this important pull still not merged with upstream?

@jgarzik
Copy link
Contributor

jgarzik commented Jun 14, 2011

Any updated test results, from heavily loaded bitcoind's?

@doublec
Copy link

doublec commented Jun 17, 2011

I'm running this patch on a loaded server. It works fine, but I've seen one problem. If I do "bitcoind listtransactions" I get a correct list of transactions. If I do "bitcoind listtransactions "" 1000" I get:
error: couldn't parse reply from server

@jgarzik
Copy link
Contributor

jgarzik commented Jun 17, 2011

Any chance you can look at wireshark output, or some other way of dumping the network traffic, and see what's going on? Sounds like output was truncated somewhere.

@doublec
Copy link

doublec commented Jun 17, 2011

Yep, I'll do that in a day or so and report back.

@jrmithdobbs
Copy link
Contributor

I don't have the dumps I made handy but I've seen this issue as well. It only seems to happen on large RPC calls like listtransactions. I actually ran across it testing out sipa's showwallet branch for privkey import/export and didn't make the correlation until seeing your comments.

Reverting this makes it stop happening. So there's definitely an issue here and this shouldn't be pulled until resolved.

The dumps I did showed it just cutting off in the middle sometimes or sometimes leaving out chunks of the response that made the json not validate.

@jordanlewis
Copy link
Contributor Author

Thanks for the testing guys. I'll look into this issue.

@jordanlewis jordanlewis reopened this Jun 17, 2011
@jrmithdobbs
Copy link
Contributor

Some more info. It also happens on RPC requests receiving a lot of data. Eg, sipa's importwallet. The "alot" seems to be around the 1k boundary or so from my very brief testing.

@jine
Copy link

jine commented Jun 25, 2011

I'm willing to pay to get this fixed and working in production use.
Also looking for a keep-alive solution which would reuse connections to bitcoind.

}
void respond(std::string str)
{
boost::asio::async_write(socket, boost::asio::buffer(str),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

str goes out of scope when the method returns

@ius
Copy link
Contributor

ius commented Jun 28, 2011

See comment above. A possible fix: http://pastie.org/private/d04wwgdsk881yl70k1g

I'm not familiar with boost though, so there might very well be a better solution.

@JoelKatz
Copy link
Contributor

JoelKatz commented Jul 3, 2011

If your plan is to optimize the RPC code, you're kind of barking up the wrong tree. The socket I/O is only about 3% of the load coming from the RPC code. If you just want it to handle more than one connection at a time and keepalives, just dispatching the RPC to a thread (and fixing the protocol handler to close the socket when it's the right time) does it.

The breakdown is, roughly:
30% Do the actual operation (various based on the operation, of course)
20% Parse JSON request
20% Generate JSON reply
15% Parse HTTP
4% Check user/pass/IP
3% Socket I/O
2% Make JSON reply
1% Send HTTP reply

This is still the right thing to do. However, there are much simpler and less invasive ways to accomplish the same thing. Now, if you had done this for the net code, that would actually make a huge difference.

@jgarzik
Copy link
Contributor

jgarzik commented Jul 3, 2011

@JoelKatz: you missed the point. This is not an optimization, but a big step towards correcting a major design flaw. The current RPC code executes HTTP requests in order, in a FIFO queue.

You can find examples of this logic in "My First TCP Server" style code examples, but never in any production server. A synchronous, FIFO approach stalls all clients except the "current" one. If the current client is, itself, stalled or slow or misbehaving, then all other clients suffer.

Asynchronous I/O + HTTP/1.1 keep alives are desperately needed to solve obvious problems seen in the field by heavy RPC users.

@JoelKatz
Copy link
Contributor

JoelKatz commented Jul 3, 2011

As I said, that issue is more easily solved by simply dispatching the RPC to a thread and making the trivial fixes to the keepalive logic. There aren't enough RPC connections, and the operation order is always accept/read/write, so you don't get any benefit from asynchronous I/O. In contrast, in the 'net' code, you have many connections and unpredictable operation order. That code would significantly benefit from async I/O.

@jgarzik
Copy link
Contributor

jgarzik commented Jul 3, 2011

One thread per RPC connection is unscalable in many modern workloads. That is also potentially DoS'able, if you're not careful.

@JoelKatz
Copy link
Contributor

JoelKatz commented Jul 3, 2011

I don't think many people, if any, expose their bitcoin RPC connections to the world. So I don't think the DoS issue is particularly important. I guess you could argue that they don't because they can't, and if they could, they might. But I think most people run a bitcoin client on each machine that needs to issue RPC queries and should bind their RPC listening sockets to 'localhost' only.

As for RPC not being scalable in modern workloads, I would argue that modern workloads include proper support for keepalives and don't require large numbers of connections.

If there's a realistic case where asio for RPC provides any benefit over thread-per-connection with proper keepalive support, I don't know what it is. Again, I still think this patch is "the right thing to do", but I don't think there will be any actual benefit in any realistic use case. (Again, over dipatching the RPC calls to threads and fixing the broken HTTP keepalive implementation. You have to at least do that.)

@jgarzik
Copy link
Contributor

jgarzik commented Jul 15, 2011

Any rebase / update for current tree?

@alexwaters
Copy link
Contributor

The pull has become unmergeable (without conflicts), and will be closed in 15 days from this message if action is not taken.

To prevent closure, kindly rebase the pull to merge cleanly with the current codebase. If a time extension is needed, please respond to this comment or contact QA@BitcoinTesting.org.

@jordanlewis
Copy link
Contributor Author

Sorry guys, I don't have the time to maintain this pull indefinitely. Anyone please feel free to rebase and maintain yourself. I think it's an important patch.

@jordanlewis jordanlewis reopened this Sep 30, 2011
@alexwaters
Copy link
Contributor

Closed pending rebase / additional commentary. The rebase label has been applied.

@alexwaters alexwaters closed this Oct 20, 2011
dexX7 pushed a commit to dexX7/bitcoin that referenced this pull request Dec 1, 2014
MetaDexObjectsToJSON: pass std::vector<CMPMetaDEx> by reference
sipa added a commit to sipa/bitcoin that referenced this pull request Mar 27, 2015
1897b8e Merge pull request bitcoin#229
efc571c Add simple testcases for signing with rfc6979 extra entropy.
1573a10 Add ability to pass extra entropy to rfc6979
3087bc4 Merge pull request bitcoin#228
d9b9f11 Merge pull request bitcoin#218
0065a8f Eliminate multiple-returns from secp256k1.c.
354ffa3 Make secp256k1_ec_pubkey_create reject oversized secrets.
27bc131 Silence some warnings from pedantic static analysis tools, improve compatibility with C++.
3b7ea63 Merge pull request bitcoin#221
f789c5b Merge pull request bitcoin#215
4bc273b Merge pull request bitcoin#222
137a8ec Merge pull request bitcoin#216
7c3771d Disable overlength-strings warnings.
8956111 use 128-bit hex seed
02efd06 Use RFC6979 for test PRNGs
ae55e85 Use faster byteswapping and avoid alignment-increasing casts.
443cd4b Get rid of hex format and some binary conversions
0bada0e Merge bitcoin#214: Improve signing API documentation & specification
8030d7c Improve signing API documentation & specification
7b2fc1c Merge bitcoin#213: Removed gotos, which are hard to trace and maintain.
11690d3 Removed gotos, which are hard to trace and maintain.
122a1ec Merge pull request bitcoin#205
035406d Merge pull request bitcoin#206
2d4cd53 Merge pull request bitcoin#161
34b898d Additional comments for the testing PRNG and a seeding fix.
6efd6e7 Some comments explaining some of the constants in the code.
ffccfd2 x86_64 assembly optimization for scalar_4x64
67cbdf0 Merge pull request bitcoin#207
039723d Benchmarks for all internal operations
6cc8425 Include a comment on secp256k1_ecdsa_sign explaining low-s.
f88343f Merge pull request bitcoin#203
d61e899 Add group operation counts
2473f17 Merge pull request bitcoin#202
b5bbce6 Some readme updates, e.g. removal of the GMP field.
f0d851e Merge pull request bitcoin#201
a0ea884 Merge pull request bitcoin#200
f735446 Convert the rest of the codebase to C89.
bf2e1ac Convert tests to C89. (also fixes a use of bare "inline" in field)
fc8285f Merge pull request bitcoin#199
fff412e Merge pull request bitcoin#197
4be8d6f Centralize the definition of uint128_t and use it uniformly.
d9543c9 Switch scalar code to C89.
fcc48c4 Remove the non-storage cmov
55422b6 Switch ecmult_gen to use storage types
41f8455 Use group element storage type in EC multiplications
e68d720 Add group element storage type
ff889f7 Field storage type
7137be8 Merge pull request bitcoin#196
0768bd5 Get rid of variable-length hex string conversions
e84e761 Merge pull request bitcoin#195
792bcdb Covert several more files to C89.
45cdf44 Merge pull request bitcoin#193
17db09e Merge pull request bitcoin#194
402878a fix ifdef/ifndef
25b35c7 Convert field code to strict C89 (+ long long, +__int128)
3627437 C89 nits and dead code removal.
a9f350d Merge pull request bitcoin#191
4732d26 Convert the field/group/ecdsa constant initialization to static consts
19f3e76 Remove unused secp256k1_fe_inner_{start, stop} functions
f1ebfe3 Convert the scalar constant initialization to static consts

git-subtree-dir: src/secp256k1
git-subtree-split: 1897b8e
TheBlueMatt added a commit to TheBlueMatt/bitcoin that referenced this pull request Oct 20, 2015
This contains the following two merges, as well as a few other changes:

Squashed 'src/secp256k1/' changes from 22f60a6..18f9f08

18f9f08 Pedersen commitments, borromean ring signatures, and ZK range proofs.
5161227 Add benchmark for ECDH multiplication
c40cb72 Expose API for constant time point multiplication
40adc7a Add constant-time `secp256k1_ecdh_point_multiply` for ECDH
ff9a397 Add zero/one tests to ecmult
729badf Merge pull request bitcoin#210
2d5a186 Apply effective-affine trick to precomp
4f9791a Effective affine addition in EC multiplication

git-subtree-dir: src/secp256k1
git-subtree-split: 18f9f0821c5a7795b760763c99d545af96a22775

Squashed 'src/secp256k1/' changes from b0210a9..22f60a6

22f60a6 Merge pull request bitcoin#245
61c1b1e Merge pull request bitcoin#190
d227579 Add scalar blinding and a secp256k1_context_randomize() call.
c146b4a Add bench_internal to gitignore.
9c4fb23 Add a secp256k1_fe_cmov unit test.
426fa52 Merge pull request bitcoin#243
d505a89 Merge pull request bitcoin#244
2d2707a travis: test i686 builds with gmp
cf7f702 travis: update to new build infrastructure
bb0ea50 Replace set/add with cmov in secp256k1_gej_add_ge.
f3d3519 Merge pull request bitcoin#241
5c2a4fa Fix memory leak in context unit test
14aacdc Merge pull request bitcoin#239
93226a5 secp256k1.c: Add missing DEBUG_CHECKs for sufficiently capable contexts
6099220 Merge pull request bitcoin#237
6066bb6 Fix typo: avg -> max
9688030 Merge pull request bitcoin#236
d899b5b Expose ability to deep-copy a context
3608c7f Merge pull request bitcoin#208
a9b6595 [API BREAK] Introduce explicit contexts
a0d3b89 Merge pull request bitcoin#233
9e8d89b Merge pull request bitcoin#234
65e70e7 Merge pull request bitcoin#235
5098f62 Improve documentation formatting consistency
4450e24 Add a comment about the avoidance of secret data in array indexes.
6534ee1 initialize variable
d5b53aa Merge pull request bitcoin#232
c01df1a Avoid some implicit type conversions to make C++ compilers happy.
bfe96ba Merge pull request bitcoin#231
33270bf Add a couple comments pointing to particular sections of RFC6979.
41603aa Merge pull request bitcoin#230
2632019 Brace all the if/for/while.
1897b8e Merge pull request bitcoin#229
efc571c Add simple testcases for signing with rfc6979 extra entropy.
1573a10 Add ability to pass extra entropy to rfc6979
3087bc4 Merge pull request bitcoin#228
d9b9f11 Merge pull request bitcoin#218
0065a8f Eliminate multiple-returns from secp256k1.c.
354ffa3 Make secp256k1_ec_pubkey_create reject oversized secrets.
27bc131 Silence some warnings from pedantic static analysis tools, improve compatibility with C++.
3b7ea63 Merge pull request bitcoin#221
f789c5b Merge pull request bitcoin#215
4bc273b Merge pull request bitcoin#222
137a8ec Merge pull request bitcoin#216
7c3771d Disable overlength-strings warnings.
8956111 use 128-bit hex seed
02efd06 Use RFC6979 for test PRNGs
ae55e85 Use faster byteswapping and avoid alignment-increasing casts.
443cd4b Get rid of hex format and some binary conversions
0bada0e Merge bitcoin#214: Improve signing API documentation & specification
8030d7c Improve signing API documentation & specification
7b2fc1c Merge bitcoin#213: Removed gotos, which are hard to trace and maintain.
11690d3 Removed gotos, which are hard to trace and maintain.
122a1ec Merge pull request bitcoin#205
035406d Merge pull request bitcoin#206
2d4cd53 Merge pull request bitcoin#161
34b898d Additional comments for the testing PRNG and a seeding fix.
6efd6e7 Some comments explaining some of the constants in the code.
ffccfd2 x86_64 assembly optimization for scalar_4x64
67cbdf0 Merge pull request bitcoin#207
039723d Benchmarks for all internal operations
6cc8425 Include a comment on secp256k1_ecdsa_sign explaining low-s.
f88343f Merge pull request bitcoin#203
d61e899 Add group operation counts
2473f17 Merge pull request bitcoin#202
b5bbce6 Some readme updates, e.g. removal of the GMP field.
f0d851e Merge pull request bitcoin#201
a0ea884 Merge pull request bitcoin#200
f735446 Convert the rest of the codebase to C89.
bf2e1ac Convert tests to C89. (also fixes a use of bare "inline" in field)
fc8285f Merge pull request bitcoin#199
fff412e Merge pull request bitcoin#197
4be8d6f Centralize the definition of uint128_t and use it uniformly.
d9543c9 Switch scalar code to C89.
fcc48c4 Remove the non-storage cmov
55422b6 Switch ecmult_gen to use storage types
41f8455 Use group element storage type in EC multiplications
e68d720 Add group element storage type
ff889f7 Field storage type
7137be8 Merge pull request bitcoin#196
0768bd5 Get rid of variable-length hex string conversions
e84e761 Merge pull request bitcoin#195
792bcdb Covert several more files to C89.
45cdf44 Merge pull request bitcoin#193
17db09e Merge pull request bitcoin#194
402878a fix ifdef/ifndef
25b35c7 Convert field code to strict C89 (+ long long, +__int128)
3627437 C89 nits and dead code removal.
a9f350d Merge pull request bitcoin#191
4732d26 Convert the field/group/ecdsa constant initialization to static consts
19f3e76 Remove unused secp256k1_fe_inner_{start, stop} functions
f1ebfe3 Convert the scalar constant initialization to static consts
50cc6ab Merge pull request bitcoin#178
941e221 Add tests for handling of the nonce function in signing.
10c81ff Merge pull request bitcoin#177
7688e34 Add magnitude limits to secp256k1_fe_verify to ensure that it's own tests function correctly.
4ee4f7a Merge pull request bitcoin#176
70ae0d2 Use secp256k1_fe_equal_var in secp256k1_fe_sqrt_var.
7767b4d Merge pull request bitcoin#175
9ab9335 Add a reference consistency test to ge_tests.
60571c6 Rework group tests
d26e26f Avoid constructing an invalid signature with probability 1:2^256.
b450c34 Merge pull request bitcoin#163
d57cae9 Merge pull request bitcoin#154
49ee0db Add _normalizes_to_zero_var variant
eed599d Add _fe_normalizes_to_zero method
d7174ed Weak normalization for secp256k1_fe_equal
0295f0a weak normalization
bbd5ba7 Use rfc6979 as default nonce generation function
b37fbc2 Implement SHA256 / HMAC-SHA256 / RFC6979.
c6e7f4e [API BREAK] Use a nonce-generation function instead of a nonce
cf0c48b Merge pull request bitcoin#169
603c33b Make signing fail if a too small buffer is passed.
6d16606 Merge pull request bitcoin#168
7277fd7 Remove GMP field implementation
e99c4c4 Merge pull request bitcoin#123
13278f6 Add explanation about how inversion can be avoided
ce7eb6f Optimize verification: avoid field inverse
a098f78 Merge pull request bitcoin#160
38acd01 Merge pull request bitcoin#165
6a59012 Make git ignore bench_recover when configured with benchmark enabled
1ba4a60 Configure options reorganization
3c0f246 Merge pull request bitcoin#157
808dd9b Merge pull request bitcoin#156
8dc75e9 Merge pull request bitcoin#158
28ade27 build: nuke bashisms
5190079 build: use subdir-objects for automake
8336040 build: disable benchmark by default
bccaf86 Merge pull request bitcoin#150
2a53a47 Merge pull request bitcoin#151
5f5a31f Merge pull request bitcoin#149
3907277 Merge pull request bitcoin#142
a3e0611 Enable tests in x86 travis builds
45da235 x86 builder
8bb0e93 Merge pull request bitcoin#155
971fe81 build: fix openssl detection for cross builds
f22d73e Explicitly access %0..%2 as 64-bit so we use the right registers for x32 ABI
e66d4d6 Avoid the stack in assembly and use explicit registers
cf7b2b4 Fix ECDSA message hashes to 32 bytes
056ad31 Really compile with -O3 by default
74ad63a Merge pull request bitcoin#146
9000458 Merge pull request bitcoin#145
1f46b00 build: fix __builtin_expect detection for clang
aaba2e0 Merge pull request bitcoin#136
8a0775c Merge pull request bitcoin#144
ee1eaa7 Merge pull request bitcoin#141
c88e2b8 Compile with -O3 by default
6558a26 Make the benchmarks print out stats
000bdf6 Rename bench_verify to bench_recovery
7c6fed2 Add a few more additional tests.
992e03b travis: add clang to the test matrix
b43b79a Merge pull request bitcoin#143
e06a924 Include time.h header for time().
8d11164 Add some additional tests.
3545627 Merge pull request bitcoin#118
6a9901e Merge pull request bitcoin#137
376b28b Merge pull request bitcoin#128
1728806 Merge pull request bitcoin#138
a5759c5 Check return value of malloc
39bd94d Variable time normalize
ad86bdf Merge pull request bitcoin#140
54b768c Another redundant secp256k1_fe_normalize
69dcaab Merge pull request bitcoin#139
1c29f2e Remove redundant secp256k1_fe_normalize from secp256k1_gej_add_ge_var.
2b9388b Remove unused secp256k1_fe_inv_all
f461b76 Allocate precomputation arrays on the heap
b2c9681 Make {mul,sqr}_inner use the same argument order as {mul,sqr}
6793505 Convert YASM code into inline assembly
f048615 Rewrite field assembly to match the C version
3ce74b1 Tweak precomputed table size for G

git-subtree-dir: src/secp256k1
git-subtree-split: 22f60a6
deadalnix pushed a commit to deadalnix/bitcoin that referenced this pull request Jan 19, 2017
8030d7c Improve signing API documentation & specification (Pieter Wuille)
deadalnix pushed a commit to deadalnix/bitcoin that referenced this pull request Feb 12, 2017
lateminer pushed a commit to lateminer/bitcoin that referenced this pull request Dec 9, 2017
Losangelosgenetics pushed a commit to Losangelosgenetics/bitcoin that referenced this pull request Mar 12, 2020
rajarshimaitra pushed a commit to rajarshimaitra/bitcoin that referenced this pull request Aug 5, 2021
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants