Merge branch 'feature/417/Add_support_in_bitcoin_for_P2SH-P2WSH_address_format' into 'feature/libbitcoin-son'
Add support for P2SH-P2WSH address format See merge request PBSA/peerplays!140
This commit is contained in:
commit
789c0547cf
5 changed files with 100 additions and 20 deletions
|
|
@ -242,12 +242,12 @@ bytes btc_multisig_segwit_address::get_address_bytes(const bytes &script_hash) {
|
|||
}
|
||||
|
||||
btc_weighted_multisig_address::btc_weighted_multisig_address(const std::vector<std::pair<fc::ecc::public_key, uint16_t>> &keys_data,
|
||||
network ntype) {
|
||||
network ntype, payment_type type) {
|
||||
network_type = ntype;
|
||||
this->type = type;
|
||||
create_redeem_script(keys_data);
|
||||
create_witness_script();
|
||||
create_segwit_address();
|
||||
type = payment_type::P2WSH;
|
||||
}
|
||||
|
||||
void btc_weighted_multisig_address::create_redeem_script(const std::vector<std::pair<fc::ecc::public_key, uint16_t>> &keys_data) {
|
||||
|
|
@ -278,26 +278,43 @@ void btc_weighted_multisig_address::create_witness_script() {
|
|||
script_builder builder;
|
||||
builder << op::_0;
|
||||
builder << fc::sha256::hash(redeem_script_.data(), redeem_script_.size());
|
||||
|
||||
witness_script_ = builder;
|
||||
}
|
||||
|
||||
void btc_weighted_multisig_address::create_segwit_address() {
|
||||
std::string hrp;
|
||||
address_types byte_version;
|
||||
switch (network_type) {
|
||||
case (network::mainnet):
|
||||
hrp = "bc";
|
||||
byte_version = address_types::MAINNET_SCRIPT;
|
||||
break;
|
||||
case (network::testnet):
|
||||
hrp = "tb";
|
||||
byte_version = address_types::TESTNET_SCRIPT;
|
||||
break;
|
||||
case (network::regtest):
|
||||
hrp = "bcrt";
|
||||
byte_version = address_types::TESTNET_SCRIPT;
|
||||
break;
|
||||
}
|
||||
fc::sha256 sh = fc::sha256::hash(&redeem_script_[0], redeem_script_.size());
|
||||
std::vector<uint8_t> hash_data(sh.data(), sh.data() + sh.data_size());
|
||||
address = segwit_addr::encode(hrp, 0, hash_data);
|
||||
|
||||
if (type == payment_type::P2WSH) {
|
||||
fc::sha256 sh = fc::sha256::hash(&redeem_script_[0], redeem_script_.size());
|
||||
std::vector<uint8_t> hash_data(sh.data(), sh.data() + sh.data_size());
|
||||
address = segwit_addr::encode(hrp, 0, hash_data);
|
||||
} else if (type == payment_type::P2SH_WSH) {
|
||||
fc::sha256 hash256 = fc::sha256::hash(&witness_script_[0], witness_script_.size());
|
||||
fc::ripemd160 hash160 = fc::ripemd160::hash(hash256.data(), hash256.data_size());
|
||||
raw_address = bytes(hash160.data(), hash160.data() + hash160.data_size());
|
||||
bytes address_bytes(1, byte_version); // 1 byte version
|
||||
address_bytes.insert(address_bytes.end(), raw_address.begin(), raw_address.end());
|
||||
fc::sha256 hash256_1 = fc::sha256::hash(fc::sha256::hash(address_bytes.data(), address_bytes.size()));
|
||||
address_bytes.insert(address_bytes.end(), hash256_1.data(), hash256_1.data() + 4); // 4 byte checksum
|
||||
address = fc::to_base58(address_bytes);
|
||||
} else {
|
||||
wlog("Unsupported payment type of address");
|
||||
}
|
||||
}
|
||||
|
||||
btc_one_or_m_of_n_multisig_address::btc_one_or_m_of_n_multisig_address(const fc::ecc::public_key &user_key_data,
|
||||
|
|
@ -353,12 +370,12 @@ void btc_one_or_m_of_n_multisig_address::create_segwit_address() {
|
|||
|
||||
btc_one_or_weighted_multisig_address::btc_one_or_weighted_multisig_address(const fc::ecc::public_key &user_key_data,
|
||||
const std::vector<std::pair<fc::ecc::public_key, uint16_t>> &keys_data,
|
||||
bitcoin_address::network ntype) {
|
||||
bitcoin_address::network ntype, payment_type type) {
|
||||
network_type = ntype;
|
||||
this->type = type;
|
||||
create_redeem_script(user_key_data, keys_data);
|
||||
create_witness_script();
|
||||
create_segwit_address();
|
||||
type = payment_type::P2WSH;
|
||||
}
|
||||
|
||||
void btc_one_or_weighted_multisig_address::create_redeem_script(const fc::ecc::public_key &user_key_data, const std::vector<std::pair<fc::ecc::public_key, uint16_t>> &keys_data) {
|
||||
|
|
@ -398,20 +415,39 @@ void btc_one_or_weighted_multisig_address::create_witness_script() {
|
|||
|
||||
void btc_one_or_weighted_multisig_address::create_segwit_address() {
|
||||
std::string hrp;
|
||||
address_types byte_version;
|
||||
switch (network_type) {
|
||||
case (network::mainnet):
|
||||
byte_version = address_types::MAINNET_SCRIPT;
|
||||
hrp = "bc";
|
||||
break;
|
||||
case (network::testnet):
|
||||
byte_version = address_types::TESTNET_SCRIPT;
|
||||
hrp = "tb";
|
||||
break;
|
||||
case (network::regtest):
|
||||
byte_version = address_types::TESTNET_SCRIPT;
|
||||
hrp = "bcrt";
|
||||
break;
|
||||
}
|
||||
fc::sha256 sh = fc::sha256::hash(&redeem_script_[0], redeem_script_.size());
|
||||
std::vector<uint8_t> hash_data(sh.data(), sh.data() + sh.data_size());
|
||||
address = segwit_addr::encode(hrp, 0, hash_data);
|
||||
|
||||
if (type == payment_type::P2WSH) {
|
||||
fc::sha256 sh = fc::sha256::hash(&redeem_script_[0], redeem_script_.size());
|
||||
std::vector<uint8_t> hash_data(sh.data(), sh.data() + sh.data_size());
|
||||
address = segwit_addr::encode(hrp, 0, hash_data);
|
||||
} else if (type == payment_type::P2SH_WSH) {
|
||||
fc::sha256 hash256 = fc::sha256::hash(&witness_script_[0], witness_script_.size());
|
||||
fc::ripemd160 hash160 = fc::ripemd160::hash(hash256.data(), hash256.data_size());
|
||||
raw_address = bytes(hash160.data(), hash160.data() + hash160.data_size());
|
||||
|
||||
bytes address_bytes(1, byte_version); // 1 byte version test net
|
||||
address_bytes.insert(address_bytes.end(), raw_address.begin(), raw_address.end());
|
||||
fc::sha256 hash256_1 = fc::sha256::hash(fc::sha256::hash(address_bytes.data(), address_bytes.size()));
|
||||
address_bytes.insert(address_bytes.end(), hash256_1.data(), hash256_1.data() + 4); // 4 byte checksum
|
||||
address = fc::to_base58(address_bytes);
|
||||
} else {
|
||||
elog("Unsupported payment type of address");
|
||||
}
|
||||
}
|
||||
|
||||
btc_timelocked_one_or_weighted_multisig_address::btc_timelocked_one_or_weighted_multisig_address(const fc::ecc::public_key &user_key_data, uint32_t latency, const std::vector<std::pair<fc::ecc::public_key, uint16_t>> &keys_data, bitcoin_address::network ntype) :
|
||||
|
|
|
|||
|
|
@ -8,6 +8,14 @@ using namespace graphene::chain;
|
|||
namespace graphene { namespace peerplays_sidechain { namespace bitcoin {
|
||||
|
||||
const bytes op_num = {0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f}; // OP_1 - OP_15
|
||||
enum address_types { MAINNET_SCRIPT = 5,
|
||||
TESTNET_SCRIPT = 196 };
|
||||
|
||||
enum script_op {
|
||||
OP_0 = 0x00,
|
||||
OP_PUSH = 0x20,
|
||||
OP_SIZE_34 = 0x22
|
||||
};
|
||||
|
||||
class bitcoin_address {
|
||||
|
||||
|
|
@ -96,9 +104,6 @@ private:
|
|||
void create_address();
|
||||
|
||||
public:
|
||||
enum address_types { MAINNET_SCRIPT = 5,
|
||||
TESTNET_SCRIPT = 196 };
|
||||
|
||||
enum { OP_0 = 0x00,
|
||||
OP_EQUAL = 0x87,
|
||||
OP_HASH160 = 0xa9,
|
||||
|
|
@ -145,7 +150,7 @@ public:
|
|||
btc_weighted_multisig_address() = default;
|
||||
|
||||
btc_weighted_multisig_address(const std::vector<std::pair<fc::ecc::public_key, uint16_t>> &keys_data,
|
||||
network network_type = network::regtest);
|
||||
network network_type = network::regtest, payment_type type = payment_type::P2SH_WSH);
|
||||
|
||||
bytes get_redeem_script() const {
|
||||
return redeem_script_;
|
||||
|
|
@ -190,7 +195,7 @@ class btc_one_or_weighted_multisig_address : public bitcoin_address {
|
|||
public:
|
||||
btc_one_or_weighted_multisig_address() = default;
|
||||
btc_one_or_weighted_multisig_address(const fc::ecc::public_key &user_key_data, const std::vector<std::pair<fc::ecc::public_key, uint16_t>> &keys_data,
|
||||
network network_type = network::regtest);
|
||||
network network_type = network::regtest, payment_type type = payment_type::P2SH_WSH);
|
||||
bytes get_redeem_script() const {
|
||||
return redeem_script_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ protected:
|
|||
sidechain_type sidechain;
|
||||
|
||||
bool debug_rpc_calls;
|
||||
bool use_p2wsh_address;
|
||||
|
||||
std::map<std::string, std::string> private_keys;
|
||||
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options(
|
|||
cli.add_options()("sidechain-retry-threshold", bpo::value<uint16_t>()->default_value(150), "Sidechain retry throttling threshold");
|
||||
|
||||
cli.add_options()("debug-rpc-calls", bpo::value<bool>()->default_value(false), "Outputs RPC calls to console");
|
||||
cli.add_options()("use-p2wsh-address", bpo::value<bool>()->default_value(false), "Use p2wsh address instead of p2sh address");
|
||||
|
||||
cli.add_options()("bitcoin-sidechain-enabled", bpo::value<bool>()->default_value(false), "Bitcoin sidechain handler enabled");
|
||||
cli.add_options()("bitcoin-node-ip", bpo::value<string>()->default_value("127.0.0.1"), "IP address of Bitcoin node");
|
||||
|
|
|
|||
|
|
@ -329,6 +329,10 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
|
|||
debug_rpc_calls = options.at("debug-rpc-calls").as<bool>();
|
||||
}
|
||||
|
||||
if (options.count("use-p2wsh-address")) {
|
||||
use_p2wsh_address = options.at("use-p2wsh-address").as<bool>();
|
||||
}
|
||||
|
||||
ip = options.at("bitcoin-node-ip").as<std::string>();
|
||||
zmq_port = options.at("bitcoin-node-zmq-port").as<uint32_t>();
|
||||
rpc_port = options.at("bitcoin-node-rpc-port").as<uint32_t>();
|
||||
|
|
@ -793,7 +797,12 @@ void sidechain_net_handler_bitcoin::process_sidechain_addresses() {
|
|||
if (sao.expires == time_point_sec::maximum()) {
|
||||
auto usr_pubkey = fc::ecc::public_key(create_public_key_data(parse_hex(sao.deposit_public_key)));
|
||||
|
||||
btc_one_or_weighted_multisig_address addr(usr_pubkey, pubkeys, network_type);
|
||||
payment_type payment_type_address = payment_type::P2SH_WSH;
|
||||
if (use_p2wsh_address) {
|
||||
payment_type_address = payment_type::P2WSH;
|
||||
}
|
||||
|
||||
btc_one_or_weighted_multisig_address addr(usr_pubkey, pubkeys, network_type, payment_type_address);
|
||||
std::string address_data = "{ \"redeemScript\": \"" + fc::to_hex(addr.get_redeem_script()) +
|
||||
"\", \"witnessScript\": \"" + fc::to_hex(addr.get_witness_script()) + "\" }";
|
||||
|
||||
|
|
@ -953,7 +962,13 @@ bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain
|
|||
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(si.public_key)));
|
||||
pubkey_weights.push_back(std::make_pair(pub_key, si.weight));
|
||||
}
|
||||
btc_weighted_multisig_address addr(pubkey_weights, network_type);
|
||||
|
||||
payment_type payment_type_address = payment_type::P2SH_WSH;
|
||||
if (use_p2wsh_address) {
|
||||
payment_type_address = payment_type::P2WSH;
|
||||
}
|
||||
|
||||
btc_weighted_multisig_address addr(pubkey_weights, network_type, payment_type_address);
|
||||
|
||||
std::string tx_txid = tx_json.get<std::string>("result.txid");
|
||||
uint32_t tx_confirmations = tx_json.get<uint32_t>("result.confirmations");
|
||||
|
|
@ -1003,7 +1018,11 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_address(const s
|
|||
pubkey_weights.push_back(std::make_pair(pub_key, son.weight));
|
||||
}
|
||||
|
||||
btc_weighted_multisig_address addr(pubkey_weights, network_type);
|
||||
payment_type payment_type_address = payment_type::P2SH_WSH;
|
||||
if (use_p2wsh_address) {
|
||||
payment_type_address = payment_type::P2WSH;
|
||||
}
|
||||
btc_weighted_multisig_address addr(pubkey_weights, network_type, payment_type_address);
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
|
|
@ -1239,6 +1258,18 @@ std::string sidechain_net_handler_bitcoin::send_transaction(const sidechain_tran
|
|||
}
|
||||
// Add redeemscripts to vins and make tx ready for sending
|
||||
sign_witness_transaction_finalize(tx, redeem_scripts, false);
|
||||
|
||||
if (!use_p2wsh_address) {
|
||||
// get witness script from redeem script
|
||||
bitcoin::bytes redeem_bytes = parse_hex(redeem_script);
|
||||
fc::sha256 sha = fc::sha256::hash(&redeem_bytes[0], redeem_bytes.size());
|
||||
std::string witness_script(sha.str());
|
||||
witness_script.insert(0, std::string("220020"));
|
||||
for (size_t i = 0; i < tx.vin.size(); i++) {
|
||||
tx.vin[i].scriptSig = parse_hex(witness_script);
|
||||
}
|
||||
}
|
||||
|
||||
std::string final_tx_hex = fc::to_hex(pack(tx));
|
||||
std::string res = bitcoin_client->sendrawtransaction(final_tx_hex);
|
||||
|
||||
|
|
@ -1309,7 +1340,13 @@ std::string sidechain_net_handler_bitcoin::get_redeemscript_for_userdeposit(cons
|
|||
pubkey_weights.push_back(std::make_pair(pub_key, son.weight));
|
||||
}
|
||||
auto user_pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(addr_itr->deposit_public_key)));
|
||||
btc_one_or_weighted_multisig_address deposit_addr(user_pub_key, pubkey_weights, network_type);
|
||||
|
||||
payment_type payment_type_address = payment_type::P2SH_WSH;
|
||||
if (use_p2wsh_address) {
|
||||
payment_type_address = payment_type::P2WSH;
|
||||
}
|
||||
btc_one_or_weighted_multisig_address deposit_addr(user_pub_key, pubkey_weights, network_type, payment_type_address);
|
||||
|
||||
return fc::to_hex(deposit_addr.get_redeem_script());
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue