diff --git a/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_address.cpp b/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_address.cpp index ed4041b7..b13208b8 100755 --- a/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_address.cpp +++ b/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_address.cpp @@ -372,4 +372,71 @@ void btc_one_or_m_of_n_multisig_address::create_segwit_address() { address = segwit_addr::encode(hrp, 0, hash_data); } +btc_one_or_weighted_multisig_address::btc_one_or_weighted_multisig_address(const fc::ecc::public_key &user_key_data, + const std::vector > &keys_data, + bitcoin_address::network ntype) +{ + network_type = ntype; + 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 > &keys_data) +{ + script_builder builder; + builder << user_key_data.serialize(); + builder << op::CHECKSIG; + builder << op::IF; + builder << op::_1; + builder << op::ELSE; + uint32_t total_weight = 0; + builder << uint32_t(0); + for (auto &p : keys_data) { + total_weight += p.second; + builder << op::SWAP; + builder << p.first.serialize(); + builder << op::CHECKSIG; + builder << op::IF; + builder << uint32_t(p.second); + builder << op::ADD; + builder << op::ENDIF; + } + uint32_t threshold_weight = 2 * total_weight / 3; + builder << threshold_weight; + builder << op::GREATERTHANOREQUAL; + builder << op::ENDIF; + redeem_script_ = builder; + fc::sha256 sh = fc::sha256::hash(redeem_script_); + raw_address = bytes(sh.data(), sh.data() + sh.data_size()); +} + +void btc_one_or_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_one_or_weighted_multisig_address::create_segwit_address() +{ + std::string hrp; + switch (network_type) { + case (network::mainnet): + hrp = "bc"; + break; + case (network::testnet): + hrp = "tb"; + break; + case (network::regtest): + hrp = "bcrt"; + break; + } + fc::sha256 sh = fc::sha256::hash(&redeem_script_[0], redeem_script_.size()); + std::vector hash_data(sh.data(), sh.data() + sh.data_size()); + address = segwit_addr::encode(hrp, 0, hash_data); +} + } } } diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin/bitcoin_address.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin/bitcoin_address.hpp index 9b249347..df467ceb 100755 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin/bitcoin_address.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin/bitcoin_address.hpp @@ -175,6 +175,26 @@ public: bytes witness_script_; }; +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>& keys_data, + network network_type = network::regtest); + bytes get_redeem_script() const { + return redeem_script_; + } + bytes get_witness_script() const { + return witness_script_; + } +private: + void create_redeem_script(const fc::ecc::public_key &user_key_data, const std::vector>& keys_data); + void create_witness_script(); + void create_segwit_address(); +public: + bytes redeem_script_; + bytes witness_script_; +}; + } } } FC_REFLECT_ENUM(graphene::peerplays_sidechain::bitcoin::bitcoin_address::network,