Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue867 Add CLI command to add signatures to a partially signed transaction #1032

Merged
merged 32 commits into from
Mar 13, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e90e9b1
#867, Add CLI command to add signatures to a partially signed transac…
windycrypto May 30, 2018
c170491
add offline transaction signing method
windycrypto Jun 3, 2018
1b29437
rough implementation of multi-sig transaction
windycrypto Jun 7, 2018
a218ef6
make filename optional on multisig_mode command
windycrypto Jun 7, 2018
dcd7150
validate TaPoS and expiration field for imported transaction
windycrypto Jun 7, 2018
47569a0
simplify implementation according to Peter's reviews
windycrypto Jun 12, 2018
dc265ab
make variable name clearer
windycrypto Jun 13, 2018
efff736
simplify again according to Peter's reviews
windycrypto Jun 13, 2018
c4d598e
correct grammer and revert unrelated code style changes
windycrypto Jun 13, 2018
c0207fc
validate TaPoS and expiration field and change error level so looks m…
windycrypto Jun 13, 2018
4a10ecc
#867, Add CLI command to add signatures to a partially signed transac…
windycrypto May 30, 2018
7cb7519
add offline transaction signing method
windycrypto Jun 3, 2018
8652bd3
rough implementation of multi-sig transaction
windycrypto Jun 7, 2018
35597c9
make filename optional on multisig_mode command
windycrypto Jun 7, 2018
a616f51
validate TaPoS and expiration field for imported transaction
windycrypto Jun 7, 2018
0ccf3e7
simplify implementation according to Peter's reviews
windycrypto Jun 12, 2018
c27c975
make variable name clearer
windycrypto Jun 13, 2018
8e99d7c
simplify again according to Peter's reviews
windycrypto Jun 13, 2018
8074954
correct grammer and revert unrelated code style changes
windycrypto Jun 13, 2018
e099865
validate TaPoS and expiration field and change error level so looks m…
windycrypto Jun 13, 2018
0c2a7dd
Add test cases and remove unneeded field check
windycrypto Jun 16, 2018
edf3291
partially updated per to Peter's review
windycrypto Jun 18, 2018
5ad1612
fixed the logic of wether a private key had signed the transaction
windycrypto Jun 19, 2018
777cf13
use private keys in wallet instead of param list and fill TaPoS/expir…
windycrypto Jun 22, 2018
3a39938
extend expiration and remove dupe check
windycrypto Jun 24, 2018
f61cb75
get max transaction expiration time from global property object
windycrypto Jul 22, 2018
0a30317
fix transaction expiration to absolute time from now
windycrypto Jul 24, 2018
3ca48dd
Merge branch 'issue867' of https://github.com/cifer-lee/bitshares-cor…
windycrypto Oct 9, 2018
6cf8fed
refactor redundent codes and change name to sign_transaction2
windycrypto Oct 9, 2018
e3a3f25
Fix issues according to review comments
Feb 16, 2019
ba463f1
Merge branch 'develop' into issue867
Feb 16, 2019
26ffeef
Merge branch 'develop' into issue867
Mar 4, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions libraries/wallet/include/graphene/wallet/wallet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,9 @@ struct vesting_balance_object_with_info : public vesting_balance_object
fc::time_point_sec allowed_withdraw_time;
};

namespace detail {
class wallet_api_impl;
namespace detail
{
class wallet_api_impl;
}

/***
Expand Down Expand Up @@ -1538,6 +1539,11 @@ class wallet_api

order_book get_order_book( const string& base, const string& quote, unsigned limit = 50);

bool multisig_mode(string on_or_off, fc::optional<string> tx_filename);
optional<signed_transaction> multisig_import_transaction( string tx_filename );
signed_transaction multisig_sign_transaction( const vector<string> &wif_keys,
bool broadcast = false );

void dbg_make_uia(string creator, string symbol);
void dbg_make_mia(string creator, string symbol);
void dbg_push_blocks( std::string src_filename, uint32_t count );
Expand Down Expand Up @@ -1751,4 +1757,7 @@ FC_API( graphene::wallet::wallet_api,
(blind_history)
(receive_blind_transfer)
(get_order_book)
(multisig_mode)
(multisig_import_transaction)
(multisig_sign_transaction)
)
150 changes: 150 additions & 0 deletions libraries/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,131 @@ class wallet_api_impl

return true;
}

bool multisig_mode(string on_or_off, fc::optional<string> tx_filename)
{
if (on_or_off == "on")
{
if (! tx_filename)
FC_THROW("Must provide transaction file name");
else
_tx_filename = *tx_filename;

_multisig_mode = true;
}
else
_multisig_mode = false;

return _multisig_mode;
}

optional<signed_transaction> multisig_import_transaction(string tx_filename)
{
signed_transaction tmp;

if ( !fc::exists( tx_filename ) )
{
elog( "Transaction file not exists" );
windycrypto marked this conversation as resolved.
Show resolved Hide resolved
return optional<signed_transaction>();
}

tmp = fc::json::from_file( tx_filename )
.as<signed_transaction>( 2 * GRAPHENE_MAX_NESTED_OBJECTS );

if ( !tmp.ref_block_num || !tmp.ref_block_prefix || tmp.expiration == fc::time_point_sec() )
{
elog( "Must fill TaPoS and expiration field in online machine" );
return optional<signed_transaction>();
}
else
{
_multisig_trx = tmp;
return _multisig_trx;
}
}

signed_transaction multisig_sign_transaction( const vector<string> &wif_keys, bool broadcast )
{
// use const reference to call the const variant of `sign()`
vector<fc::ecc::private_key> private_keys;

for ( const string &wif_key : wif_keys )
{
fc::optional<fc::ecc::private_key> optional_private_key = wif_to_key( wif_key );

if ( !optional_private_key )
FC_THROW( "Invalid private key: ${i}", ( "i", wif_key ) );

private_keys.push_back(*optional_private_key);
}

for ( const fc::ecc::private_key& privkey : private_keys)
{
signature_type sig = privkey.sign_compact( _multisig_trx.sig_digest( _chain_id ) );
const vector<signature_type> &sigs = _multisig_trx.signatures;
if ( std::find( sigs.begin(), sigs.end(), sig ) != sigs.end() )
windycrypto marked this conversation as resolved.
Show resolved Hide resolved
{
wlog( "signature of ${fn} had already exist, skip", ( "fn", key_to_wif( privkey ) ) );
windycrypto marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
_multisig_trx.sign( privkey, _chain_id );
}
}

if ( broadcast )
{
try
{
_remote_net_broadcast->broadcast_transaction( _multisig_trx );
}
catch ( const fc::exception &e )
{
elog( "Caught exception while broadcasting tx ${id}: ${e}",
( "id", _multisig_trx.id().str() )( "e", e.to_detail_string() ) );
throw;
}
}

return _multisig_trx;
}

void save_transaction_to_file(signed_transaction& tx)
{
//
// Serialize in memory, then save to disk
//
// This approach lessens the risk of a partially written wallet
// if exceptions are thrown in serialization
//

ilog( "saving wallet to file ${fn}", ("fn", _tx_filename) );

string tx_data = fc::json::to_pretty_string( tx );
try
{
enable_umask_protection();
//
// Parentheses on the following declaration fails to compile,
// due to the Most Vexing Parse. Thanks, C++
//
// http://en.wikipedia.org/wiki/Most_vexing_parse
//
fc::ofstream outfile{ fc::path( _tx_filename ) };
outfile.write( tx_data.c_str(), tx_data.length() );
outfile.flush();
outfile.close();
disable_umask_protection();
}
catch(...)
{
disable_umask_protection();
throw;
}

_multisig_trx = tx;
}

void save_wallet_file(string wallet_filename = "")
{
//
Expand Down Expand Up @@ -1860,6 +1985,11 @@ class wallet_api_impl
++expiration_time_offset;
}

if (_multisig_mode)
{
save_transaction_to_file(tx);
}

if( broadcast )
{
try
Expand Down Expand Up @@ -2610,6 +2740,10 @@ class wallet_api_impl
return it->second;
}

bool _multisig_mode = false;
signed_transaction _multisig_trx;
string _tx_filename;

string _wallet_filename;
wallet_data _wallet;

Expand Down Expand Up @@ -3587,6 +3721,22 @@ dynamic_global_property_object wallet_api::get_dynamic_global_properties() const
return my->get_dynamic_global_properties();
}

bool wallet_api::multisig_mode(string on_or_off, fc::optional<string> tx_filename)
{
return my->multisig_mode(on_or_off, tx_filename);
}

optional<signed_transaction> wallet_api::multisig_import_transaction( string tx_filename )
{
return my->multisig_import_transaction( tx_filename );
}

signed_transaction wallet_api::multisig_sign_transaction( const vector<string> &wif_keys,
bool broadcast )
{
return my->multisig_sign_transaction( wif_keys, broadcast );
}

string wallet_api::help()const
{
std::vector<std::string> method_names = my->method_documentation.get_method_names();
Expand Down