public_key_type wallet_db::generate_new_account( const fc::sha512& password, const string& account_name, const private_key_type& owner_private_key ) { try { FC_ASSERT( is_open() ); owallet_account_record account_record = lookup_account( account_name ); FC_ASSERT( !account_record.valid(), "Wallet already contains an account with that name!" ); const public_key_type owner_public_key = owner_private_key.get_public_key(); const address owner_address = address( owner_public_key ); const private_key_type active_private_key = get_account_child_key( owner_private_key, 0 ); const public_key_type active_public_key = active_private_key.get_public_key(); const address active_address = address( active_public_key ); account_record = lookup_account( owner_address ); FC_ASSERT( !account_record.valid(), "Wallet already contains an account with that key!" ); account_record = lookup_account( active_address ); FC_ASSERT( !account_record.valid(), "Wallet already contains an account with the new derived active key!" ); owallet_key_record key_record = lookup_key( owner_address ); FC_ASSERT( !key_record.valid() || !key_record->has_private_key(), "Wallet already contains that key!" ); key_record = lookup_key( active_address ); FC_ASSERT( !key_record.valid() || !key_record->has_private_key(), "Wallet already contains the new derived active key!" ); key_data active_key; active_key.account_address = owner_address; active_key.public_key = active_public_key; active_key.encrypt_private_key( password, active_private_key ); key_data owner_key; owner_key.account_address = owner_address; owner_key.public_key = owner_public_key; owner_key.encrypt_private_key( password, owner_private_key ); account_data account; account.name = account_name; account.owner_key = owner_public_key; account.set_active_key( blockchain::now(), active_public_key ); account.last_update = blockchain::now(); store_key( active_key ); store_key( owner_key ); store_account( account ); return owner_public_key; } FC_CAPTURE_AND_RETHROW( (account_name) ) }
PrivateKeyType WalletDb::generate_new_account_child_key( const fc::sha512& password, const string& account_name ) { try { FC_ASSERT( is_open() ,"Wallet not open!"); oWalletAccountEntry account_entry = lookup_account( account_name ); FC_ASSERT( account_entry.valid(), "Account not found!" ); FC_ASSERT( !account_entry->is_retracted(), "Account has been retracted!" ); FC_ASSERT( account_entry->is_my_account, "Not my account!" ); const oWalletKeyEntry key_entry = lookup_key( Address( account_entry->active_key() ) ); FC_ASSERT( key_entry.valid(), "Active key not found!" ); FC_ASSERT( key_entry->has_private_key(), "Active private key not found!" ); const PrivateKeyType active_private_key = key_entry->decrypt_private_key( password ); uint32_t seq_num = account_entry->last_used_gen_sequence; PrivateKeyType account_child_private_key; PublicKeyType account_child_public_key; Address account_child_address; while( true ) { ++seq_num; FC_ASSERT( seq_num != 0, "Overflow!" ); account_child_private_key = get_account_child_key( active_private_key, seq_num ); account_child_public_key = account_child_private_key.get_public_key(); account_child_address = Address( account_child_public_key ); oWalletKeyEntry key_entry = lookup_key( account_child_address ); if( key_entry.valid() && key_entry->has_private_key() ) continue; break; } account_entry->last_used_gen_sequence = seq_num; KeyData key; key.account_address = account_entry->owner_address(); key.public_key = account_child_public_key; key.encrypt_private_key( password, account_child_private_key ); key.gen_seq_number = seq_num; store_account( *account_entry ); store_key( key ); return account_child_private_key; } FC_CAPTURE_AND_RETHROW( (account_name) ) }
PublicKeyType WalletDb::generate_new_account( const fc::sha512& password, const string& account_name, const variant& private_data ) { try { FC_ASSERT( is_open() ,"Wallet not open!"); oWalletAccountEntry account_entry = lookup_account( account_name ); FC_ASSERT( !account_entry.valid(), "Wallet already contains an account with that name!" ); uint32_t key_index = get_last_wallet_child_key_index(); PrivateKeyType owner_private_key, active_private_key; PublicKeyType owner_public_key, active_public_key; Address owner_address, active_address; while( true ) { ++key_index; FC_ASSERT( key_index != 0, "Overflow!" ); owner_private_key = get_wallet_child_key( password, key_index ); owner_public_key = owner_private_key.get_public_key(); owner_address = Address( owner_public_key ); account_entry = lookup_account( owner_address ); if( account_entry.valid() ) continue; oWalletKeyEntry key_entry = lookup_key( owner_address ); if( key_entry.valid() && key_entry->has_private_key() ) continue; active_private_key = get_account_child_key( owner_private_key, 0 ); active_public_key = active_private_key.get_public_key(); active_address = Address( active_public_key ); account_entry = lookup_account( active_address ); if( account_entry.valid() ) continue; key_entry = lookup_key( active_address ); if( key_entry.valid() && key_entry->has_private_key() ) continue; break; } KeyData active_key; active_key.account_address = owner_address; active_key.public_key = active_public_key; active_key.encrypt_private_key( password, active_private_key ); KeyData owner_key; owner_key.account_address = owner_address; owner_key.public_key = owner_public_key; owner_key.encrypt_private_key( password, owner_private_key ); owner_key.gen_seq_number = key_index; AccountData account; account.name = account_name; account.owner_key = owner_public_key; account.set_active_key( blockchain::now(), active_public_key ); account.last_update = blockchain::now(); account.is_my_account = true; account.private_data = private_data; store_key( active_key ); set_last_wallet_child_key_index( key_index ); store_key( owner_key ); store_account( account ); return owner_public_key; } FC_CAPTURE_AND_RETHROW( (account_name) ) }
private_key_type wallet_db::generate_new_account_child_key( const fc::sha512& password, const string& account_name, const account_key_type parent_key_type ) { try { FC_ASSERT( is_open() ); owallet_account_record account_record = lookup_account( account_name ); FC_ASSERT( account_record.valid(), "Account not found!" ); FC_ASSERT( !account_record->is_retracted(), "Account has been retracted!" ); public_key_type parent_public_key; switch( parent_key_type ) { case account_key_type::owner_key: parent_public_key = account_record->owner_key; break; case account_key_type::active_key: parent_public_key = account_record->active_key(); break; case account_key_type::signing_key: FC_ASSERT( account_record->is_delegate() ); parent_public_key = account_record->signing_key(); break; // No default to force compiler warning } const owallet_key_record parent_key_record = lookup_key( address( parent_public_key ) ); FC_ASSERT( parent_key_record.valid(), "Parent key not found!" ); FC_ASSERT( parent_key_record->has_private_key(), "Parent private key not found!" ); const private_key_type parent_private_key = parent_key_record->decrypt_private_key( password ); uint32_t child_key_index = account_record->last_child_key_index; private_key_type account_child_private_key; public_key_type account_child_public_key; address account_child_address; while( true ) { ++child_key_index; FC_ASSERT( child_key_index != 0, "Overflow!" ); account_child_private_key = get_account_child_key( parent_private_key, child_key_index ); account_child_public_key = account_child_private_key.get_public_key(); account_child_address = address( account_child_public_key ); owallet_key_record child_key_record = lookup_key( account_child_address ); if( child_key_record.valid() && child_key_record->has_private_key() ) continue; break; } account_record->last_child_key_index = child_key_index; key_data child_key; child_key.account_address = account_record->owner_address(); child_key.child_key_index = child_key_index; child_key.public_key = account_child_public_key; child_key.encrypt_private_key( password, account_child_private_key ); store_account( *account_record ); store_key( child_key ); return account_child_private_key; } FC_CAPTURE_AND_RETHROW( (account_name) ) }
public_key_type wallet_db::generate_new_account( const fc::sha512& password, const string& account_name ) { try { FC_ASSERT( is_open() ); owallet_account_record account_record = lookup_account( account_name ); FC_ASSERT( !account_record.valid(), "Wallet already contains an account with that name!" ); uint32_t key_index = get_last_wallet_child_key_index(); private_key_type owner_private_key, active_private_key; public_key_type owner_public_key, active_public_key; address owner_address, active_address; while( true ) { ++key_index; FC_ASSERT( key_index != 0, "Overflow!" ); owner_private_key = get_wallet_child_key( password, key_index ); owner_public_key = owner_private_key.get_public_key(); owner_address = address( owner_public_key ); account_record = lookup_account( owner_address ); if( account_record.valid() ) continue; owallet_key_record key_record = lookup_key( owner_address ); if( key_record.valid() && key_record->has_private_key() ) continue; active_private_key = get_account_child_key( owner_private_key, 0 ); active_public_key = active_private_key.get_public_key(); active_address = address( active_public_key ); account_record = lookup_account( active_address ); if( account_record.valid() ) continue; key_record = lookup_key( active_address ); if( key_record.valid() && key_record->has_private_key() ) continue; break; } key_data active_key; active_key.account_address = owner_address; active_key.public_key = active_public_key; active_key.encrypt_private_key( password, active_private_key ); key_data owner_key; owner_key.account_address = owner_address; owner_key.child_key_index = key_index; owner_key.public_key = owner_public_key; owner_key.encrypt_private_key( password, owner_private_key ); account_data account; account.name = account_name; account.owner_key = owner_public_key; account.set_active_key( blockchain::now(), active_public_key ); account.last_update = blockchain::now(); store_key( active_key ); set_last_wallet_child_key_index( key_index ); store_key( owner_key ); store_account( account ); return owner_public_key; } FC_CAPTURE_AND_RETHROW( (account_name) ) }