Add signing and verification tests and sign_transaction_standalone

This commit is contained in:
satyakoneru 2020-04-14 16:41:43 +00:00
parent b08d34d62f
commit 73e0673199
7 changed files with 233 additions and 4 deletions

View file

@ -3,6 +3,12 @@
namespace graphene { namespace peerplays_sidechain { namespace bitcoin {
const secp256k1_context_t *btc_context()
{
static secp256k1_context_t *ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
return ctx;
}
fc::sha256 get_signature_hash( const bitcoin_transaction& tx, const bytes& scriptCode, int64_t amount,
size_t in_index, int hash_type, bool is_witness )
{

View file

@ -1,7 +1,25 @@
#include <graphene/peerplays_sidechain/bitcoin/utils.hpp>
#include <fc/crypto/base58.hpp>
namespace graphene { namespace peerplays_sidechain { namespace bitcoin {
fc::ecc::public_key_data create_public_key_data( const std::vector<char>& public_key )
{
FC_ASSERT( public_key.size() == 33 );
fc::ecc::public_key_data key;
for(size_t i = 0; i < 33; i++) {
key.at(i) = public_key[i];
}
return key;
}
bytes get_privkey_bytes( const std::string& privkey_base58 )
{
const auto privkey = fc::from_base58( privkey_base58 );
// Remove version and hash
return bytes( privkey.cbegin() + 1, privkey.cbegin() + 1 + 32 );
}
bytes parse_hex( const std::string& str )
{
bytes vec( str.size() / 2 );

View file

@ -8,6 +8,8 @@ namespace graphene { namespace peerplays_sidechain { namespace bitcoin {
class bitcoin_transaction;
const secp256k1_context_t *btc_context();
fc::sha256 get_signature_hash( const bitcoin_transaction& tx, const bytes& scriptPubKey, int64_t amount,
size_t in_index, int hash_type, bool is_witness );
@ -24,4 +26,4 @@ bool verify_sig( const bytes& sig, const bytes& pubkey, const bytes& msg, const
std::vector<std::vector<bytes>> sort_sigs( const bitcoin_transaction& tx, const std::vector<bytes>& redeem_scripts,
const std::vector<uint64_t>& amounts, const secp256k1_context_t* context );
} } }
} } }

View file

@ -5,6 +5,10 @@
namespace graphene { namespace peerplays_sidechain { namespace bitcoin {
fc::ecc::public_key_data create_public_key_data( const std::vector<char>& public_key );
bytes get_privkey_bytes( const std::string& privkey_base58 );
bytes parse_hex( const std::string& str );
std::vector<bytes> get_pubkey_from_redeemScript( bytes script );

View file

@ -17,6 +17,7 @@
#include <graphene/chain/son_wallet_object.hpp>
#include <graphene/peerplays_sidechain/bitcoin/bitcoin_transaction.hpp>
#include <graphene/peerplays_sidechain/bitcoin/serialize.hpp>
#include <graphene/peerplays_sidechain/bitcoin/sign_bitcoin_transaction.hpp>
namespace graphene { namespace peerplays_sidechain {
@ -1435,7 +1436,7 @@ std::vector<std::vector<unsigned char>> read_byte_arrays_from_string(const std::
return data;
}
std::string write_byte_arrays_to_string(const std::vector<std::vector<unsigned char>>& data)
std::string write_byte_arrays_to_string(const std::vector<bitcoin::bytes>& data)
{
std::string res = "[";
for (unsigned int idx = 0; idx < data.size(); ++idx) {
@ -1461,6 +1462,17 @@ void read_tx_data_from_string(const std::string &string_buf, std::vector<unsigne
in_amounts.push_back(fc::to_uint64(v.second.data()));
}
void read_tx_data_from_string(const std::string &string_buf, std::string &tx_hex, std::vector<uint64_t> &in_amounts)
{
std::stringstream ss(string_buf);
boost::property_tree::ptree json;
boost::property_tree::read_json(ss, json);
tx_hex = json.get<std::string>("tx_hex");
in_amounts.clear();
for(auto &v: json.get_child("in_amounts"))
in_amounts.push_back(fc::to_uint64(v.second.data()));
}
std::string save_tx_data_to_string(const std::vector<unsigned char> &tx, const std::vector<uint64_t> &in_amounts)
{
std::string res = "{\"tx_hex\":\"" + fc::to_hex((const char*)&tx[0], tx.size()) + "\",\"in_amounts\":[";
@ -1669,9 +1681,36 @@ std::string sidechain_net_handler_bitcoin::sign_transaction_psbt(const sidechain
std::string sidechain_net_handler_bitcoin::sign_transaction_standalone(const sidechain_transaction_object &sto) {
std::string pubkey = plugin.get_current_son_object().sidechain_public_keys.at(sidechain);
std::string prvkey = get_private_key(pubkey);
using namespace bitcoin;
std::vector<uint64_t> in_amounts;
std::string tx_hex;
return "";
const auto privkey_signing = get_privkey_bytes( prvkey );
read_tx_data_from_string(sto.transaction, tx_hex, in_amounts);
accounts_keys son_pubkeys;
for (auto& son: sto.signers) {
std::string pub_key = son.sidechain_public_keys.at(sidechain_type::bitcoin);
son_pubkeys[son.son_id] = create_public_key_data( parse_hex(pub_key) );
}
uint32_t nrequired = sto.signers.size() * 2 / 3 + 1;
btc_multisig_segwit_address pw_address(nrequired, son_pubkeys);
bitcoin_transaction tx = unpack(parse_hex(tx_hex));
bitcoin::bytes rscript = pw_address.get_redeem_script();
std::vector<bitcoin::bytes> redeem_scripts(tx.vin.size(), rscript);
auto sigs = sign_witness_transaction_part( tx, redeem_scripts, in_amounts, privkey_signing, btc_context(), 1 );
std::string tx_signature = write_byte_arrays_to_string(sigs);
wlog("skoneru: signatures: ${s}", ("s", tx_signature));
return tx_signature;
}
std::string sidechain_net_handler_bitcoin::send_transaction_raw(const sidechain_transaction_object &sto) {

View file

@ -149,6 +149,7 @@ BOOST_AUTO_TEST_CASE( create_segwit_address_10_of_14_test )
std::vector<char> public_key14 = parse_hex( "0287bcbd4f5d357f89a86979b386402445d7e9a5dccfd16146d1d2ab0dc2c32ae8" );
std::vector<char> witness_script = parse_hex("0020b70a52b55974d3c8c1a2055bf23e2d6421942135c7be1f786ad8cbce2f532cef");
std::vector<char> redeem_script = parse_hex("5a2103456772301e221026269d3095ab5cb623fc239835b583ae4632f99a15107ef2752102d67c26cf20153fe7625ca1454222d3b3aeb53b122d8a0f7d32a3dd4b2c2016f421025f7cfda933516fd590c5a34ad4a68e3143b6f4155a64b3aab2c55fb851150f61210228155bb1ddcd11c7f14a2752565178023aa963f84ea6b6a052bddebad6fe986621037500441cfb4484da377073459511823b344f1ef0d46bac1efd4c7c466746f6662102ef0d79bfdb99ab0be674b1d5d06c24debd74bffdc28d466633d6668cc281cccf210317941e4219548682fb8d8e172f0a8ce4d83ce21272435c85d598558c8e060b7f210266065b27f7e3d3ad45b471b1cd4e02de73fc4737dc2679915a45e293c5adcf8421023821cc3da7be9e8cdceb8f146e9ddd78a9519875ecc5b42fe645af690544bccf210229ff2b2106b76c27c393e82d71c20eec32bcf1f0cf1a9aca8a237269a67ff3e521024d113381cc09deb8a6da62e0470644d1a06de82be2725b5052668c8845a4a8da2103df2462a5a2f681a3896f61964a65566ff77448be9a55a6da18506fd9c6c051c12102bafba3096f546cc5831ce1e49ba7142478a659f2d689bbc70ed37235255172a8210287bcbd4f5d357f89a86979b386402445d7e9a5dccfd16146d1d2ab0dc2c32ae85eae");
fc::ecc::public_key_data key1 = create_public_key_data( public_key1 );
fc::ecc::public_key_data key2 = create_public_key_data( public_key2 );
@ -170,6 +171,7 @@ BOOST_AUTO_TEST_CASE( create_segwit_address_10_of_14_test )
{ son_id_type(8), public_key_type(key8) }, { son_id_type(9), public_key_type(key9) }, { son_id_type(10), public_key_type(key10) }, { son_id_type(11), public_key_type(key11) },
{ son_id_type(12), public_key_type(key12) }, { son_id_type(13), public_key_type(key13) }, { son_id_type(14), public_key_type(key14) },});
BOOST_CHECK( address.get_witness_script() == witness_script );
BOOST_CHECK( address.get_redeem_script() == redeem_script );
BOOST_CHECK( address.get_address() == "2MwhYhBrZeb6mTf1kaWcYfLBCCQoMqQybFZ" );
}

File diff suppressed because one or more lines are too long