Skip to content

Commit

Permalink
adding wallet support for private messages
Browse files Browse the repository at this point in the history
  • Loading branch information
revflash committed May 6, 2016
1 parent 2d913a8 commit 449b88e
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 9 deletions.
12 changes: 6 additions & 6 deletions libraries/app/database_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1184,7 +1184,7 @@ state database_api::get_state( string path )const
}
}
} else if( part[1] == "recent-replies" ) {
auto replies = get_discussions_by_last_update( acnt, "", 80 );
auto replies = get_discussions_by_last_update( acnt, "", 50 );
edump((replies));
eacnt.recent_replies = vector<string>();
for( const auto& reply : replies ) {
Expand Down Expand Up @@ -1251,7 +1251,7 @@ state database_api::get_state( string path )const
_state.pow_queue = get_miner_queue();
}
else if( part[0] == "trending" && part[1].size() ) {
auto trending_disc = get_discussions_in_category_by_total_pending_payout( part[1], "", "", 50 );
auto trending_disc = get_discussions_in_category_by_total_pending_payout( part[1], "", "", 20 );

auto& didx = _state.discussion_idx[part[1]];
for( const auto& d : trending_disc ) {
Expand All @@ -1262,7 +1262,7 @@ state database_api::get_state( string path )const
}
}
else if( part[0] == "trending" || part[0] == "") {
auto trending_disc = get_discussions_by_total_pending_payout( "", "", 50 );
auto trending_disc = get_discussions_by_total_pending_payout( "", "", 20 );
auto& didx = _state.discussion_idx[""];
for( const auto& d : trending_disc ) {
auto key = d.author +"/" + d.permlink;
Expand All @@ -1284,7 +1284,7 @@ state database_api::get_state( string path )const
}
}
else if( part[0] == "maturing" ) {
auto trending_disc = get_discussions_in_category_by_cashout_time( part[1], "", "", 50 );
auto trending_disc = get_discussions_in_category_by_cashout_time( part[1], "", "", 20 );
auto& didx = _state.discussion_idx[part[1]];
for( const auto& d : trending_disc ) {
auto key = d.author +"/" + d.permlink;
Expand All @@ -1294,7 +1294,7 @@ state database_api::get_state( string path )const
}
}
else if( part[0] == "recent" && part[1] == "") {
auto trending_disc = get_discussions_by_last_update( "", "", 50 );
auto trending_disc = get_discussions_by_last_update( "", "", 20 );
auto& didx = _state.discussion_idx[""];
for( const auto& d : trending_disc ) {
auto key = d.author +"/" + d.permlink;
Expand All @@ -1303,7 +1303,7 @@ state database_api::get_state( string path )const
_state.content[key] = std::move(d);
}
} else if( part[0] == "recent" ) {
auto trending_disc = get_discussions_in_category_by_last_update( part[1], "", "", 50 );
auto trending_disc = get_discussions_in_category_by_last_update( part[1], "", "", 20 );
auto& didx = _state.discussion_idx[part[1]];
for( const auto& d : trending_disc ) {
auto key = d.author +"/" + d.permlink;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <boost/multi_index/composite_key.hpp>

#include <fc/thread/future.hpp>
#include <fc/api.hpp>

namespace steemit { namespace private_message {
using namespace chain;
Expand Down Expand Up @@ -72,6 +73,7 @@ struct message_body {
};



class message_object : public abstract_object<message_object> {
public:
static const uint8_t space_id = PRIVATE_MESSAGE_SPACE_ID;
Expand All @@ -82,10 +84,17 @@ class message_object : public abstract_object<message_object> {
public_key_type from_memo_key;
public_key_type to_memo_key;
fc::time_point sent_time; /// used as seed to secret generation
fc::time_point_sec receive_time; /// time received by blockchain
uint32_t checksum = 0;
vector<char> encrypted_message;
};

struct extended_message_object : public message_object {
extended_message_object(){}
extended_message_object( const message_object& o ):message_object(o){}
message_body message;
};

struct private_message_operation {
string from;
string to;
Expand Down Expand Up @@ -154,9 +163,30 @@ class private_message_plugin : public steemit::app::plugin
std::unique_ptr<detail::private_message_plugin_impl> my;
};

class private_message_api : public std::enable_shared_from_this<private_message_api> {
public:
private_message_api(app::application& a):_app(a){}
void on_api_startup(){}

/**
*
*/
vector<message_object> get_inbox( string to, time_point newest, uint16_t limit )const;
vector<message_object> get_outbox( string from, time_point newest, uint16_t limit )const;

private:
app::application& _app;
};



} } //steemit::private_message

FC_REFLECT_DERIVED( steemit::private_message::message_object, (graphene::db::object), (from)(to)(from_memo_key)(to_memo_key)(sent_time)(checksum)(encrypted_message) );
FC_API( steemit::private_message::private_message_api, (get_inbox)(get_outbox) );

FC_REFLECT( steemit::private_message::message_body, (thread_start)(subject)(body)(json_meta)(cc) );
FC_REFLECT_DERIVED( steemit::private_message::message_object, (graphene::db::object), (from)(to)(from_memo_key)(to_memo_key)(sent_time)(receive_time)(checksum)(encrypted_message) );
FC_REFLECT_DERIVED( steemit::private_message::extended_message_object, (steemit::private_message::message_object), (message) );

FC_REFLECT( steemit::private_message::private_message_operation, (from)(to)(from_memo_key)(to_memo_key)(sent_time)(checksum)(encrypted_message) );

Expand Down
30 changes: 30 additions & 0 deletions libraries/plugins/private_message/private_message_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,40 @@ void private_message_plugin::plugin_initialize(const boost::program_options::var
database().on_applied_operation.connect( [&]( const operation_object& b){ my->on_operation(b); } );
database().add_index< primary_index< private_message_index > >();

app().register_api_factory<private_message_api>("private_message_api");

typedef pair<string,string> pairstring;
LOAD_VALUE_SET(options, "pm-accounts", my->_tracked_accounts, pairstring);
}

vector<message_object> private_message_api::get_inbox( string to, time_point newest, uint16_t limit )const {
FC_ASSERT( limit <= 100 );
vector<message_object> result;
const auto& idx = database().get_index_type<private_message_index>().indices().get<by_to_date>();
auto itr = idx.lower_bound( std::make_tuple( to, newest ) );
while( itr != idx.end() && limit && itr->to == to ) {
result.push_back(*itr);
++itr;
--limit;
}

return result;
}

vector<message_object> private_message_api::get_outbox( string from, time_point newest, uint16_t limit )const {
FC_ASSERT( limit <= 100 );
vector<message_object> result;
const auto& idx = database().get_index_type<private_message_index>().indices().get<by_from_date>();

auto itr = idx.lower_bound( std::make_tuple( from, newest ) );
while( itr != idx.end() && limit && itr->from == from ) {
result.push_back(*itr);
++itr;
--limit;
}
return result;
}

void private_message_plugin::plugin_startup()
{
}
Expand Down
2 changes: 1 addition & 1 deletion libraries/wallet/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ else()
endif()

add_library( steemit_wallet wallet.cpp ${CMAKE_CURRENT_BINARY_DIR}/api_documentation.cpp ${HEADERS} )
target_link_libraries( steemit_wallet PRIVATE steemit_app graphene_net steemit_chain graphene_utilities fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
target_link_libraries( steemit_wallet PRIVATE steemit_app graphene_net steemit_chain graphene_utilities fc steemit_private_message ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
target_include_directories( graphene_db PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )

if(MSVC)
Expand Down
12 changes: 12 additions & 0 deletions libraries/wallet/include/steemit/wallet/wallet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#pragma once

#include <steemit/app/api.hpp>
#include <steemit/private_message/private_message_plugin.hpp>
#include <steemit/chain/steem_objects.hpp>

#include <graphene/utilities/key_conversion.hpp>
Expand All @@ -38,6 +39,7 @@ using namespace std;
namespace steemit { namespace wallet {

using steemit::app::discussion;
using namespace steemit::private_message;

typedef uint16_t transaction_handle_type;

Expand Down Expand Up @@ -661,6 +663,11 @@ class wallet_api
*/
annotated_signed_transaction post_comment( string author, string permlink, string parent_author, string parent_permlink, string title, string body, string json, bool broadcast );

annotated_signed_transaction send_private_message( string from, string to, string subject, string body, bool broadcast );
vector<extended_message_object> get_inbox( string account, fc::time_point newest, uint32_t limit );
vector<extended_message_object> get_outbox( string account, fc::time_point newest, uint32_t limit );
message_body try_decrypt_message( const message_object& mo );

/**
* Vote on a comment to be paid STEEM
*
Expand Down Expand Up @@ -763,6 +770,11 @@ FC_API( steemit::wallet::wallet_api,
(post_comment)
(vote)

// private message api
(send_private_message)
(get_inbox)
(get_outbox)

/// helper api
(get_prototype_operation)
(serialize_transaction)
Expand Down
96 changes: 95 additions & 1 deletion libraries/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,8 @@ class wallet_api_impl
: self( s ),
_remote_api( rapi ),
_remote_db( rapi->get_api_by_name("database_api")->as< database_api >() ),
_remote_net_broadcast( rapi->get_api_by_name("network_broadcast_api")->as< network_broadcast_api >() )
_remote_net_broadcast( rapi->get_api_by_name("network_broadcast_api")->as< network_broadcast_api >() ),
_remote_message_api( rapi->get_api_by_name("private_message_api")->as< private_message_api >() )
{
init_prototype_ops();

Expand Down Expand Up @@ -877,6 +878,7 @@ class wallet_api_impl
fc::api<login_api> _remote_api;
fc::api<database_api> _remote_db;
fc::api<network_broadcast_api> _remote_net_broadcast;
fc::api<private_message_api> _remote_message_api;
optional< fc::api<network_node_api> > _remote_net_node;

flat_map<string, operation> _prototype_ops;
Expand Down Expand Up @@ -1690,5 +1692,97 @@ annotated_signed_transaction wallet_api::get_transaction( transaction_id_type id
return my->_remote_db->get_transaction( id );
}

annotated_signed_transaction wallet_api::send_private_message( string from, string to, string subject, string body, bool broadcast ) {
FC_ASSERT( !is_locked(), "wallet must be unlocked to send a private message" );
auto from_account = get_account( from );
auto to_account = get_account( to );

custom_operation op;
op.required_auths.insert(from);
op.id = STEEMIT_PRIVATE_MESSAGE_COP_ID;


private_message_operation pmo;
pmo.from = from;
pmo.to = to;
pmo.sent_time = fc::time_point::now();
pmo.from_memo_key = from_account.memo_key;
pmo.to_memo_key = to_account.memo_key;

message_body message;
message.subject = subject;
message.body = body;

auto priv_key = wif_to_key( get_private_key( pmo.from_memo_key ) );
FC_ASSERT( priv_key, "unable to find private key for memo" );
auto shared_secret = priv_key->get_shared_secret( pmo.to_memo_key );
fc::sha512::encoder enc;
fc::raw::pack( enc, pmo.sent_time );
fc::raw::pack( enc, shared_secret );
auto encrypt_key = enc.result();
pmo.checksum = fc::sha256::hash( encrypt_key )._hash[0];

vector<char> plain_text = fc::raw::pack( message );
pmo.encrypted_message = fc::aes_encrypt( encrypt_key, plain_text );

signed_transaction tx;
tx.operations.push_back( op );
tx.validate();

return my->sign_transaction( tx, broadcast );
}
message_body wallet_api::try_decrypt_message( const message_object& mo ) {
message_body result;

fc::sha512 shared_secret;

auto it = my->_keys.find(mo.from_memo_key);
if( it == my->_keys.end() )
{
it = my->_keys.find(mo.to_memo_key);
if( it == my->_keys.end() )
return result;
auto priv_key = wif_to_key( it->second );
if( priv_key ) return result;
shared_secret = priv_key->get_shared_secret( mo.from_memo_key );
} else {
auto priv_key = wif_to_key( it->second );
if( priv_key ) return result;
shared_secret = priv_key->get_shared_secret( mo.to_memo_key );
}

fc::sha512::encoder enc;
fc::raw::pack( enc, mo.sent_time );
fc::raw::pack( enc, shared_secret );
auto encrypt_key = enc.result();

if( mo.checksum != fc::sha256::hash( encrypt_key )._hash[0] )
return result;

auto decrypt_data = fc::aes_decrypt( encrypt_key, mo.encrypted_message );
try {
return fc::raw::unpack<message_body>( decrypt_data );
} catch ( ... ) {
return result;
}
}

vector<extended_message_object> wallet_api::get_inbox( string account, fc::time_point newest, uint32_t limit ) {
FC_ASSERT( !is_locked() );
vector<extended_message_object> result;
auto remote_result = my->_remote_message_api->get_inbox( account, newest, limit );
for( const auto& item : remote_result ) {
result.emplace_back( item );
result.back().message = try_decrypt_message( item );
}
return result;
}

vector<extended_message_object> wallet_api::get_outbox( string account, fc::time_point newest, uint32_t limit ) {
FC_ASSERT( !is_locked() );
vector<extended_message_object> result;
return result;
}

} } // steemit::wallet

0 comments on commit 449b88e

Please sign in to comment.