Skip to content

Commit f1d87d2

Browse files
committed
Add/test electrum blockchain.transaction.broadcast (partial).
1 parent 4696c48 commit f1d87d2

2 files changed

Lines changed: 74 additions & 5 deletions

File tree

src/protocols/protocol_electrum.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -409,14 +409,41 @@ void protocol_electrum::handle_blockchain_scripthash_unsubscribe(const code& ec,
409409
send_code(error::not_implemented);
410410
}
411411

412-
// TODO: requires tx pool in order to validate against unconfirmed txs.
413-
// TODO: requires that p2p channels subscribe to transaction broadcast.
414412
void protocol_electrum::handle_blockchain_transaction_broadcast(const code& ec,
415413
rpc_interface::blockchain_transaction_broadcast,
416-
const std::string& ) NOEXCEPT
414+
const std::string& raw_tx) NOEXCEPT
417415
{
418-
if (stopped(ec)) return;
419-
send_code(error::not_implemented);
416+
if (stopped(ec))
417+
return;
418+
419+
// ElectrumX changed in version 1.1 to return error vs. bitcoind result.
420+
// Previously it returned text string (bitcoind message) in the error case.
421+
422+
data_chunk tx_data{};
423+
if (!decode_base16(tx_data, raw_tx))
424+
{
425+
send_code(error::invalid_argument);
426+
return;
427+
}
428+
429+
const auto tx = to_shared<chain::transaction>(tx_data, true);
430+
if (!tx->is_valid())
431+
{
432+
send_code(error::invalid_argument);
433+
return;
434+
}
435+
436+
// TODO: handle just as any peer annoucement, validate and relay.
437+
// TODO: requires tx pool in order to validate against unconfirmed txs.
438+
constexpr auto confirmable = false;
439+
if (!confirmable)
440+
{
441+
send_code(error::unconfirmable_transaction);
442+
return;
443+
}
444+
445+
constexpr auto size = two * hash_size;
446+
send_result(encode_base16(tx->hash(false)), size, BIND(complete, _1));
420447
}
421448

422449
void protocol_electrum::handle_blockchain_transaction_get(const code& ec,

test/protocols/electrum/electrum_transactions.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,50 @@
1717
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1818
*/
1919
#include "../../test.hpp"
20+
#include "../blocks.hpp"
2021
#include "electrum.hpp"
22+
#include <boost/format.hpp>
2123

2224
BOOST_FIXTURE_TEST_SUITE(electrum_tests, electrum_setup_fixture)
2325

26+
// blockchain.transaction.broadcast
27+
28+
using namespace system;
29+
static const code invalid_argument{ server::error::invalid_argument };
30+
static const code unconfirmable_transaction{ server::error::unconfirmable_transaction };
31+
32+
BOOST_AUTO_TEST_CASE(electrum__blockchain_transaction_broadcast__empty__invalid_argument)
33+
{
34+
BOOST_CHECK(handshake());
35+
36+
const auto response = get(R"({"id":74,"method":"blockchain.transaction.broadcast","params":[""]})" "\n");
37+
BOOST_CHECK_EQUAL(response.at("error").as_object().at("code").as_int64(), invalid_argument.value());
38+
}
39+
40+
BOOST_AUTO_TEST_CASE(electrum__blockchain_transaction_broadcast__invalid_encoding__invalid_argument)
41+
{
42+
BOOST_CHECK(handshake());
43+
44+
const auto response = get(R"({"id":75,"method":"blockchain.transaction.broadcast","params":["deadbeef"]})" "\n");
45+
BOOST_CHECK_EQUAL(response.at("error").as_object().at("code").as_int64(), invalid_argument.value());
46+
}
47+
48+
BOOST_AUTO_TEST_CASE(electrum__blockchain_transaction_broadcast__invalid_tx__invalid_argument)
49+
{
50+
BOOST_CHECK(handshake());
51+
52+
const auto response = get(R"({"id":76,"method":"blockchain.transaction.broadcast","params":["0100000001"]})" "\n");
53+
BOOST_CHECK_EQUAL(response.at("error").as_object().at("code").as_int64(), invalid_argument.value());
54+
}
55+
56+
BOOST_AUTO_TEST_CASE(electrum__blockchain_transaction_broadcast__genesis_coinbase__unconfirmable_transaction)
57+
{
58+
BOOST_CHECK(handshake());
59+
60+
const auto tx0_text = encode_base16(genesis.transactions_ptr()->front()->to_data(true));
61+
constexpr auto request = R"({"id":73,"method":"blockchain.transaction.broadcast","params":["%1%"]})" "\n";
62+
const auto response = get((boost::format(request) % tx0_text).str());
63+
BOOST_CHECK_EQUAL(response.at("error").as_object().at("code").as_int64(), unconfirmable_transaction.value());
64+
}
65+
2466
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)