Skip to content

Commit 70434b1

Browse files
theStackhebasto
authored andcommitted
external_signer: replace boost::process with cpp-subprocess
This primarily affects the `RunCommandParseJSON` utility function.
1 parent cc8b987 commit 70434b1

File tree

5 files changed

+20
-29
lines changed

5 files changed

+20
-29
lines changed

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ BITCOIN_CORE_H = \
323323
util/sock.h \
324324
util/spanparsing.h \
325325
util/string.h \
326+
util/subprocess.hpp \
326327
util/syserror.h \
327328
util/task_runner.h \
328329
util/thread.h \

src/common/run_command.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,34 @@
1212
#include <univalue.h>
1313

1414
#ifdef ENABLE_EXTERNAL_SIGNER
15-
#include <boost/process.hpp>
15+
#include <util/subprocess.hpp>
1616
#endif // ENABLE_EXTERNAL_SIGNER
1717

1818
UniValue RunCommandParseJSON(const std::string& str_command, const std::string& str_std_in)
1919
{
2020
#ifdef ENABLE_EXTERNAL_SIGNER
21-
namespace bp = boost::process;
21+
namespace sp = subprocess;
2222

2323
UniValue result_json;
24-
bp::opstream stdin_stream;
25-
bp::ipstream stdout_stream;
26-
bp::ipstream stderr_stream;
24+
std::istringstream stdout_stream;
25+
std::istringstream stderr_stream;
2726

2827
if (str_command.empty()) return UniValue::VNULL;
2928

30-
bp::child c(
31-
str_command,
32-
bp::std_out > stdout_stream,
33-
bp::std_err > stderr_stream,
34-
bp::std_in < stdin_stream
35-
);
29+
auto c = sp::Popen(str_command, sp::input{sp::PIPE}, sp::output{sp::PIPE}, sp::error{sp::PIPE});
3630
if (!str_std_in.empty()) {
37-
stdin_stream << str_std_in << std::endl;
31+
c.send(str_std_in);
3832
}
39-
stdin_stream.pipe().close();
33+
auto [out_res, err_res] = c.communicate();
34+
stdout_stream.str(std::string{out_res.buf.begin(), out_res.buf.end()});
35+
stderr_stream.str(std::string{err_res.buf.begin(), err_res.buf.end()});
4036

4137
std::string result;
4238
std::string error;
4339
std::getline(stdout_stream, result);
4440
std::getline(stderr_stream, error);
4541

46-
c.wait();
47-
const int n_error = c.exit_code();
42+
const int n_error = c.retcode();
4843
if (n_error) throw std::runtime_error(strprintf("RunCommandParseJSON error: process(%s) returned %d: %s\n", str_command, n_error, error));
4944
if (!result_json.read(result)) throw std::runtime_error("Unable to parse JSON: " + result);
5045

src/external_signer.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,12 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector<ExternalS
6262

6363
UniValue ExternalSigner::DisplayAddress(const std::string& descriptor) const
6464
{
65-
return RunCommandParseJSON(m_command + " --fingerprint \"" + m_fingerprint + "\"" + NetworkArg() + " displayaddress --desc \"" + descriptor + "\"");
65+
return RunCommandParseJSON(m_command + " --fingerprint " + m_fingerprint + NetworkArg() + " displayaddress --desc " + descriptor);
6666
}
6767

6868
UniValue ExternalSigner::GetDescriptors(const int account)
6969
{
70-
return RunCommandParseJSON(m_command + " --fingerprint \"" + m_fingerprint + "\"" + NetworkArg() + " getdescriptors --account " + strprintf("%d", account));
70+
return RunCommandParseJSON(m_command + " --fingerprint " + m_fingerprint + NetworkArg() + " getdescriptors --account " + strprintf("%d", account));
7171
}
7272

7373
bool ExternalSigner::SignTransaction(PartiallySignedTransaction& psbtx, std::string& error)
@@ -93,8 +93,8 @@ bool ExternalSigner::SignTransaction(PartiallySignedTransaction& psbtx, std::str
9393
return false;
9494
}
9595

96-
const std::string command = m_command + " --stdin --fingerprint \"" + m_fingerprint + "\"" + NetworkArg();
97-
const std::string stdinStr = "signtx \"" + EncodeBase64(ssTx.str()) + "\"";
96+
const std::string command = m_command + " --stdin --fingerprint " + m_fingerprint + NetworkArg();
97+
const std::string stdinStr = "signtx " + EncodeBase64(ssTx.str());
9898

9999
const UniValue signer_result = RunCommandParseJSON(command, stdinStr);
100100

src/test/system_tests.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include <univalue.h>
1212

1313
#ifdef ENABLE_EXTERNAL_SIGNER
14-
#include <boost/process.hpp>
14+
#include <util/subprocess.hpp>
1515
#endif // ENABLE_EXTERNAL_SIGNER
1616

1717
#include <boost/test/unit_test.hpp>
@@ -34,20 +34,16 @@ BOOST_AUTO_TEST_CASE(run_command)
3434
BOOST_CHECK(result.isNull());
3535
}
3636
{
37-
const UniValue result = RunCommandParseJSON("echo \"{\"success\": true}\"");
37+
const UniValue result = RunCommandParseJSON("echo {\"success\": true}");
3838
BOOST_CHECK(result.isObject());
3939
const UniValue& success = result.find_value("success");
4040
BOOST_CHECK(!success.isNull());
4141
BOOST_CHECK_EQUAL(success.get_bool(), true);
4242
}
4343
{
44-
// An invalid command is handled by Boost
45-
const int expected_error{2};
46-
BOOST_CHECK_EXCEPTION(RunCommandParseJSON("invalid_command"), boost::process::process_error, [&](const boost::process::process_error& e) {
47-
BOOST_CHECK(std::string(e.what()).find("RunCommandParseJSON error:") == std::string::npos);
48-
BOOST_CHECK_EQUAL(e.code().value(), expected_error);
49-
return true;
50-
});
44+
// An invalid command is handled by cpp-subprocess
45+
const std::string expected{"execve failed: "};
46+
BOOST_CHECK_EXCEPTION(RunCommandParseJSON("invalid_command"), subprocess::CalledProcessError, HasReason(expected));
5147
}
5248
{
5349
// Return non-zero exit code, no output to stderr

test/lint/lint-includes.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
"boost/multi_index/tag.hpp",
3131
"boost/multi_index_container.hpp",
3232
"boost/operators.hpp",
33-
"boost/process.hpp",
3433
"boost/signals2/connection.hpp",
3534
"boost/signals2/optional_last_value.hpp",
3635
"boost/signals2/signal.hpp",

0 commit comments

Comments
 (0)