Merge branch 'master' of github.com:cryptonomex/graphene

This commit is contained in:
Daniel Larimer 2015-10-09 16:31:44 -04:00
commit 31502d1959
5 changed files with 180 additions and 40 deletions

View file

@ -520,8 +520,6 @@ void_result asset_publish_feeds_evaluator::do_evaluate(const asset_publish_feed_
{
FC_ASSERT(o.feed.settlement_price.quote.asset_id == bitasset.options.short_backing_asset);
bool is_nop = false;
try
{
// these two changes should go in price_feed::validate() when creating new network
@ -559,7 +557,6 @@ void_result asset_publish_feeds_evaluator::do_evaluate(const asset_publish_feed_
("n", d.head_block_num()+1)
("name", o.publisher(d).name)
);
is_nop = true;
}
}
catch( const fc::exception& e )

View file

@ -575,10 +575,10 @@ class wallet_api
bool import_account_keys( string filename, string password, string src_account_name, string dest_account_name );
/**
* This call will construct a transaction that will claim all balances controled
* This call will construct transaction(s) that will claim all balances controled
* by wif_keys and deposit them into the given account.
*/
signed_transaction import_balance( string account_name_or_id, const vector<string>& wif_keys, bool broadcast );
vector< signed_transaction > import_balance( string account_name_or_id, const vector<string>& wif_keys, bool broadcast );
/** Transforms a brain key to reduce the chance of errors when re-entering the key from memory.
*

View file

@ -624,7 +624,7 @@ public:
{
fc::optional<fc::ecc::private_key> optional_private_key = wif_to_key(wif_key);
if (!optional_private_key)
FC_THROW("Invalid private key ${key}", ("key", wif_key));
FC_THROW("Invalid private key");
graphene::chain::public_key_type wif_pub_key = optional_private_key->get_public_key();
account_object account = get_account( account_name_or_id );
@ -646,6 +646,8 @@ public:
return all_keys_for_account.find(wif_pub_key) != all_keys_for_account.end();
}
vector< signed_transaction > import_balance( string name_or_id, const vector<string>& wif_keys, bool broadcast );
bool load_wallet_file(string wallet_filename = "")
{
// TODO: Merge imported wallet with existing wallet,
@ -2571,7 +2573,7 @@ bool wallet_api::import_key(string account_name_or_id, string wif_key)
// backup wallet
fc::optional<fc::ecc::private_key> optional_private_key = wif_to_key(wif_key);
if (!optional_private_key)
FC_THROW("Invalid private key ${key}", ("key", wif_key));
FC_THROW("Invalid private key");
string shorthash = detail::address_to_shorthash(optional_private_key->get_public_key());
copy_wallet_file( "before-import-key-" + shorthash );
@ -2626,14 +2628,28 @@ map<string, bool> wallet_api::import_accounts( string filename, string password
if( should_proceed )
{
uint32_t import_successes = 0;
uint32_t import_failures = 0;
// TODO: First check that all private keys match public keys
for( const auto& encrypted_key : item.encrypted_private_keys )
{
const auto plain_text = fc::aes_decrypt( password_hash, encrypted_key );
const auto private_key = fc::raw::unpack<private_key_type>( plain_text );
try
{
const auto plain_text = fc::aes_decrypt( password_hash, encrypted_key );
const auto private_key = fc::raw::unpack<private_key_type>( plain_text );
import_key( item.account_name, string( graphene::utilities::key_to_wif( private_key ) ) );
import_key( item.account_name, string( graphene::utilities::key_to_wif( private_key ) ) );
++import_successes;
}
catch( const fc::exception& e )
{
elog( "Couldn't import key due to exception ${e}", ("e", e.to_detail_string()) );
++import_failures;
}
}
ilog( "successfully imported ${n} keys for account ${name}", ("n", import_successes)("name", item.account_name) );
if( import_failures > 0 )
elog( "failed to import ${n} keys for account ${name}", ("n", import_failures)("name", item.account_name) );
}
}
@ -3119,65 +3135,117 @@ void wallet_api::set_password( string password )
lock();
}
signed_transaction wallet_api::import_balance( string name_or_id, const vector<string>& wif_keys, bool broadcast )
vector< signed_transaction > wallet_api::import_balance( string name_or_id, const vector<string>& wif_keys, bool broadcast )
{
return my->import_balance( name_or_id, wif_keys, broadcast );
}
namespace detail {
vector< signed_transaction > wallet_api_impl::import_balance( string name_or_id, const vector<string>& wif_keys, bool broadcast )
{ try {
FC_ASSERT(!is_locked());
const dynamic_global_property_object& dpo = _remote_db->get_dynamic_global_properties();
account_object claimer = get_account( name_or_id );
uint32_t max_ops_per_tx = 30;
vector<address> addrs;
map<address,private_key_type> keys;
for( auto wif_key : wif_keys )
map< address, private_key_type > keys; // local index of address -> private key
vector< address > addrs;
bool has_wildcard = false;
addrs.reserve( wif_keys.size() );
for( const string& wif_key : wif_keys )
{
auto priv_key = wif_to_key(wif_key);
FC_ASSERT( priv_key, "Invalid Private Key", ("key",wif_key) );
addrs.push_back( priv_key->get_public_key() );
keys[addrs.back()] = *priv_key;
if( wif_key == "*" )
{
if( has_wildcard )
continue;
for( const public_key_type& pub : _wallet.extra_keys[ claimer.id ] )
{
addrs.push_back( pub );
auto it = _keys.find( pub );
if( it != _keys.end() )
{
fc::optional< fc::ecc::private_key > privkey = wif_to_key( it->second );
FC_ASSERT( privkey );
keys[ addrs.back() ] = *privkey;
}
else
{
wlog( "Somehow _keys has no private key for extra_keys public key ${k}", ("k", pub) );
}
}
has_wildcard = true;
}
else
{
optional< private_key_type > key = wif_to_key( wif_key );
FC_ASSERT( key.valid(), "Invalid private key" );
addrs.push_back( key->get_public_key() );
keys[addrs.back()] = *key;
}
}
auto balances = my->_remote_db->get_balance_objects( addrs );
vector< balance_object > balances = _remote_db->get_balance_objects( addrs );
wdump((balances));
addrs.clear();
set<asset_id_type> bal_types;
for( auto b : balances ) bal_types.insert( b.balance.asset_id );
set<address> required_addrs;
signed_transaction trx;
for( auto a : bal_types )
struct claim_tx
{
vector< balance_claim_operation > ops;
set< address > addrs;
};
vector< claim_tx > claim_txs;
for( const asset_id_type& a : bal_types )
{
balance_claim_operation op;
op.deposit_to_account = claimer.id;
for( const auto& b : balances )
for( const balance_object& b : balances )
{
if( b.balance.asset_id == a )
{
op.total_claimed = b.vesting_policy.valid()? asset(0, b.balance.asset_id) : b.balance;
op.total_claimed = b.available( dpo.time );
if( op.total_claimed.amount == 0 )
continue;
op.balance_to_claim = b.id;
op.balance_owner_key = keys[b.owner].get_public_key();
trx.operations.push_back(op);
required_addrs.insert(b.owner);
if( (claim_txs.empty()) || (claim_txs.back().ops.size() >= max_ops_per_tx) )
claim_txs.emplace_back();
claim_txs.back().ops.push_back(op);
claim_txs.back().addrs.insert(b.owner);
}
}
}
my->set_operation_fees( trx, my->_remote_db->get_global_properties().parameters.current_fees );
trx.validate();
vector< signed_transaction > result;
auto tx = sign_transaction( trx, false );
for( auto a : required_addrs )
tx.sign( keys[a], my->_chain_id );
for( const claim_tx& ctx : claim_txs )
{
signed_transaction tx;
tx.operations.reserve( ctx.ops.size() );
for( const balance_claim_operation& op : ctx.ops )
tx.operations.emplace_back( op );
set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees );
tx.validate();
signed_transaction signed_tx = sign_transaction( tx, false );
for( const address& addr : ctx.addrs )
signed_tx.sign( keys[addr], _chain_id );
// if the key for a balance object was the same as a key for the account we're importing it into,
// we may end up with duplicate signatures, so remove those
boost::erase(signed_tx.signatures, boost::unique<boost::return_found_end>(boost::sort(signed_tx.signatures)));
result.push_back( signed_tx );
if( broadcast )
_remote_net_broadcast->broadcast_transaction(signed_tx);
}
// if the key for a balance object was the same as a key for the account we're importing it into,
// we may end up with duplicate signatures, so remove those
boost::erase(tx.signatures, boost::unique<boost::return_found_end>(boost::sort(tx.signatures)));
if( broadcast )
my->_remote_net_broadcast->broadcast_transaction(tx);
return tx;
return result;
} FC_CAPTURE_AND_RETHROW( (name_or_id) ) }
}
map<public_key_type, string> wallet_api::dump_private_keys()
{
FC_ASSERT(!is_locked());

View file

@ -0,0 +1,14 @@
#!/usr/bin/env python3
import argparse
import json
import sys
if len(sys.argv) < 3:
print("syntax: "+sys.argv[0]+" INFILE OUTFILE")
sys.exit(0)
with open(sys.argv[1], "r") as infile:
genesis = json.load(infile)
with open(sys.argv[2], "w") as outfile:
json.dump(genesis, outfile, indent=2, sort_keys=True)

View file

@ -0,0 +1,61 @@
#!/usr/bin/env python3
import argparse
import json
import re
import sys
def dump_json(obj, out, pretty):
if pretty:
json.dump(obj, out, indent=2, sort_keys=True)
else:
json.dump(obj, out, separators=(",", ":"), sort_keys=True)
return
re_init = re.compile(r"^init[0-9]+$")
def load_names(infile):
names = set()
for line in infile:
if '#' in line:
line = line[:line.index('#')]
line = line.strip()
if line == "":
continue
names.add(line)
return names
def main():
parser = argparse.ArgumentParser(description="Remove entities from snapshot")
parser.add_argument("-o", "--output", metavar="OUT", default="-", help="output filename (default: stdout)")
parser.add_argument("-i", "--input", metavar="IN", default="-", help="input filename (default: stdin)")
parser.add_argument("-n", "--names", metavar="NAMES", default="", help="file containing names to upgrade")
parser.add_argument("-p", "--pretty", action="store_true", default=False, help="pretty print output")
opts = parser.parse_args()
if opts.input == "-":
genesis = json.load(sys.stdin)
else:
with open(opts.input, "r") as f:
genesis = json.load(f)
if opts.names == "-":
names = load_names(sys.stdin)
else:
with open(opts.names, "r") as f:
names = load_names(f)
for account in genesis["initial_accounts"]:
if account["name"] in names:
account["is_lifetime_member"] = True
if opts.output == "-":
dump_json( genesis, sys.stdout, opts.pretty )
sys.stdout.flush()
else:
with open(opts.output, "w") as f:
dump_json( genesis, f, opts.pretty )
return
if __name__ == "__main__":
main()