external_signer: replace boost::process with cpp-subprocess
This primarily affects the `RunCommandParseJSON` utility function.
This commit is contained in:
1 parent
cc8b9875b1
commit
70434b1c44
5 files changed
+20
-29
No files matched your search
@@ -323,6 +323,7 @@ BITCOIN_CORE_H = \
|
|||||||
util/sock.h \
|
util/sock.h \
|
||||||
util/spanparsing.h \
|
util/spanparsing.h \
|
||||||
util/string.h \
|
util/string.h \
|
||||||
|
util/subprocess.hpp \
|
||||||
util/syserror.h \
|
util/syserror.h \
|
||||||
util/task_runner.h \
|
util/task_runner.h \
|
||||||
util/thread.h \
|
util/thread.h \
|
||||||
|
|||||||
+10
-15
@@ -12,39 +12,34 @@
|
|||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
#ifdef ENABLE_EXTERNAL_SIGNER
|
#ifdef ENABLE_EXTERNAL_SIGNER
|
||||||
#include <boost/process.hpp>
|
#include <util/subprocess.hpp>
|
||||||
#endif // ENABLE_EXTERNAL_SIGNER
|
#endif // ENABLE_EXTERNAL_SIGNER
|
||||||
|
|
||||||
UniValue RunCommandParseJSON(const std::string& str_command, const std::string& str_std_in)
|
UniValue RunCommandParseJSON(const std::string& str_command, const std::string& str_std_in)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_EXTERNAL_SIGNER
|
#ifdef ENABLE_EXTERNAL_SIGNER
|
||||||
namespace bp = boost::process;
|
namespace sp = subprocess;
|
||||||
|
|
||||||
UniValue result_json;
|
UniValue result_json;
|
||||||
bp::opstream stdin_stream;
|
std::istringstream stdout_stream;
|
||||||
bp::ipstream stdout_stream;
|
std::istringstream stderr_stream;
|
||||||
bp::ipstream stderr_stream;
|
|
||||||
|
|
||||||
if (str_command.empty()) return UniValue::VNULL;
|
if (str_command.empty()) return UniValue::VNULL;
|
||||||
|
|
||||||
bp::child c(
|
auto c = sp::Popen(str_command, sp::input{sp::PIPE}, sp::output{sp::PIPE}, sp::error{sp::PIPE});
|
||||||
str_command,
|
|
||||||
bp::std_out > stdout_stream,
|
|
||||||
bp::std_err > stderr_stream,
|
|
||||||
bp::std_in < stdin_stream
|
|
||||||
);
|
|
||||||
if (!str_std_in.empty()) {
|
if (!str_std_in.empty()) {
|
||||||
stdin_stream << str_std_in << std::endl;
|
c.send(str_std_in);
|
||||||
}
|
}
|
||||||
stdin_stream.pipe().close();
|
auto [out_res, err_res] = c.communicate();
|
||||||
|
stdout_stream.str(std::string{out_res.buf.begin(), out_res.buf.end()});
|
||||||
|
stderr_stream.str(std::string{err_res.buf.begin(), err_res.buf.end()});
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
std::string error;
|
std::string error;
|
||||||
std::getline(stdout_stream, result);
|
std::getline(stdout_stream, result);
|
||||||
std::getline(stderr_stream, error);
|
std::getline(stderr_stream, error);
|
||||||
|
|
||||||
c.wait();
|
const int n_error = c.retcode();
|
||||||
const int n_error = c.exit_code();
|
|
||||||
if (n_error) throw std::runtime_error(strprintf("RunCommandParseJSON error: process(%s) returned %d: %s\n", str_command, n_error, error));
|
if (n_error) throw std::runtime_error(strprintf("RunCommandParseJSON error: process(%s) returned %d: %s\n", str_command, n_error, error));
|
||||||
if (!result_json.read(result)) throw std::runtime_error("Unable to parse JSON: " + result);
|
if (!result_json.read(result)) throw std::runtime_error("Unable to parse JSON: " + result);
|
||||||
|
|
||||||
|
|||||||
@@ -62,12 +62,12 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector<ExternalS
|
|||||||
|
|
||||||
UniValue ExternalSigner::DisplayAddress(const std::string& descriptor) const
|
UniValue ExternalSigner::DisplayAddress(const std::string& descriptor) const
|
||||||
{
|
{
|
||||||
return RunCommandParseJSON(m_command + " --fingerprint \"" + m_fingerprint + "\"" + NetworkArg() + " displayaddress --desc \"" + descriptor + "\"");
|
return RunCommandParseJSON(m_command + " --fingerprint " + m_fingerprint + NetworkArg() + " displayaddress --desc " + descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue ExternalSigner::GetDescriptors(const int account)
|
UniValue ExternalSigner::GetDescriptors(const int account)
|
||||||
{
|
{
|
||||||
return RunCommandParseJSON(m_command + " --fingerprint \"" + m_fingerprint + "\"" + NetworkArg() + " getdescriptors --account " + strprintf("%d", account));
|
return RunCommandParseJSON(m_command + " --fingerprint " + m_fingerprint + NetworkArg() + " getdescriptors --account " + strprintf("%d", account));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExternalSigner::SignTransaction(PartiallySignedTransaction& psbtx, std::string& error)
|
bool ExternalSigner::SignTransaction(PartiallySignedTransaction& psbtx, std::string& error)
|
||||||
@@ -93,8 +93,8 @@ bool ExternalSigner::SignTransaction(PartiallySignedTransaction& psbtx, std::str
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string command = m_command + " --stdin --fingerprint \"" + m_fingerprint + "\"" + NetworkArg();
|
const std::string command = m_command + " --stdin --fingerprint " + m_fingerprint + NetworkArg();
|
||||||
const std::string stdinStr = "signtx \"" + EncodeBase64(ssTx.str()) + "\"";
|
const std::string stdinStr = "signtx " + EncodeBase64(ssTx.str());
|
||||||
|
|
||||||
const UniValue signer_result = RunCommandParseJSON(command, stdinStr);
|
const UniValue signer_result = RunCommandParseJSON(command, stdinStr);
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
#ifdef ENABLE_EXTERNAL_SIGNER
|
#ifdef ENABLE_EXTERNAL_SIGNER
|
||||||
#include <boost/process.hpp>
|
#include <util/subprocess.hpp>
|
||||||
#endif // ENABLE_EXTERNAL_SIGNER
|
#endif // ENABLE_EXTERNAL_SIGNER
|
||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
@@ -34,20 +34,16 @@ BOOST_AUTO_TEST_CASE(run_command)
|
|||||||
BOOST_CHECK(result.isNull());
|
BOOST_CHECK(result.isNull());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const UniValue result = RunCommandParseJSON("echo \"{\"success\": true}\"");
|
const UniValue result = RunCommandParseJSON("echo {\"success\": true}");
|
||||||
BOOST_CHECK(result.isObject());
|
BOOST_CHECK(result.isObject());
|
||||||
const UniValue& success = result.find_value("success");
|
const UniValue& success = result.find_value("success");
|
||||||
BOOST_CHECK(!success.isNull());
|
BOOST_CHECK(!success.isNull());
|
||||||
BOOST_CHECK_EQUAL(success.get_bool(), true);
|
BOOST_CHECK_EQUAL(success.get_bool(), true);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// An invalid command is handled by Boost
|
// An invalid command is handled by cpp-subprocess
|
||||||
const int expected_error{2};
|
const std::string expected{"execve failed: "};
|
||||||
BOOST_CHECK_EXCEPTION(RunCommandParseJSON("invalid_command"), boost::process::process_error, [&](const boost::process::process_error& e) {
|
BOOST_CHECK_EXCEPTION(RunCommandParseJSON("invalid_command"), subprocess::CalledProcessError, HasReason(expected));
|
||||||
BOOST_CHECK(std::string(e.what()).find("RunCommandParseJSON error:") == std::string::npos);
|
|
||||||
BOOST_CHECK_EQUAL(e.code().value(), expected_error);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// Return non-zero exit code, no output to stderr
|
// Return non-zero exit code, no output to stderr
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ EXPECTED_BOOST_INCLUDES = ["boost/date_time/posix_time/posix_time.hpp",
|
|||||||
"boost/multi_index/tag.hpp",
|
"boost/multi_index/tag.hpp",
|
||||||
"boost/multi_index_container.hpp",
|
"boost/multi_index_container.hpp",
|
||||||
"boost/operators.hpp",
|
"boost/operators.hpp",
|
||||||
"boost/process.hpp",
|
|
||||||
"boost/signals2/connection.hpp",
|
"boost/signals2/connection.hpp",
|
||||||
"boost/signals2/optional_last_value.hpp",
|
"boost/signals2/optional_last_value.hpp",
|
||||||
"boost/signals2/signal.hpp",
|
"boost/signals2/signal.hpp",
|
||||||
|
|||||||
Reference in new issue
Block a user