diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index e7d9acfe..73c8abf7 100755 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -16,7 +16,7 @@ endif() unset(SUPPORT_MULTIPLE_SONS) unset(SUPPORT_MULTIPLE_SONS CACHE) -target_link_libraries( peerplays_sidechain graphene_chain graphene_app fc zmq ) +target_link_libraries( peerplays_sidechain graphene_chain graphene_app bitcoin fc zmq ) target_include_directories( peerplays_sidechain PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp index d483e23c..350f7666 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp @@ -110,10 +110,15 @@ private: std::string create_deposit_transaction(const son_wallet_deposit_object &swdo); std::string create_withdrawal_transaction(const son_wallet_withdraw_object &swwo); + std::string create_multisig_address(const std::vector> &son_pubkeys); std::string create_transaction(const std::vector &inputs, const fc::flat_map outputs); std::string sign_transaction(const sidechain_transaction_object &sto); std::string send_transaction(const sidechain_transaction_object &sto); + std::string create_multisig_address_raw(const std::vector> &son_pubkeys); + std::string create_multisig_address_psbt(const std::vector> &son_pubkeys); + std::string create_multisig_address_standalone(const std::vector> &son_pubkeys); + std::string create_transaction_raw(const std::vector &inputs, const fc::flat_map outputs); std::string create_transaction_psbt(const std::vector &inputs, const fc::flat_map outputs); std::string create_transaction_standalone(const std::vector &inputs, const fc::flat_map outputs); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index c6c4fb3a..0bd4d290 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -3,6 +3,8 @@ #include #include +#include + #include #include #include @@ -1067,16 +1069,12 @@ void sidechain_net_handler_bitcoin::process_primary_wallet() { const chain::global_property_object &gpo = database.get_global_properties(); auto active_sons = gpo.active_sons; - vector son_pubkeys_bitcoin; + vector> son_pubkeys_bitcoin; for (const son_info &si : active_sons) { - son_pubkeys_bitcoin.push_back(si.sidechain_public_keys.at(sidechain_type::bitcoin)); + son_pubkeys_bitcoin.push_back(std::make_pair(si.sidechain_public_keys.at(sidechain_type::bitcoin), si.weight)); } - if (!wallet_password.empty()) { - bitcoin_client->walletpassphrase(wallet_password, 5); - } - uint32_t nrequired = son_pubkeys_bitcoin.size() * 2 / 3 + 1; - string reply_str = bitcoin_client->createmultisig(nrequired, son_pubkeys_bitcoin); + string reply_str = create_multisig_address(son_pubkeys_bitcoin); std::stringstream active_pw_ss(reply_str); boost::property_tree::ptree active_pw_pt; @@ -1378,6 +1376,16 @@ std::string sidechain_net_handler_bitcoin::create_withdrawal_transaction(const s return create_transaction(inputs, outputs); } +// Creates segwit multisig address +// Function to actually create segwit multisig address should return json string with address info, or empty string in case of failure +std::string sidechain_net_handler_bitcoin::create_multisig_address(const std::vector> &son_pubkeys) { + std::string new_addr = ""; + //new_addr = create_multisig_address_raw(son_pubkeys); + //new_addr = create_multisig_address_psbt(son_pubkeys); + new_addr = create_multisig_address_standalone(son_pubkeys); + return new_addr; +} + // Creates transaction in any format // Function to actually create transaction should return transaction string, or empty string in case of failure std::string sidechain_net_handler_bitcoin::create_transaction(const std::vector &inputs, const fc::flat_map outputs) { @@ -1403,6 +1411,74 @@ std::string sidechain_net_handler_bitcoin::send_transaction(const sidechain_tran return send_transaction_psbt(sto); } +std::string sidechain_net_handler_bitcoin::create_multisig_address_raw(const std::vector> &son_pubkeys) { + vector pubkeys; + for (auto s : son_pubkeys) { + pubkeys.push_back(s.first); + } + + if (!wallet_password.empty()) { + bitcoin_client->walletpassphrase(wallet_password, 5); + } + + uint32_t nrequired = pubkeys.size() * 2 / 3 + 1; + return bitcoin_client->addmultisigaddress(nrequired, pubkeys); +} + +std::string sidechain_net_handler_bitcoin::create_multisig_address_psbt(const std::vector> &son_pubkeys) { + vector pubkeys; + for (auto s : son_pubkeys) { + pubkeys.push_back(s.first); + } + + if (!wallet_password.empty()) { + bitcoin_client->walletpassphrase(wallet_password, 5); + } + + uint32_t nrequired = pubkeys.size() * 2 / 3 + 1; + return bitcoin_client->addmultisigaddress(nrequired, pubkeys); +} + +std::string sidechain_net_handler_bitcoin::create_multisig_address_standalone(const std::vector> &son_pubkeys) { + + using namespace libbitcoin; + using namespace libbitcoin::chain; + using namespace libbitcoin::machine; + using namespace libbitcoin::wallet; + + uint32_t nrequired = son_pubkeys.size() * 2 / 3 + 1; + point_list keys; + for (auto son_pubkey : son_pubkeys) { + keys.push_back(ec_public(son_pubkey.first)); + } + script witness_script = script::to_pay_multisig_pattern(nrequired, keys); + + // sha256 of witness script + data_chunk multisig_hash = to_chunk(sha256_hash(witness_script.to_data(0))); + + // redeem script + libbitcoin::machine::operation::list redeemscript_ops{libbitcoin::machine::operation(opcode(0)), libbitcoin::machine::operation(multisig_hash)}; + script redeem_script = script(redeemscript_ops); + + // address + payment_address address = payment_address(redeem_script, payment_address::testnet_p2sh); + + std::stringstream ss; + ss << "{\n \"address\": \"" << address.encoded() + << "\",\n \"redeemScript\": \"" << encode_base16(witness_script.to_data(0)) << "\"\n}\n"; + + std::cout << "Redeem Script Hash: " << encode_base16(address.hash()) << std::endl; + std::cout << "Payment Address: " << address.encoded() << std::endl; + std::cout << "Redeem Script: " << redeem_script.to_string(0) << std::endl; + std::cout << "Witness Script: " << witness_script.to_string(0) << std::endl; + std::cout << "Witness Script: " << encode_base16(witness_script.to_data(0)) << std::endl; + std::cout << "Locking Script: " << P2SH_P2WSH.to_string(0) << std::endl; + + //create_multisig_address_psbt(son_pubkeys); + + return ss.str(); +} + std::string sidechain_net_handler_bitcoin::create_transaction_raw(const std::vector &inputs, const fc::flat_map outputs) { return bitcoin_client->createrawtransaction(inputs, outputs); }