34 namespace graphene {
namespace wallet {
namespace detail {
39 static const char hd[] =
"0123456789abcdef";
42 result += hd[(x >> 0x1c) & 0x0f];
43 result += hd[(x >> 0x18) & 0x0f];
44 result += hd[(x >> 0x14) & 0x0f];
45 result += hd[(x >> 0x10) & 0x0f];
46 result += hd[(x >> 0x0c) & 0x0f];
47 result += hd[(x >> 0x08) & 0x0f];
48 result += hd[(x >> 0x04) & 0x0f];
49 result += hd[(x ) & 0x0f];
64 size_t i = 0, n = s.length();
69 bool preceded_by_whitespace =
false;
70 bool non_empty =
false;
76 case ' ':
case '\t':
case '\r':
case '\n':
case '\v':
case '\f':
77 preceded_by_whitespace =
true;
80 case 'a': c =
'A';
break;
81 case 'b': c =
'B';
break;
82 case 'c': c =
'C';
break;
83 case 'd': c =
'D';
break;
84 case 'e': c =
'E';
break;
85 case 'f': c =
'F';
break;
86 case 'g': c =
'G';
break;
87 case 'h': c =
'H';
break;
88 case 'i': c =
'I';
break;
89 case 'j': c =
'J';
break;
90 case 'k': c =
'K';
break;
91 case 'l': c =
'L';
break;
92 case 'm': c =
'M';
break;
93 case 'n': c =
'N';
break;
94 case 'o': c =
'O';
break;
95 case 'p': c =
'P';
break;
96 case 'q': c =
'Q';
break;
97 case 'r': c =
'R';
break;
98 case 's': c =
'S';
break;
99 case 't': c =
'T';
break;
100 case 'u': c =
'U';
break;
101 case 'v': c =
'V';
break;
102 case 'w': c =
'W';
break;
103 case 'x': c =
'X';
break;
104 case 'y': c =
'Y';
break;
105 case 'z': c =
'Z';
break;
110 if( preceded_by_whitespace && non_empty )
111 result.push_back(
' ');
113 preceded_by_whitespace =
false;
146 md.
from =
self.get_public_key( from );
158 md.
to =
self.get_public_key( to );
166 std::swap( md.
from, md.
to );
168 std::swap( md.
from, md.
to );
176 std::string clear_text;
182 "Memo is encrypted to a key ${to} or ${from} not in this wallet.",
183 (
"to", memo->
to)(
"from",memo->
from) );
184 if(
_keys.count(memo->
to) > 0 ) {
186 FC_ASSERT(my_key,
"Unable to recover private key to decrypt memo. Wallet may be corrupted.");
190 FC_ASSERT(my_key,
"Unable to recover private key to decrypt memo. Wallet may be corrupted.");
211 msg.
meta.
block = dynamic_props.head_block_number;
212 msg.
meta.
time = dynamic_props.time.to_iso_string() +
"Z";
235 if( !
message.signature.valid() )
return false;
240 if( !(
message.meta.memo_key == signer ) )
return false;
242 "Message was signed by contained key, but it doesn't belong to the contained account!" );
249 static string meta_extract(
const string& meta,
const string& key )
251 FC_ASSERT( meta.size() > key.size(),
"Key '${k}' not found!", (
"k",key) );
253 if( meta.substr( 0, key.size() ) == key && meta[key.size()] ==
'=' )
257 start = meta.find(
"\n" + key +
"=" );
258 FC_ASSERT( start != string::npos,
"Key '${k}' not found!", (
"k",key) );
261 start += key.size() + 1;
262 size_t lf = meta.find(
"\n", start );
263 if( lf == string::npos ) lf = meta.size();
264 return meta.substr( start, lf - start );
270 size_t begin_p =
message.find( ENC_HEADER );
271 FC_ASSERT( begin_p != string::npos,
"BEGIN MESSAGE line not found!" );
272 size_t meta_p =
message.find( ENC_META, begin_p );
273 FC_ASSERT( meta_p != string::npos,
"BEGIN META line not found!" );
274 FC_ASSERT( meta_p >= begin_p + ENC_HEADER.size() + 1,
"Missing message!?" );
275 size_t sig_p =
message.find( ENC_SIG, meta_p );
276 FC_ASSERT( sig_p != string::npos,
"BEGIN SIGNATURE line not found!" );
277 FC_ASSERT( sig_p >= meta_p + ENC_META.size(),
"Missing metadata?!" );
278 size_t end_p =
message.find( ENC_FOOTER, meta_p );
279 FC_ASSERT( end_p != string::npos,
"END MESSAGE line not found!" );
280 FC_ASSERT( end_p >= sig_p + ENC_SIG.size() + 1,
"Missing signature?!" );
282 msg.message =
message.substr( begin_p + ENC_HEADER.size(), meta_p - begin_p - ENC_HEADER.size() - 1 );
283 const string meta =
message.substr( meta_p + ENC_META.size(), sig_p - meta_p - ENC_META.size() );
284 const string sig =
message.substr( sig_p + ENC_SIG.size(), end_p - sig_p - ENC_SIG.size() - 1 );
286 msg.meta.account = meta_extract( meta,
"account" );
287 msg.meta.memo_key =
public_key_type( meta_extract( meta,
"memokey" ) );
288 msg.meta.block = boost::lexical_cast<uint32_t>( meta_extract( meta,
"block" ) );
289 msg.meta.time = meta_extract( meta,
"timestamp" );
308 tx.
set_expiration( now + parameters.maximum_time_until_expiration );
321 elog(
"Caught exception while broadcasting tx ${id}: ${e}",
323 FC_THROW(
"Caught exception while broadcasting tx" );
336 const vector<public_key_type>& signing_keys,
bool broadcast)
342 approving_key_set.insert(explicit_key);
353 auto oldest_transaction_record_iter =
354 _recently_generated_transactions.get<timestamp_index>().lower_bound(oldest_transaction_ids_to_track);
355 auto begin_iter = _recently_generated_transactions.get<timestamp_index>().begin();
356 _recently_generated_transactions.get<timestamp_index>().erase(begin_iter, oldest_transaction_record_iter);
358 uint32_t expiration_time_offset = 0;
368 auto iter = _recently_generated_transactions.find(this_transaction_id);
369 if (iter == _recently_generated_transactions.end())
372 recently_generated_transaction_record this_transaction_record;
373 this_transaction_record.generation_time = dyn_props.time;
374 this_transaction_record.transaction_id = this_transaction_id;
375 _recently_generated_transactions.insert(this_transaction_record);
380 ++expiration_time_offset;
391 elog(
"Caught exception while broadcasting tx ${id}: ${e}",
402 auto it =
_keys.find(
id);
413 if (active_keys.size() != 1)
414 FC_THROW(
"Expecting a simple authority with one active key");
425 if (!optional_private_key)
432 flat_set<public_key_type> all_keys_for_account;
433 std::vector<public_key_type> active_keys = account.
active.
get_keys();
434 std::vector<public_key_type> owner_keys = account.
owner.
get_keys();
435 std::copy(active_keys.begin(), active_keys.end(),
436 std::inserter(all_keys_for_account, all_keys_for_account.end()));
437 std::copy(owner_keys.begin(), owner_keys.end(),
438 std::inserter(all_keys_for_account, all_keys_for_account.end()));
441 _keys[wif_pub_key] = wif_key;
447 return all_keys_for_account.find(wif_pub_key) != all_keys_for_account.end();
466 bool erase_existing_sigs )
468 set<public_key_type> pks =
_remote_db->get_potential_signatures( tx );
469 flat_set<public_key_type> owned_keys;
470 owned_keys.reserve( pks.size() );
471 std::copy_if( pks.begin(), pks.end(),
472 std::inserter( owned_keys, owned_keys.end() ),
474 return _keys.find( pk ) != _keys.end();
477 if ( erase_existing_sigs )
480 return _remote_db->get_required_signatures( tx, owned_keys );